| @@ -236,16 +236,27 @@ | ||
| 236 | 236 | $parsed = []; |
| 237 | 237 | |
| 238 | 238 | // Handle different data formats |
| 239 | 239 | if (is_string($itineraryData)) { |
| 240 | - // Try to unserialize if it's serialized data | |
| 241 | - $unserialized = @unserialize($itineraryData); | |
| 240 | + // Itinerary meta is only ever expected to hold scalars/arrays. Forbid object | |
| 241 | + // instantiation so a crafted serialized payload in legacy post meta cannot trigger | |
| 242 | + // PHP object-injection / __destruct gadget chains during migration. | |
| 243 | + $unserialized = false; | |
| 244 | + if ($itineraryData !== '' && (str_starts_with($itineraryData, 'a:') || str_starts_with($itineraryData, 's:'))) { | |
| 245 | + set_error_handler(static function (): bool { return true; }); // suppress unserialize notices | |
| 246 | + try { | |
| 247 | + $unserialized = unserialize($itineraryData, ['allowed_classes' => false]); | |
| 248 | + } finally { | |
| 249 | + restore_error_handler(); | |
| 250 | + } | |
| 251 | + } | |
| 252 | + | |
| 242 | 253 | if ($unserialized !== false) { |
| 243 | 254 | $itineraryData = $unserialized; |
| 244 | 255 | } else { |
| 245 | - // Try to decode JSON | |
| 246 | - $decoded = @json_decode($itineraryData, true); | |
| 247 | - if ($decoded !== null) { | |
| 256 | + // Try to decode JSON. Don't suppress with @ — log decode errors so silent data loss is visible. | |
| 257 | + $decoded = json_decode($itineraryData, true); | |
| 258 | + if (json_last_error() === JSON_ERROR_NONE && $decoded !== null) { | |
| 248 | 259 | $itineraryData = $decoded; |
| 249 | 260 | } |
| 250 | 261 | } |
| 251 | 262 | } |