From aa1a8932854ce7fce271a32909ed8b31cb49968d Mon Sep 17 00:00:00 2001 From: Bruno Postle Date: Thu, 16 Jul 2026 22:42:58 +0100 Subject: [PATCH] IfcParse: don't abort when a string literal runs off the end of the file read_string() looped on stream_.peek() to scan a STEP string/binary literal, assuming peek() returns 0 at EOF. It actually throws std::out_of_range("peek at EOF"). A fuzzed file with a missing or relocated closing quote leaves the decoder with no terminator before it, so the loop runs the cursor past the end of the buffer and the exception comes up uncaught, aborting the process. Check stream_.eof() in the loop condition so an unterminated literal ends the scan at EOF instead of throwing, and log a SYN warning for the unterminated case (tracked via a "closed" flag so this doesn't fire for the pre-existing null-byte early exit). --- src/ifcparse/IfcCharacterDecoder.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ifcparse/IfcCharacterDecoder.cpp b/src/ifcparse/IfcCharacterDecoder.cpp index 019499a49e..ef226a365e 100644 --- a/src/ifcparse/IfcCharacterDecoder.cpp +++ b/src/ifcparse/IfcCharacterDecoder.cpp @@ -98,8 +98,9 @@ namespace { int codepage = 1; unsigned int hex = 0; unsigned int hex_count = 0; + bool closed = false; - while ((current_char = stream_.peek()) != 0) { + while (!stream_.eof() && (current_char = stream_.peek()) != 0) { if (EXPECTS_CHARACTER(parse_state)) { builder_.push_back(IfcUtil::convert_codepage(codepage, current_char + 0x80)); parse_state = 0; @@ -162,6 +163,7 @@ namespace { (current_char == '\\' && parse_state == FIRST_SOLIDUS) || (current_char == '\'' && parse_state == APOSTROPHE))) { if (parse_state == APOSTROPHE && current_char != '\'') { + closed = true; break; } throw IfcInvalidTokenException(stream_.tell(), current_char); @@ -171,6 +173,9 @@ namespace { } stream_.increment(); } + if (!closed && stream_.eof()) { + logger.Warning("SYN", 41, "Unterminated string literal at offset " + std::to_string(stream_.tell())); + } builder_.push_back('\''); if (mode == IfcParse::IfcCharacterDecoder::UTF8) {