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
 [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

Add a Patch

Pull Requests

Add a Pull Request

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-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 01:01:28 2024 UTC