{"record":{"id":"b3dd2a3f55f64f51","repo":"gchq/CyberChef","slug":"unexpected-input-found","errorCode":null,"errorMessage":"Unexpected input found","messagePattern":"Unexpected input found","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/PHPDeserialize.mjs","lineNumber":91,"sourceCode":"                    if (char === until) {\n                        break;\n                    } else {\n                        result += char;\n                    }\n                }\n                return result;\n\n            }\n\n            /**\n             * Read characters from the input that must be equal to `expect`\n             * @param expect\n             * @returns {string}\n             */\n            function expect(expect) {\n                const result = read(expect.length);\n                if (result !== expect) {\n                    throw new OperationError(\"Unexpected input found\");\n                }\n                return result;\n            }\n\n            /**\n             * Helper function to handle deserialized arrays.\n             * @returns {Array}\n             */\n            function handleArray() {\n                const items = parseInt(readUntil(\":\"), 10) * 2;\n                expect(\"{\");\n                const result = [];\n                let isKey = true;\n                let lastItem = null;\n                for (let idx = 0; idx < items; idx++) {\n                    const item = handleInput();\n                    if (isKey) {\n                        lastItem = item;","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/PHPDeserialize.mjs#L73-L109","documentation":"The expect() helper reads N characters and checks them against an expected literal delimiter. This fires when the parsed structure has a delimiter or structural marker that does not match the PHP serialization grammar — e.g., a missing semicolon after a scalar, or a missing brace in an array.","triggerScenarios":"Malformed delimiters such as i:5} instead of i:5; (missing semicolon). Array body missing the opening brace: a:2:s:1:\"a\";i:1; instead of a:2:{s:1:\"a\";i:1;}. String element missing the closing '\";' delimiter pair.","commonSituations":"Hand-editing a serialized string and introducing a typo. Data corruption from transport or storage. Using a non-standard serialization variant that uses different delimiters.","solutions":["Compare the input against a reference serialization produced by PHP's serialize() to spot delimiter mismatches","Check that every scalar value ends with ';' and every array opens with '{' and closes with '}'","Validate that string elements follow the pattern s:N:\"<N chars>\";"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-check: verify basic delimiter structure\nfunction hasValidDelimiters(s) {\n  // Scalars should end with ';' and arrays with '{}'\n  const opens = (s.match(/\\{/g) || []).length;\n  const closes = (s.match(/\\}/g) || []).length;\n  return opens === closes;\n}\nif (!hasValidDelimiters(input)) {\n  throw new Error(\"Mismatched array braces in serialized data.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = chef.phpDeserialize(input, [true]);\n} catch (e) {\n  if (/Unexpected input/i.test(e.message)) {\n    console.error(\"Delimiter mismatch — compare against PHP serialize() output\");\n  } else { throw e; }\n}","preventionTips":["Compare the input against a reference output from PHP's serialize() to spot delimiter mismatches","Ensure every scalar ends with ';' and every array opens with '{' and closes with '}'"],"tags":["php","deserialization","parsing","data-integrity"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}