{"record":{"id":"4764b6f414483dd1","repo":"NationalSecurityAgency/ghidra","slug":"need-even-number-of-ascii-chars-for-byte-stream","errorCode":null,"errorMessage":"need even-number of ascii chars for byte-stream: (offset: %08lx, %s, %ld)\\n","messagePattern":"need even-number of ascii chars for byte-stream: \\(offset: %08lx, (.+?), %ld\\)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"GPL/GnuDisassembler/src/gdis/c/disasm_1.c","lineNumber":376,"sourceCode":"\t\t\t}\n\t\t\telse {\n\t\t\t\tfprintf(stderr, \"exiting, no ASCII hex found\\n\");\n\t\t\t\treturn 0; // finished! #TODO\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif(strlen(byteString) > BYTE_BUFFER_SIZE*2) {\n\t\t\t\tfprintf(stderr, \"Max ascii string size is %d you provided: %lu chars. Exiting.\\n\", BYTE_BUFFER_SIZE*2,\n\t\t\t\t\t\tstrlen(byteString));\n\t\t\t\texit(-1);\n\t\t\t}\n\t\t\tstrncpy(byteStringBuffer, byteString, BYTE_BUFFER_SIZE*2);\n\t\t\tstdin_mode = 0; // break out of the while loop\n\t\t}\n\n\t\tint size = strlen(byteStringBuffer);\n\t\tif((size % 2) != 0){\n\t\t\tfprintf(stderr, \"need even-number of ascii chars for byte-stream: (offset: %08lx, %s, %ld)\\n\", offset, byteStringBuffer, strlen(byteStringBuffer));\n\t\t\texit(-1);\n\t\t}\n\n\t\tmemset(byteBuffer, 0x00, BYTE_BUFFER_SIZE);\n\n\t\t//\n\t\t// TODO:\n\t\t// check to make sure chars are only valid HEX.\n\t\t//\n\t\tint i, j;\n\t\tfor(i=j=0; (i < size) && (j < BYTE_BUFFER_SIZE); i+=2, j++){\n\t\t\ttmp[0] = byteStringBuffer[i];\n\t\t\ttmp[1] = byteStringBuffer[i+1];\n\t\t\ttmp[2] = 0;\n\t\t\tsscanf(tmp, \"%02X\", &byteValue);\n\t\t\tbyteBuffer[j] = (unsigned char)byteValue;\n\t\t}\n","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/GPL/GnuDisassembler/src/gdis/c/disasm_1.c#L358-L394","documentation":"gdis validation error: the ascii byte-string has an odd number of characters, so it cannot be decoded into whole bytes (each byte = 2 hex chars). The program prints the offset, the buffer, and its length, then calls exit(-1).","triggerScenarios":"Passing/piping a hex string whose length is odd, e.g. '9090' is fine but '90901' (5 chars) triggers it.","commonSituations":"A stray nibble from a copy-paste; a hex-dump tool that emits a partial final byte; truncation of the string at a non-even boundary.","solutions":["Make the hex string length even by removing the trailing nibble or padding with a leading '0'.","Validate `strlen(str) % 2 == 0` in the caller/wrapper before invoking gdis.","Regenerate the byte string from the original binary to avoid partial bytes.","Add a preflight check in your script that rejects odd-length input."],"exampleFix":"// before\n$ gdis ... 90901      // 5 chars -> odd\n\n// after\n$ gdis ... 9090         // drop stray nibble\n// or\n$ gdis ... 090901       // pad to even","handlingStrategy":"validation","validationCode":"size_t n = strlen(byteString);\nif (n % 2 != 0) {\n  fprintf(stderr, \"odd-length hex string (%zu)\\n\", n);\n  return 2;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate even length in the caller/wrapper.","Generate hex from raw bytes with a %02x formatter to avoid partial bytes.","Reject non-hex characters too (the source marks this as a TODO)."],"tags":["cli","disassembler","validation","hex","c"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}