From f54724502a79d5489a6860022829128c8cb6fd24 Mon Sep 17 00:00:00 2001 From: Bruno Postle Date: Sat, 18 Jul 2026 18:04:46 +0100 Subject: [PATCH] Fix leak of IfcSpfLexer when read_from_stream returns early or throws tokens was a raw new'd pointer only freed at the very end of in_memory_file_storage::read_from_stream(). Every early return along the way (e.g. NO_HEADER / UNSUPPORTED_SCHEMA / no matching schema, which is almost any malformed input) skipped that delete and leaked it, along with whatever exceptions escaping readInstance() during the scan loop. Own it via a local unique_ptr for the duration of the function instead, so every exit path frees it. Found via fuzzing (see the ifcfuzz harness in src/ifcfuzz/). --- src/ifcparse/IfcParse.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index badbfa8ba7..bc113112e2 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1584,7 +1584,12 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead return; } - tokens = new IfcSpfLexer(s, logger()); + // Owned via RAII so that any early return or exception while scanning + // the file (e.g. a malformed header, see fuzzer-z6u) still frees the + // lexer instead of leaking it; `tokens` itself stays a raw pointer since + // it's read by in_memory_file_storage::load() during the scan below. + std::unique_ptr tokens_owner(new IfcSpfLexer(s, logger())); + tokens = tokens_owner.get(); std::vector schemas; @@ -1689,7 +1694,8 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead logger().Status("\rDone scanning file "); - delete tokens; + tokens_owner.reset(); + tokens = nullptr; if (good_ != file_open_status::SUCCESS) { return;