edit pages
This commit is contained in:
21
old/wp-content/plugins/advanced-custom-fields-pro/vendor/polyfill-unserialize/LICENSE
vendored
Normal file
21
old/wp-content/plugins/advanced-custom-fields-pro/vendor/polyfill-unserialize/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2019 Denis Brumann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
namespace ACF\Brumann\Polyfill;
|
||||
|
||||
/**
|
||||
* 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 ACF\Brumann\Polyfill\Unserialize
|
||||
*/
|
||||
final class DisallowedClassesSubstitutor
|
||||
{
|
||||
const PATTERN_STRING = '#s:(\d+):(")#';
|
||||
const PATTERN_OBJECT = '#(^|;)O:\d+:"([^"]*)":(\d+):\{#';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $serialized;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $allowedClasses;
|
||||
|
||||
/**
|
||||
* Each array item consists of `[<offset-start>, <offset-end>]` and
|
||||
* marks start and end positions of items to be ignored.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
private $ignoreItems = array();
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
* @param string[] $allowedClasses
|
||||
*/
|
||||
public function __construct($serialized, array $allowedClasses)
|
||||
{
|
||||
$this->serialized = $serialized;
|
||||
$this->allowedClasses = $allowedClasses;
|
||||
|
||||
$this->buildIgnoreItems();
|
||||
$this->substituteObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSubstitutedSerialized()
|
||||
{
|
||||
return $this->serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies items to be ignored - like nested serializations in string literals.
|
||||
*/
|
||||
private function buildIgnoreItems()
|
||||
{
|
||||
$offset = 0;
|
||||
while (preg_match(self::PATTERN_STRING, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$length = (int)$matches[1][0]; // given length in serialized data (e.g. `s:123:"` --> 123)
|
||||
$start = $matches[2][1]; // offset position of quote character
|
||||
$end = $start + $length + 1;
|
||||
$offset = $end + 1;
|
||||
|
||||
// serialized string nested in outer serialized string
|
||||
if ($this->ignore($start, $end)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->ignoreItems[] = array($start, $end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes disallowed object class names and respects items to be ignored.
|
||||
*/
|
||||
private function substituteObjects()
|
||||
{
|
||||
$offset = 0;
|
||||
while (preg_match(self::PATTERN_OBJECT, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$completeMatch = (string)$matches[0][0];
|
||||
$completeLength = strlen($completeMatch);
|
||||
$start = $matches[0][1];
|
||||
$end = $start + $completeLength;
|
||||
$leftBorder = (string)$matches[1][0];
|
||||
$className = (string)$matches[2][0];
|
||||
$objectSize = (int)$matches[3][0];
|
||||
$offset = $end + 1;
|
||||
|
||||
// class name is actually allowed - skip this item
|
||||
if (in_array($className, $this->allowedClasses, true)) {
|
||||
continue;
|
||||
}
|
||||
// serialized object nested in outer serialized string
|
||||
if ($this->ignore($start, $end)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$incompleteItem = $this->sanitizeItem($className, $leftBorder, $objectSize);
|
||||
$incompleteItemLength = strlen($incompleteItem);
|
||||
$offset = $start + $incompleteItemLength + 1;
|
||||
|
||||
$this->replace($incompleteItem, $start, $end);
|
||||
$this->shift($end, $incompleteItemLength - $completeLength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces sanitized object class names in serialized data.
|
||||
*
|
||||
* @param string $replacement Sanitized object data
|
||||
* @param int $start Start offset in serialized data
|
||||
* @param int $end End offset in serialized data
|
||||
*/
|
||||
private function replace($replacement, $start, $end)
|
||||
{
|
||||
$this->serialized = substr($this->serialized, 0, $start)
|
||||
. $replacement . substr($this->serialized, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether given offset positions should be ignored.
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return bool
|
||||
*/
|
||||
private function ignore($start, $end)
|
||||
{
|
||||
foreach ($this->ignoreItems as $ignoreItem) {
|
||||
if ($ignoreItem[0] <= $start && $ignoreItem[1] >= $end) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts offset positions of ignore items by `$size`.
|
||||
* This is necessary whenever object class names have been
|
||||
* substituted which have a different length than before.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $size
|
||||
*/
|
||||
private function shift($offset, $size)
|
||||
{
|
||||
foreach ($this->ignoreItems as &$ignoreItem) {
|
||||
// only focus on items starting after given offset
|
||||
if ($ignoreItem[0] < $offset) {
|
||||
continue;
|
||||
}
|
||||
$ignoreItem[0] += $size;
|
||||
$ignoreItem[1] += $size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes object class item.
|
||||
*
|
||||
* @param string $className
|
||||
* @param int $leftBorder
|
||||
* @param int $objectSize
|
||||
* @return string
|
||||
*/
|
||||
private function sanitizeItem($className, $leftBorder, $objectSize)
|
||||
{
|
||||
return sprintf(
|
||||
'%sO:22:"__PHP_Incomplete_Class":%d:{s:27:"__PHP_Incomplete_Class_Name";%s',
|
||||
$leftBorder,
|
||||
$objectSize + 1, // size of object + 1 for added string
|
||||
\serialize($className)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace ACF\Brumann\Polyfill;
|
||||
|
||||
final class Unserialize
|
||||
{
|
||||
/**
|
||||
* @see https://secure.php.net/manual/en/function.unserialize.php
|
||||
*
|
||||
* @param string $serialized Serialized data
|
||||
* @param array $options Associative array containing options
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unserialize($serialized, array $options = array())
|
||||
{
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
return \unserialize($serialized, $options);
|
||||
}
|
||||
if (!array_key_exists('allowed_classes', $options) || true === $options['allowed_classes']) {
|
||||
return \unserialize($serialized);
|
||||
}
|
||||
$allowedClasses = $options['allowed_classes'];
|
||||
if (false === $allowedClasses) {
|
||||
$allowedClasses = array();
|
||||
}
|
||||
if (!is_array($allowedClasses)) {
|
||||
$allowedClasses = array();
|
||||
trigger_error(
|
||||
'unserialize(): allowed_classes option should be array or boolean',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
|
||||
$worker = new DisallowedClassesSubstitutor($serialized, $allowedClasses);
|
||||
|
||||
return \unserialize($worker->getSubstitutedSerialized());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user