php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63481 Segmentation fault caused by unserialize()
Submitted: 2012-11-10 16:24 UTC Modified: 2013-10-04 14:23 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: aurelijus at astdev dot lt Assigned: mike
Status: Closed Package: Reproducible crash
PHP Version: 5.4.8 OS: RHEL 6 & Mac OS X 10.7.4
Private report: No CVE-ID:
 [2012-11-10 16:24 UTC] aurelijus at astdev dot lt
Description:
------------
Hey,
I can reproduce this on my local machine (Mac OS X 10.7.4) & our dev server (RHEL 
6) with PHP 5.4.* (including 5.4.9RC1). With 5.3.* it's fine.
We are trying to unserialize big \Serializable object and it causes the 
segmentation fault.
Code example bellow. Serialized object that causes the issue is attached.

PHP Configure:
./configure  --prefix=/opt/local --mandir=/opt/local/share/man --
infodir=/opt/local/share/info --program-suffix=54d --
includedir=/opt/local/include/php54d --libdir=/opt/local/lib/php54d --with-
config-file-path=/opt/local/etc/php54d --with-config-file-scan-
dir=/opt/local/var/db/php54d --disable-all --enable-bcmath --enable-ctype --
enable-dom --enable-fileinfo --enable-filter --enable-hash --enable-json --
enable-libxml --enable-pdo --enable-phar --enable-session --enable-simplexml --
enable-tokenizer --enable-xml --enable-xmlreader --enable-xmlwriter --with-
bz2=/opt/local --with-mhash=/opt/local --with-pcre-regex=/opt/local --with-
libxml-dir=/opt/local --with-zlib=/opt/local --without-pear --disable-cgi --
disable-fpm --enable-cli --with-libedit=/opt/local --enable-debug


Test script:
---------------
<?php

class Token implements \Serializable {
    public function serialize()
    {}

    public function unserialize($str)
    {
        $r = unserialize($str);
        unserialize($r[2]);
    }
}


$token = file_get_contents('string2.txt');
$obj = unserialize($token);
?>

Expected result:
----------------
It should not cause segmentation fault.

Actual result:
--------------
Segmentation fault.

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xffffffffffffffbf

VM Regions Near 0xffffffffffffffbf:
--> shared memory          00007fffffe00000-00007fffffe02000 [    8K] r-x/r-x 
SM=SHM  
    

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   php54d  0x000000010f75d994 zend_mm_check_ptr + 500
1   php54d  0x000000010f75feed _zend_mm_free_int + 109
2   php54d  0x000000010f761bed _efree + 125
3   php54d  0x000000010f7ea6eb zend_object_std_dtor + 283
4   php54d  0x000000010f7ead20 zend_objects_free_object_storage + 32
5   php54d  0x000000010f7f7dc5 zend_objects_store_free_object_storage + 325
6   php54d  0x000000010f78c977 shutdown_executor + 1335
7   php54d  0x000000010f7a9d1a zend_deactivate + 122
8   php54d  0x000000010f6eb681 php_request_shutdown + 1009
9   php54d  0x000000010f9834c8 do_cli + 7288
10  php54d  0x000000010f984415 main + 3461
11  php54d  0x000000010f3de304 start + 52

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-11-10 16:28 UTC] aurelijus at astdev dot lt
Serialized object:
http://aurelijus.eu/string2.txt
 [2012-11-10 17:10 UTC] laruence@php.net
I can reproduce it.
 [2012-11-10 17:10 UTC] laruence@php.net
-Assigned To: +Assigned To: laruence
 [2012-11-10 17:15 UTC] laruence@php.net
assigned by accident.
 [2012-11-10 17:15 UTC] laruence@php.net
-Assigned To: laruence +Assigned To:
 [2012-11-11 07:45 UTC] laruence@php.net
-Assigned To: +Assigned To: mike
 [2012-11-11 07:45 UTC] laruence@php.net
mike,do you have time to look at this?

seems due to the unserialize hash level.

I tried BG(seralize_lock)++ before calling zend_user_unserliaze, the problem 
gone.

but that break test #63481.

I am keeping dig this, but  it's  better if you can look at this
 [2012-11-11 08:41 UTC] mike@php.net
Please show the code, which does the 
serialisation.

