PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.2
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.2
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 3 days 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 3 days 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 3 days ago RestRequestTrait.php 1 week ago RestoreFileExclusionTrait.php 1 week ago SafeFileInfoTrait.php 1 week ago SerializeTrait.php 3 days ago SetTimeLimitTrait.php 1 week ago SlashTrait.php 1 week ago SqlCommentTrait.php 1 week ago TablePrefixValidator.php 5 months ago ThrottledResponseTrait.php 3 days ago UrlTrait.php 1 week ago ValueGetterTrait.php 1 week ago WindowsOsTrait.php 1 week ago WordPressOptionNameTrait.php 3 days ago
SerializeTrait.php
168 lines
1 <?php
2
3 namespace WPStaging\Framework\Traits;
4
5 trait SerializeTrait
6 {
7
8
9
10
11
12
13
14 protected function safeMaybeUnserialize($data, array $allowedClasses = [], &$rejected = false, &$failedToParse = false)
15 {
16 $rejected = false;
17 $failedToParse = false;
18
19 if (!is_string($data) || !$this->isSerialized($data)) {
20 return $data;
21 }
22
23 $data = trim($data);
24 $value = $this->unserializeQuietly($data, $allowedClasses, $failedToParse);
25
26 if ($value === false && $failedToParse) {
27 $rejected = true;
28 return false;
29 }
30
31 if ($this->containsForbiddenClass($value)) {
32 $rejected = true;
33 return false;
34 }
35
36 return $value;
37 }
38
39
40
41
42
43
44
45 private function unserializeQuietly(string $data, array $allowedClasses, &$failed = false)
46 {
47 $failed = false;
48
49 set_error_handler(function () use (&$failed) {
50 $failed = true;
51 return true;
52 });
53
54 try {
55 return unserialize($data, ['allowed_classes' => $allowedClasses]);
56 } finally {
57 restore_error_handler();
58 }
59 }
60
61
62
63
64
65
66 protected function containsForbiddenClass($value, int $maxDepth = 256): bool
67 {
68 $pending = [[$value, 0]];
69
70 while ($pending !== []) {
71 list($current, $depth) = array_pop($pending);
72
73 if ($current instanceof \__PHP_Incomplete_Class) {
74 return true;
75 }
76
77 if (is_object($current)) {
78 $current = (array)$current;
79 }
80
81 if (!is_array($current)) {
82 continue;
83 }
84
85 if ($depth >= $maxDepth) {
86 return true;
87 }
88
89 foreach ($current as $item) {
90 if (is_array($item) || is_object($item)) {
91 $pending[] = [$item, $depth + 1];
92 }
93 }
94 }
95
96 return false;
97 }
98
99
100
101
102
103 protected function isSerialized(string $data, bool $strict = true): bool
104 {
105 if (!is_string($data)) {
106 return false;
107 }
108
109 $data = trim($data);
110 if ($data === 'N;') {
111 return true;
112 }
113
114 if (strlen($data) < 4) {
115 return false;
116 }
117
118 if ($data[1] !== ':') {
119 return false;
120 }
121
122 if ($strict) {
123 $lastc = substr($data, -1);
124 if ($lastc !== ';' && $lastc !== '}') {
125 return false;
126 }
127 } else {
128 $semicolon = strpos($data, ';');
129 $brace = strpos($data, '}');
130 if ($semicolon === false && $brace === false) {
131 return false;
132 }
133
134 if ($semicolon !== false && $semicolon < 3) {
135 return false;
136 }
137
138 if ($brace !== false && $brace < 4) {
139 return false;
140 }
141 }
142
143 $token = $data[0];
144 switch ($token) {
145 case 's':
146 if ($strict) {
147 if ('"' !== substr($data, -2, 1)) {
148 return false;
149 }
150 } elseif (function_exists('str_contains') && !str_contains($data, '"') || strpos($data, '"') === false) {
151 return false;
152 }
153
154 case 'a':
155 case 'O':
156 case 'E':
157 return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
158 case 'b':
159 case 'i':
160 case 'd':
161 $end = $strict ? '$' : '';
162 return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
163 }
164
165 return false;
166 }
167 }
168