php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #50842 var_export/eval/unserialize of protected Object Member vars
Submitted: 2010-01-26 08:15 UTC Modified: 2010-01-26 12:04 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: lars dot schultz at toolpark dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.2.12 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lars dot schultz at toolpark dot com
New email:
PHP Version: OS:

 

 [2010-01-26 08:15 UTC] lars dot schultz at toolpark dot com
Description:
------------
When var_export() is used on a serialized-object-string, where the object has a protected member, and then use eval() or include() and then unserialize it again, it fails to do so.

The trouble seems to be that var_export() creates a string which escapes the chr(0) as \000 whereas eval() does not unescape this, when it should.

Protected Member:
http://dev01.toolpark.com/test/unserialize.protected.php

Public Member:
http://dev01.toolpark.com/test/unserialize.public.php

Reproduce code:
---------------
<?
	class Person {
		protected $name;
		
		public function __construct($name){
			$this->name = $name;
		}
	}
	
	$person = new Person('Lars Schultz');
	$serializedPerson = serialize($person);
	$exportedSerializePerson = var_export($serializedPerson,true);
	$evaluatedPerson = eval('return '.$exportedSerializePerson.';');
	$unserialized = unserialize($evaluatedPerson);
?>
<pre>
Original serialize:			<?	var_dump($serializedPerson); ?>
Exported serialize: 			<? var_dump($exportedSerializePerson); ?>
Evaluated Exported serialize: 		<? var_dump($evaluatedPerson); ?>
Unserialized Exported serialize:	<? var_dump($unserialized); ?>
<? print_r(error_get_last()) ?>

Expected result:
----------------
Original serialize:			string(51) "O:6:"Person":1:{s:7:"&#65533;*&#65533;name";s:12:"Lars Schultz";}"
Exported serialize: 			string(59) "'O:6:"Person":1:{s:7:"\000*\000name";s:12:"Lars Schultz";}'"
Evaluated Exported serialize: 		string(57) "O:6:"Person":1:{s:7:"\000*\000name";s:12:"Lars Schultz";}"
Unserialized Exported serialize:	object(Person)#2 (1) {
  ["name"]=>
  string(12) "Lars Schultz"
}

Actual result:
--------------
Original serialize:			string(51) "O:6:"Person":1:{s:7:"&#65533;*&#65533;name";s:12:"Lars Schultz";}"
Exported serialize: 			string(59) "'O:6:"Person":1:{s:7:"\000*\000name";s:12:"Lars Schultz";}'"
Evaluated Exported serialize: 		string(57) "O:6:"Person":1:{s:7:"\000*\000name";s:12:"Lars Schultz";}"
Unserialized Exported serialize:	bool(false)
Array
(
    [type] => 8
    [message] => unserialize() [function.unserialize]: Error at offset 28 of 57 bytes
    [file] => /srv/www/htdocs/test/unserialize.protected.php
    [line] => 19
)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-01-26 08:53 UTC] lars dot schultz at toolpark dot com
This is essentially the same problem, although not my use case.

var_dump(unserialize(eval('return '.var_export(serialize(chr(0)),true).';')));

Expected Result:
string(1) "[000]"

Actual Result:
bool(false)
 [2010-01-26 10:28 UTC] jani@php.net
Please try using this snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/

Your first case works fine using latest SVN. The other one..I don't think is a bug anyway.
 [2010-01-26 10:34 UTC] jani@php.net
That 2nd is bogus, you forget that var_export() returns PHP code. You're doing eval() on wrong stuff. Don't eval(). Refactor your code.
 [2010-01-26 11:01 UTC] lars dot schultz at toolpark dot com
thanks for checking it out.

I do not have the possibility to install a different version...but if you say it works, then we'll try again when we update to that version...it's not a critical to us at the moment, but it might become so in the future (our current solution is not to have protected members).

as for the 2nd one being bogus, i disagree;)

i shortened it down to this (no serialize).

var_export(), which should produce parseable (evaluatable) PHP-Code (as you said), creates a php-code-string, which i extend to a return statement, which I want to eval(). This is, though strange, correct.

Reproduce Code:
var_dump(eval('return '.var_export(chr(0),true).';'));

Expected Result:
string(1) "[000]"

Actual Result:
string(4) "\000"

It seems to me that var_export() is the culprit because it returns '\000' instead of "\000" (note the double-quotes) this only happens with chr(0) but works with chr(1). Could it be related to \000 being a string-termination character, which is why it is escaped by var_export but it fails to provide the correct double-quotes? Because the character \001 is not escaped by var_export...

<?
//creates correct code
var_dump(var_export(chr(1),true));

//creates incorrect code
var_dump(var_export(chr(0),true));

//evaluates correctly
var_dump(eval('return '.var_export(chr(1),true).';'));

//does not evaluate the chr(0) correctly because it's not wrapped by double-quotes
var_dump(eval('return '.var_export(chr(0),true).';'));

//is actually the same as the previous line
var_dump(eval('return \'\000\';'));

//as it should be created by var_export
var_dump(eval('return "\000";'));
?>
 [2010-01-26 11:14 UTC] derick@php.net
This works fine (5.1.7-dev, 5.2.13-dev and 5.3.2-dev):

derick@kossu:/tmp$ pe 5.1dev
derick@kossu:/tmp$ php test2.php
<pre>
Original serialize:                     string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Exported serialize:                     string(53) "'O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}'"
Evaluated Exported serialize:           string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Unserialized Exported serialize:        object(Person)#2 (1) {
  ["name:protected"]=>
  string(12) "Lars Schultz"
}
derick@kossu:/tmp$ pe 5.2dev
derick@kossu:/tmp$ php test2.php
<pre>
Original serialize:                     string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Exported serialize:                     string(75) "'O:6:"Person":1:{s:7:"' . "\0" . '*' . "\0" . 'name";s:12:"Lars Schultz";}'"
Evaluated Exported serialize:           string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Unserialized Exported serialize:        object(Person)#2 (1) {
  ["name:protected"]=>
  string(12) "Lars Schultz"
}
derick@kossu:/tmp$ pe 5.3dev
derick@kossu:/tmp$ php test2.php
<pre>
Original serialize:                     string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Exported serialize:                     string(75) "'O:6:"Person":1:{s:7:"' . "\0" . '*' . "\0" . 'name";s:12:"Lars Schultz";}'"
Evaluated Exported serialize:           string(51) "O:6:"Person":1:{s:7:"*name";s:12:"Lars Schultz";}"
Unserialized Exported serialize:        object(Person)#2 (1) {
  ["name":protected]=>
  string(12) "Lars Schultz"
}

 [2010-01-26 12:04 UTC] lars dot schultz at toolpark dot com
@derick: thanks for your effort.

Just checked the changelog and found your bugfix;) sorry,...somehow escaped my search for an existing bug. sorry.

http://bugs.php.net/bug.php?id=42272
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 03 19:01:35 2025 UTC