Skip to content

Commit

Permalink
Merge pull request #15 from dbrumann/improvement/cleanup_codestyle
Browse files Browse the repository at this point in the history
Applies some code style changes.
  • Loading branch information
dbrumann authored Jul 24, 2020
2 parents 3822bc8 + a066718 commit 2b3fdcf
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 27 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,26 @@ Installation
You can install this package via composer:

```bash
composer require brumann/polyfill-unserialize "^1.0"
composer require brumann/polyfill-unserialize "^2.0"
```

Older versions
--------------

You can find the most recent 1.x versions in the branch with the same name:

* [dbrumann/polyfill-unserialize/tree/1.x](https://github.com/dbrumann/polyfill-unserialize/tree/1.x)

Upgrading
---------

Upgrading from 1.x to 2.0 should be seamless and require no changes to code
using the library. There are no changes to the public API, i.e. the names for
classes, methods and arguments as well as argument order and types remain the
same. Version 2.x uses a completely different approach for substituting
disallowed classes, which is why we chose to use a new major release to prevent
issues from unknown side effects in existing installations.

Known Issues
------------

Expand Down
3 changes: 0 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,5 @@
"minimum-stability": "stable",
"require": {
"php": "^5.3|^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
}
}
22 changes: 13 additions & 9 deletions src/Worker.php → src/DisallowedClassesSubstitutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
/**
* Worker implementation for identifying and skipping false-positives
* not to be substituted - like nested serializations in string literals.
*
* @internal This class should only be used by \Brumann\Polyfill\Unserialize
*/
final class Worker
final class DisallowedClassesSubstitutor
{
const PATTERN_STRING = '#s:(\d+):(")#';
const PATTERN_OBJECT = '#(^|;)O:\d+:"([^"]*)":(\d+):\{#';
Expand Down Expand Up @@ -36,14 +38,15 @@ public function __construct($serialized, array $allowedClasses)
{
$this->serialized = $serialized;
$this->allowedClasses = $allowedClasses;

$this->buildIgnoreItems();
$this->substituteObjects();
}

/**
* @return string
*/
public function get()
public function getSubstitutedSerialized()
{
return $this->serialized;
}
Expand All @@ -61,7 +64,7 @@ private function buildIgnoreItems()
$offset = $end + 1;

// serialized string nested in outer serialized string
if ($this->shallIgnore($start, $end)) {
if ($this->ignore($start, $end)) {
continue;
}

Expand Down Expand Up @@ -90,7 +93,7 @@ private function substituteObjects()
continue;
}
// serialized object nested in outer serialized string
if ($this->shallIgnore($start, $end)) {
if ($this->ignore($start, $end)) {
continue;
}

Expand All @@ -99,7 +102,7 @@ private function substituteObjects()
$offset = $start + $incompleteItemLength + 1;

$this->replace($incompleteItem, $start, $end);
$this->shiftIgnoreItems($end, $incompleteItemLength - $completeLength);
$this->shift($end, $incompleteItemLength - $completeLength);
}
}

Expand All @@ -110,26 +113,27 @@ private function substituteObjects()
* @param int $start Start offset in serialized data
* @param int $end End offset in serialized data
*/
protected function replace($replacement, $start, $end)
private function replace($replacement, $start, $end)
{
$this->serialized = substr($this->serialized, 0, $start)
. $replacement . substr($this->serialized, $end);
}

/**
* Whether given offset positions shall be ignored.
* Whether given offset positions should be ignored.
*
* @param int $start
* @param int $end
* @return bool
*/
private function shallIgnore($start, $end)
private function ignore($start, $end)
{
foreach ($this->ignoreItems as $ignoreItem) {
if ($ignoreItem[0] <= $start && $ignoreItem[1] >= $end) {
return true;
}
}

return false;
}

Expand All @@ -141,7 +145,7 @@ private function shallIgnore($start, $end)
* @param int $offset
* @param int $size
*/
private function shiftIgnoreItems($offset, $size)
private function shift($offset, $size)
{
foreach ($this->ignoreItems as &$ignoreItem) {
// only focus on items starting after given offset
Expand Down
5 changes: 3 additions & 2 deletions src/Unserialize.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public static function unserialize($serialized, array $options = array())
);
}

$worker = new Worker($serialized, $allowedClasses);
return \unserialize($worker->get());
$worker = new DisallowedClassesSubstitutor($serialized, $allowedClasses);

return \unserialize($worker->getSubstitutedSerialized());
}
}
20 changes: 8 additions & 12 deletions tests/UnserializeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,32 +232,28 @@ public function test_double_unserialize_double_serialized()
$this->assertInstanceOf('__PHP_Incomplete_Class', $unserialized);
}

/**
* @test
*/
public function nestedSerializedObjectInSerializedObjectCanBeDeserialized()
public function test_nested_serialized_object_in_serialized_object_can_be_deserialized()
{
$inner = new \stdClass();
$outer = new \stdClass();
$inner->value = serialize('inner');
$outer->value = serialize(array('item', $inner));
$serialized = serialize($outer);

$options = array('allowed_classes' => false);

$unserialized = Unserialize::unserialize($serialized, $options);
self::assertEquals($outer,$unserialized);

$this->assertEquals($outer,$unserialized);
}

/**
* @test
*/
public function stringContainingSerializedLiteralsCanBeDeserialized()
public function test_string_containing_serialized_literals_can_be_deserialized()
{
$string = 'A serialized object might look like `...;O:9:"ClassName":0:{};...` - watch out!';
$serialized = serialize($string);

$options = array('allowed_classes' => false);

$unserialized = Unserialize::unserialize($serialized, $options);
self::assertEquals($string, $unserialized);

$this->assertEquals($string, $unserialized);
}
}

0 comments on commit 2b3fdcf

Please sign in to comment.