Skip to content
This repository was archived by the owner on Jan 31, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/book/adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ The `Zend\Serializer\Adapter\PhpSerialize` adapter uses the built-in
[serialize()](http://php.net/serialize)/[unserialize()](http://php.net/unserialize)
functions, and is a good default adapter choice.

There are no configurable options for this adapter.
Available options include:

Option | Data Type | Default Value | Description
--------------------------- | ----------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------
unserialize_class_whitelist | `array` or `bool` | `true` | The allowed classes for unserialize(), see [unserialize()](http://php.net/unserialize) for more information. Only available on PHP 7.0 or higher.


## The IgBinary Adapter

Expand Down
46 changes: 45 additions & 1 deletion src/Adapter/PhpSerialize.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ class PhpSerialize extends AbstractAdapter
*/
private static $serializedFalse = null;

/**
* @var PhpSerializeOptions
*/
protected $options;

/**
* Constructor
*
* @param array|\Traversable|PhpSerializeOptions|null $options
*/
public function __construct($options = null)
{
Expand All @@ -35,6 +42,36 @@ public function __construct($options = null)
parent::__construct($options);
}

/**
* Set options
*
* @param array|\Traversable|PhpSerializeOptions $options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please import Traversable

* @return PhpSerialize
*/
public function setOptions($options)
{
if (! $options instanceof PhpSerializeOptions) {
$options = new PhpSerializeOptions($options);
}

$this->options = $options;
return $this;
}

/**
* Get options
*
* @return PhpSerializeOptions
*/
public function getOptions()
{
if ($this->options === null) {
$this->options = new PhpSerializeOptions();
}

return $this->options;
}

/**
* Serialize using serialize()
*
Expand Down Expand Up @@ -85,7 +122,14 @@ public function unserialize($serialized)
}

ErrorHandler::start(E_NOTICE);
$ret = unserialize($serialized);

if (PHP_MAJOR_VERSION >= 7) {
// the second parameter is only available on PHP 7.0 or higher
$ret = unserialize($serialized, ['allowed_classes' => $this->getOptions()->getUnserializeClassWhitelist()]);
} else {
$ret = unserialize($serialized);
}

$err = ErrorHandler::stop();
if ($ret === false) {
throw new Exception\RuntimeException('Unserialization failed', 0, $err);
Expand Down
52 changes: 52 additions & 0 deletions src/Adapter/PhpSerializeOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2015?

* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Serializer\Adapter;

use Zend\Json\Json as ZendJson;
use Zend\Serializer\Exception;

class PhpSerializeOptions extends AdapterOptions
{
/**
* The list of allowed classes for unserialization (PHP 7.0+)
* Possible values:
* Array of class names that are allowed to be unserialized
* or true if all classes should be allowed (behavior of pre PHP 7.0)
* or false if no classes should be allowed
*
* @var array|bool
*/
protected $unserializeClassWhitelist = true;

/**
* @param array|bool $unserializeClassWhitelist
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@param string[]|bool $unserializeClassWhitelist

*
* @return PhpSerializeOptions
*/
public function setUnserializeClassWhitelist($unserializeClassWhitelist)
{
if (($unserializeClassWhitelist !== true) && (PHP_MAJOR_VERSION < 7)) {
throw new Exception\InvalidArgumentException(
'Class whitelist for unserialize() is only available on PHP 7.0 or higher.'
);
}

$this->unserializeClassWhitelist = $unserializeClassWhitelist;
return $this;
}

/**
* @return array|bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@return string[]|bool

*/
public function getUnserializeClassWhitelist()
{
return $this->unserializeClassWhitelist;
}
}
45 changes: 45 additions & 0 deletions test/Adapter/PhpSerializeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,49 @@ public function testUnserializingInvalidStringRaisesException($string, $expected
$this->expectExceptionMessage($expected);
$this->adapter->unserialize($string);
}

public function testUnserializeNoWhitelistedClasses()
{
$value = 'O:8:"stdClass":0:{}';

$this->adapter->getOptions()->setUnserializeClassWhitelist(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail on PHP < 7


$data = $this->adapter->unserialize($value);

if (PHP_MAJOR_VERSION >= 7) {
$this->assertNotInstanceOf(\stdClass::class, $data);
$this->assertInstanceOf('__PHP_Incomplete_Class', $data);
} else {
// Pre PHP 7.0 the whitelist should have no effect
$this->assertInstanceOf(\stdClass::class, $data);
}
}

public function testUnserializeClassNotAllowed()
{
$value = 'O:8:"stdClass":0:{}';

$this->adapter->getOptions()->setUnserializeClassWhitelist([\My\Dummy::class]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail on PHP < 7


$data = $this->adapter->unserialize($value);

if (PHP_MAJOR_VERSION >= 7) {
$this->assertNotInstanceOf(\stdClass::class, $data);
$this->assertInstanceOf('__PHP_Incomplete_Class', $data);
} else {
// Pre PHP 7.0 the whitelist should have no effect
$this->assertInstanceOf(\stdClass::class, $data);
}
}

public function testUnserializeClassAllowed()
{
$value = 'O:8:"stdClass":0:{}';

$this->adapter->getOptions()->setUnserializeClassWhitelist([\stdClass::class]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail on PHP < 7


$data = $this->adapter->unserialize($value);
$this->assertInstanceOf(\stdClass::class, $data);
$this->assertNotInstanceOf('__PHP_Incomplete_Class', $data);
}
}