JPSpan_Unserializer_PHP::getClasses()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 10
rs 10
1
<?php declare(strict_types=1);
2
/**
3
 * @param mixed $className
4
 * @param mixed $getFailed
5
 */
6
7
//--------------------------------------------------------------------------------
8
/**
9
 * Unserialize call back function - checks that classes exist in the JPSpan map,
10
 * and includes them where needed. Throws an E_USER_ERROR if not found and dies
11
 * @param string $className classname (passed by PHP)
12
 * @param bool   $getFailed set to TRUE to get back the name of the last failed class
13
 * @return void|null void unless getFailed param is true
14
 */
15
function JPSpan_Unserializer_PHP_Callback($className, $getFailed = false)
16
{
17
    static $failedClass = null;
18
    if ($getFailed) {
19
        return $failedClass;
20
    } else {
21
        $className = \mb_strtolower($className);
22
        if (array_key_exists($className, $GLOBALS['_JPSPAN_UNSERIALIZER_MAP'])) {
23
            if (null !== $GLOBALS['_JPSPAN_UNSERIALIZER_MAP'][$className]) {
24
                require_once $GLOBALS['_JPSPAN_UNSERIALIZER_MAP'][$className];
25
            }
26
        } else {
27
            $failedClass = \mb_strtolower($className);
28
        }
29
    }
30
}
31
32
//---------------------------------------------------------------------------
33
34
/**
35
 * Unserializes PHP serialized strings
36
 */
37
class JPSpan_Unserializer_PHP
38
{
39
    /**
40
     * Unserialize a string into PHP data types. Changes the unserialize callback
41
     * function temporarily to JPSpan_Unserializer_PHP_Callback
42
     * @param mixed $data
43
     * @return mixed PHP data
44
     */
45
    public function unserialize($data)
46
    {
47
        if (is_string($data)) {
48
            if (!$this->validateClasses($data)) {
49
                return false;
50
            }
51
        } else {
52
            // It's not a string - give it back
53
            return $data;
54
        }
55
56
        $old_cb = ini_get('unserialize_callback_func');
57
        ini_set('unserialize_callback_func', 'JPSpan_Unserializer_PHP_Callback');
58
59
        $result = @unserialize(trim($data));
60
61
        ini_set('unserialize_callback_func', $old_cb);
62
63
        // Check for a serialized FALSE value
64
        if (false !== $result || 'b:0;' === $data) {
65
            return $result;
66
        }
67
68
        return $data;
69
    }
70
71
    /**
72
     * Validates unserialized data, checking the class names of serialized objects,
73
     * to prevent unexpected objects from being instantiated by PHP's unserialize()
74
     * @param mixed $data
75
     * @return bool TRUE if valid
76
     */
77
    public function validateClasses($data): bool
78
    {
79
        foreach ($this->getClasses($data) as $class) {
80
            if (!array_key_exists(mb_strtolower($class), $GLOBALS['_JPSPAN_UNSERIALIZER_MAP'])) {
81
                trigger_error('Illegal type: ' . \mb_strtolower($class), E_USER_ERROR);
82
83
                return false;
84
            }
85
        }
86
87
        return true;
88
    }
89
90
    /**
91
     * Parses the serialized string, extracting class names
92
     * @param serialized $string
0 ignored issues
show
Bug introduced by
The type serialized was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
     * @return array list of classes found
94
     * @internal param serialized $string string to parse
95
     */
96
    public function getClasses($string): array
97
    {
98
        // Stip any string representations (which might contain object syntax)
99
        $string = preg_replace('/s:[0-9]+:".*"/Us', '', $string);
100
101
        // Pull out the class named
102
        preg_match_all('/O:[0-9]+:"(.*)"/U', $string, $matches, PREG_PATTERN_ORDER);
103
104
        // Make sure names are unique (same object serialized twice)
105
        return array_unique($matches[1]);
106
    }
107
}
108