PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.1
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.1
4.11.2 4.11.1 4.11.0 4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Traits / SerializeTrait.php
wp-staging / Framework / Traits Last commit date
ApplyFiltersTrait.php 1 week ago ArrayableTrait.php 1 week ago BatchSizeCalculateTrait.php 1 week ago BearerTokenTrait.php 1 week ago BenchmarkTrait.php 1 week ago BooleanTransientTrait.php 1 week ago DatabaseSearchReplaceTrait.php 1 week ago DbRowsGeneratorTrait.php 1 week ago DebugLogTrait.php 1 week ago DeveloperTimerTrait.php 1 week ago EndOfLinePlaceholderTrait.php 1 week ago EventLoggerTrait.php 1 week ago FileScanToCacheTrait.php 1 week ago FormatTrait.php 1 week ago HttpRequestTrait.php 1 week ago HydrateTrait.php 1 week ago I18nTrait.php 1 week ago IpResolverTrait.php 1 week ago JobResponseTrait.php 1 week ago MaintenanceTrait.php 7 months ago MemoryExhaustTrait.php 1 week ago MySQLRowsGeneratorTrait.php 1 week ago NoticesTrait.php 1 week ago PagesTrait.php 1 week ago PropertyConstructor.php 1 week ago RenameTmpDirectoryTrait.php 1 week ago ResourceTrait.php 1 week ago RestRequestTrait.php 1 week ago RestoreFileExclusionTrait.php 1 week ago SafeFileInfoTrait.php 1 week ago SerializeTrait.php 1 week ago SetTimeLimitTrait.php 1 week ago SlashTrait.php 1 week ago SqlCommentTrait.php 1 week ago TablePrefixValidator.php 5 months ago UrlTrait.php 1 week ago ValueGetterTrait.php 1 week ago WindowsOsTrait.php 1 week ago
SerializeTrait.php
170 lines
1 <?php
2
3 namespace WPStaging\Framework\Traits;
4
5 use __PHP_Incomplete_Class;
6
7 trait SerializeTrait
8 {
9
10
11
12
13
14
15
16 protected function safeMaybeUnserialize($data, array $allowedClasses = [], &$rejected = false, &$failedToParse = false)
17 {
18 $rejected = false;
19 $failedToParse = false;
20
21 if (!is_string($data) || !$this->isSerialized($data)) {
22 return $data;
23 }
24
25 $data = trim($data);
26 $value = $this->unserializeQuietly($data, $allowedClasses, $failedToParse);
27
28 if ($value === false && $failedToParse) {
29 $rejected = true;
30 return false;
31 }
32
33 if ($this->containsForbiddenClass($value)) {
34 $rejected = true;
35 return false;
36 }
37
38 return $value;
39 }
40
41
42
43
44
45
46
47 private function unserializeQuietly(string $data, array $allowedClasses, &$failed = false)
48 {
49 $failed = false;
50
51 set_error_handler(function () use (&$failed) {
52 $failed = true;
53 return true;
54 });
55
56 try {
57 return unserialize($data, ['allowed_classes' => $allowedClasses]);
58 } finally {
59 restore_error_handler();
60 }
61 }
62
63
64
65
66
67
68 protected function containsForbiddenClass($value, int $maxDepth = 256): bool
69 {
70 $pending = [[$value, 0]];
71
72 while ($pending !== []) {
73 list($current, $depth) = array_pop($pending);
74
75 if ($current instanceof __PHP_Incomplete_Class) {
76 return true;
77 }
78
79 if (is_object($current)) {
80 $current = (array)$current;
81 }
82
83 if (!is_array($current)) {
84 continue;
85 }
86
87 if ($depth >= $maxDepth) {
88 return true;
89 }
90
91 foreach ($current as $item) {
92 if (is_array($item) || is_object($item)) {
93 $pending[] = [$item, $depth + 1];
94 }
95 }
96 }
97
98 return false;
99 }
100
101
102
103
104
105 protected function isSerialized(string $data, bool $strict = true): bool
106 {
107 if (!is_string($data)) {
108 return false;
109 }
110
111 $data = trim($data);
112 if ($data === 'N;') {
113 return true;
114 }
115
116 if (strlen($data) < 4) {
117 return false;
118 }
119
120 if ($data[1] !== ':') {
121 return false;
122 }
123
124 if ($strict) {
125 $lastc = substr($data, -1);
126 if ($lastc !== ';' && $lastc !== '}') {
127 return false;
128 }
129 } else {
130 $semicolon = strpos($data, ';');
131 $brace = strpos($data, '}');
132 if ($semicolon === false && $brace === false) {
133 return false;
134 }
135
136 if ($semicolon !== false && $semicolon < 3) {
137 return false;
138 }
139
140 if ($brace !== false && $brace < 4) {
141 return false;
142 }
143 }
144
145 $token = $data[0];
146 switch ($token) {
147 case 's':
148 if ($strict) {
149 if ('"' !== substr($data, -2, 1)) {
150 return false;
151 }
152 } elseif (function_exists('str_contains') && !str_contains($data, '"') || strpos($data, '"') === false) {
153 return false;
154 }
155
156 case 'a':
157 case 'O':
158 case 'E':
159 return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
160 case 'b':
161 case 'i':
162 case 'd':
163 $end = $strict ? '$' : '';
164 return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
165 }
166
167 return false;
168 }
169 }
170