Which PHP version did the serialisation?
Serialized strings are not portable 
between PHP versions, thea are just 
meant to be used as temporary 
representation.
 [2012-11-11 08:41 UTC] mike@php.net
-Status: Assigned +Status: Feedback
 [2012-11-11 16:52 UTC] aurelijus at astdev dot lt
-Status: Feedback +Status: Assigned
 [2012-11-11 16:52 UTC] aurelijus at astdev dot lt
Getting serialization code might be complicated, cause it's mostly 3rd pary 
framework code + DB, but I'll try.

String was generated with 5.4.8.
 [2012-11-12 02:51 UTC] laruence@php.net
did you generated the "serialize data" by two PHP process?


like:
1. serializer($xxx) then write to a temporary file like /tmp/xxx.txt
2. then in another PHP script, 
   $data[2]= file_get_contents("/tmp/xxx.txt");
  
then you got your serialization data by:
 $result = serialize($data);  ?

thanks
 [2012-11-12 12:29 UTC] aurelijus at astdev dot lt
It might have been another php process, it might have been the same.
1. generate $object.
2. serialize $object.
3. save $string in php session (under /tmp)
/* might be different process from here, it did not really matter, segmenatation 
fault happend in both cases */
4. get $string from session
5. dumped to a file for debugging (optional)
6. unserialize($string)
7. segmenatation fault.
 [2013-02-05 12:00 UTC] aurelijus at astdev dot lt
Hi,
Here is a reproducible serialization/unserialization code
https://gist.github.com/aurelijus/4713758
 [2013-02-06 09:54 UTC] mike@php.net
Looks like an excellent test case.

I suspect the problem is calling parent::(un)serialize() within a (un)serialize() 
callback.

I'll try to find out.
 [2013-02-06 10:07 UTC] mike@php.net
Yep, avoiding parent::serialize() helps:

diff --git a/serialize.php b/serialize.php
index 14ae4c8..4def326 100644
--- a/serialize.php
+++ b/serialize.php
@@ -58,13 +58,12 @@ class UsernamePasswordToken extends AbstractToken {
 
     public function serialize()
     {
-        return serialize(array($this->credentials, $this->providerKey, 
parent::serialize()));
+        return serialize(array($this->credentials, $this->providerKey, $this-
>roles));
     }
 
     public function unserialize($str)
     {
-        list($this->credentials, $this->providerKey, $parentStr) = 
unserialize($str);
-        parent::unserialize($parentStr);
+        list($this->credentials, $this->providerKey, $this->roles) = 
unserialize($str);
     }
 }
 [2013-03-08 15:44 UTC] zach dot quintana at gmail dot com
I'm also experiencing a similar bug, but will unserializing a class that doesn't 
implement serializable. Need the code?
 [2013-06-06 09:57 UTC] arjen at react dot com
I believe these are different issues, the backtrace is quite different.

Got the following results using php-5.4.15 from php.net:

Original report: https://gist.github.com/anonymous/5720457
Backtrace of https://gist.github.com/aurelijus/4713758: 
https://gist.github.com/anonymous/5720464

I tried reducing the original testcase, got a segfault but again the backtrace is quite different.

Testscript http://3v4l.org/3WCpP (crashes >= 5.4.0)
Backtrace at https://gist.github.com/anonymous/5720491

Should I create a seperate issue for it?
 [2013-07-29 18:11 UTC] mike@php.net
Yes, please. I already have a possible fix for the second issue.
 [2013-08-19 22:13 UTC] mike@php.net
See bug #65481
 [2013-08-30 09:04 UTC] arjen at react dot com
Thanx!

The testcase in the original bugreport by aurelijus at astdev dot lt is also 
fixed on 5.4.20, don't know by which commit.

Create new issue for calling 'parent::serialize()' issue, which still crashes: 
https://bugs.php.net/bug.php?id=65591

This issues can be closed.
 [2013-10-04 14:23 UTC] mike@php.net
-Status: Assigned +Status: Closed
 [2013-10-04 14:23 UTC] mike@php.net
Thank you for your bug report. This issue has already been fixed
in the latest released version of PHP, which you can download at 
http://www.php.net/downloads.php


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Mon Apr 21 02:02:11 2014 UTC