From 9ebaa8a377f3adaee93e4c0b6c4717b674ef2cd3 Mon Sep 17 00:00:00 2001 From: saumya Date: Sun, 12 Apr 2026 20:53:01 +0530 Subject: [PATCH 01/11] odb: fix segfault on invalid path in read_3dbx Add explicit file existence checks in ThreeDBlox::readDbx and ThreeDBlox::readDbv before parsing. Previously, when a non-existent path was passed (directly or via a header include), execution could continue past the failed open, producing partially-initialized ChipletDef data that caused a segfault in dbBlock::create via _dbBlock::initialize -> dbModule::create -> _dbDatabase::getLogger(). Also guard dbBlock::create against a null tech pointer to prevent a secondary crash when a chip has no associated technology. Add regression test read_3dbx-fail covering: - main 3dbx file does not exist - main file exists but references a non-existent include Fixes #10082 echo "Message file created" Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 8 ++++++++ src/odb/src/db/dbBlock.cpp | 4 +++- src/odb/test/BUILD | 2 ++ src/odb/test/CMakeLists.txt | 1 + src/odb/test/data/fail.3dbx | 9 +++++++++ src/odb/test/read_3dbx-fail.ok | 3 +++ src/odb/test/read_3dbx-fail.tcl | 22 ++++++++++++++++++++++ 7 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/odb/test/data/fail.3dbx create mode 100644 src/odb/test/read_3dbx-fail.ok create mode 100644 src/odb/test/read_3dbx-fail.tcl diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index 5c10e56a4f6..8b30030469d 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -57,6 +57,10 @@ ThreeDBlox::ThreeDBlox(utl::Logger* logger, odb::dbDatabase* db, sta::Sta* sta) void ThreeDBlox::readDbv(const std::string& dbv_file) { + if (!std::filesystem::exists(dbv_file)) { + logger_->error( + utl::ODB, 541, "3DBV file does not exist: {}", dbv_file); + } read_files_.insert(std::filesystem::absolute(dbv_file).string()); DbvParser parser(logger_); DbvData data = parser.parseFile(dbv_file); @@ -174,6 +178,10 @@ void ThreeDBlox::buildChipNetsFromVerilog(dbChip* chip, const DbxData& data) void ThreeDBlox::readDbx(const std::string& dbx_file) { + if (!std::filesystem::exists(dbx_file)) { + logger_->error( + utl::ODB, 542, "3DBX file does not exist: {}", dbx_file); + } read_files_.insert(std::filesystem::absolute(dbx_file).string()); DbxParser parser(logger_); DbxData data = parser.parseFile(dbx_file); diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index b0ec3e19ac9..bdfaf168ec4 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -2998,7 +2998,9 @@ dbBlock* dbBlock::create(dbChip* chip_, const char* name_, char hier_delimiter_) _dbBlock* top = chip->block_tbl_->create(); top->initialize(chip, nullptr, name_, hier_delimiter_); chip->top_ = top->getOID(); - top->dbu_per_micron_ = chip_->getTech()->getDbUnitsPerMicron(); + if (chip_->getTech() != nullptr) { + top->dbu_per_micron_ = chip_->getTech()->getDbUnitsPerMicron(); + } return (dbBlock*) top; } diff --git a/src/odb/test/BUILD b/src/odb/test/BUILD index 874267d8863..7543730f946 100644 --- a/src/odb/test/BUILD +++ b/src/odb/test/BUILD @@ -186,6 +186,7 @@ COMPULSORY_TESTS = [ "read_abstract_lef", "read_3dbv", "read_3dbx", + "read_3dbx-fail", "read_db", "read_def", "read_def58", @@ -283,6 +284,7 @@ filegroup( "data/design58.def", "data/example.3dbv", "data/example.3dbx", + "data/fail.3dbx", "data/example.bmap", "data/example1.bmap", "data/example2.bmap", diff --git a/src/odb/test/CMakeLists.txt b/src/odb/test/CMakeLists.txt index dd1ceda26d6..90b859a814f 100644 --- a/src/odb/test/CMakeLists.txt +++ b/src/odb/test/CMakeLists.txt @@ -42,6 +42,7 @@ or_integration_tests( read_abstract_lef read_3dbv read_3dbx + read_3dbx-fail read_db read_def read_def58 diff --git a/src/odb/test/data/fail.3dbx b/src/odb/test/data/fail.3dbx new file mode 100644 index 00000000000..9c5afcb13ad --- /dev/null +++ b/src/odb/test/data/fail.3dbx @@ -0,0 +1,9 @@ +Header: + version: "1.0" + unit: "micron" + precision: 2000 + include: + - nonexistent_include.3dbv + +Design: + name: "TestDesign" diff --git a/src/odb/test/read_3dbx-fail.ok b/src/odb/test/read_3dbx-fail.ok new file mode 100644 index 00000000000..f2ce18f9708 --- /dev/null +++ b/src/odb/test/read_3dbx-fail.ok @@ -0,0 +1,3 @@ +Caught expected error: main file not found +Caught expected error: include file not found +pass diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl new file mode 100644 index 00000000000..4c3ae7dc07a --- /dev/null +++ b/src/odb/test/read_3dbx-fail.tcl @@ -0,0 +1,22 @@ +source "helpers.tcl" + +# Test that read_3dbx gives a proper error for a non-existent file +# rather than segfaulting (regression test for issue #10082) + +# Test 1: Main file does not exist +if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { + puts "Caught expected error: main file not found" +} else { + puts "FAIL: Expected an error for non-existent main file" + exit 1 +} + +# Test 2: Main file exists but references a non-existent include +if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { + puts "Caught expected error: include file not found" +} else { + puts "FAIL: Expected an error for non-existent include file" + exit 1 +} + +puts "pass" From f8a4b1dab6df145f2626cf01459160e35e040f6c Mon Sep 17 00:00:00 2001 From: saumya Date: Sun, 12 Apr 2026 21:17:28 +0530 Subject: [PATCH 02/11] odb: address copilot reviewer feedback on read_3dbx segfault fix - Use std::error_code overloads for std::filesystem::exists in readDbx and readDbv to handle permission errors or bad paths - Fix duplicate error ID: readDbx check changed from 542 to 556 (542 was already used for bump net bterm error at line 949) - Add else-if fallback in dbBlock::create to guard dbu_per_micron_ when chip has no associated technology - Strengthen read_3dbx-fail test to assert err_msg contains the expected substring not just any error Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 8 +++++--- src/odb/src/db/dbBlock.cpp | 2 ++ src/odb/test/read_3dbx-fail.tcl | 8 ++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index 8b30030469d..8935929cd66 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -57,7 +57,8 @@ ThreeDBlox::ThreeDBlox(utl::Logger* logger, odb::dbDatabase* db, sta::Sta* sta) void ThreeDBlox::readDbv(const std::string& dbv_file) { - if (!std::filesystem::exists(dbv_file)) { + std::error_code ec; + if (!std::filesystem::exists(dbv_file, ec) || ec) { logger_->error( utl::ODB, 541, "3DBV file does not exist: {}", dbv_file); } @@ -178,9 +179,10 @@ void ThreeDBlox::buildChipNetsFromVerilog(dbChip* chip, const DbxData& data) void ThreeDBlox::readDbx(const std::string& dbx_file) { - if (!std::filesystem::exists(dbx_file)) { + std::error_code ec; + if (!std::filesystem::exists(dbx_file, ec) || ec) { logger_->error( - utl::ODB, 542, "3DBX file does not exist: {}", dbx_file); + utl::ODB, 556, "3DBX file does not exist: {}", dbx_file); } read_files_.insert(std::filesystem::absolute(dbx_file).string()); DbxParser parser(logger_); diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index bdfaf168ec4..8bae19c780a 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -3000,6 +3000,8 @@ dbBlock* dbBlock::create(dbChip* chip_, const char* name_, char hier_delimiter_) chip->top_ = top->getOID(); if (chip_->getTech() != nullptr) { top->dbu_per_micron_ = chip_->getTech()->getDbUnitsPerMicron(); + } else if (top->dbu_per_micron_ <= 0) { + top->dbu_per_micron_ = 1; } return (dbBlock*) top; } diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index 4c3ae7dc07a..3f2b9a3e13d 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -5,6 +5,10 @@ source "helpers.tcl" # Test 1: Main file does not exist if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { + if { [string first "does not exist" $err_msg] < 0 } { + puts "FAIL: Wrong error for missing main file: $err_msg" + exit 1 + } puts "Caught expected error: main file not found" } else { puts "FAIL: Expected an error for non-existent main file" @@ -13,6 +17,10 @@ if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { # Test 2: Main file exists but references a non-existent include if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { + if { [string first "does not exist" $err_msg] < 0 } { + puts "FAIL: Wrong error for missing include file: $err_msg" + exit 1 + } puts "Caught expected error: include file not found" } else { puts "FAIL: Expected an error for non-existent include file" From 01e13dfe80e195a2be683b559b7134bc1c022e63 Mon Sep 17 00:00:00 2001 From: saumya Date: Mon, 13 Apr 2026 00:05:40 +0530 Subject: [PATCH 03/11] odb: fix segfault when DEF file referenced in 3DBV is missing The actual crash reported in #10082 occurs when a chiplet's external DEF file does not exist: defin::createBlock does fopen, fails, emits a warning and returns false; readChip then destroys the chip and returns; but createChiplet continues using the now-dangling chip pointer, causing a segfault on chip->setWidth() etc. Add a std::filesystem::exists check (non-throwing error_code overload) in createChiplet before calling def_reader.readChip, so a proper error is raised before any chip is created or destroyed. Also extend the read_3dbx-fail regression test with a third case that exercises read_3dbv with a chiplet referencing a nonexistent DEF file. Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 7 +++++++ src/odb/test/BUILD | 1 + src/odb/test/data/fail_def.3dbv | 10 ++++++++++ src/odb/test/read_3dbx-fail.ok | 1 + src/odb/test/read_3dbx-fail.tcl | 12 ++++++++++++ 5 files changed, 31 insertions(+) create mode 100644 src/odb/test/data/fail_def.3dbv diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index 8935929cd66..de933c78644 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -464,6 +464,13 @@ void ThreeDBlox::createChiplet(const ChipletDef& chiplet) // Read DEF file if (!chiplet.external.def_file.empty()) { + std::error_code ec; + if (!std::filesystem::exists(chiplet.external.def_file, ec) || ec) { + logger_->error(utl::ODB, + 557, + "DEF file does not exist: {}", + chiplet.external.def_file); + } odb::defin def_reader(db_, logger_, odb::defin::DEFAULT); std::vector search_libs; for (odb::dbLib* lib : db_->getLibs()) { diff --git a/src/odb/test/BUILD b/src/odb/test/BUILD index 7543730f946..3c4aadf98ab 100644 --- a/src/odb/test/BUILD +++ b/src/odb/test/BUILD @@ -285,6 +285,7 @@ filegroup( "data/example.3dbv", "data/example.3dbx", "data/fail.3dbx", + "data/fail_def.3dbv", "data/example.bmap", "data/example1.bmap", "data/example2.bmap", diff --git a/src/odb/test/data/fail_def.3dbv b/src/odb/test/data/fail_def.3dbv new file mode 100644 index 00000000000..0f091e27079 --- /dev/null +++ b/src/odb/test/data/fail_def.3dbv @@ -0,0 +1,10 @@ +Header: + version: "1.0" + unit: "micron" + precision: 2000 + +ChipletDef: + TestChiplet: + type: die + external: + DEF_file: nonexistent.def diff --git a/src/odb/test/read_3dbx-fail.ok b/src/odb/test/read_3dbx-fail.ok index f2ce18f9708..e2e839840a1 100644 --- a/src/odb/test/read_3dbx-fail.ok +++ b/src/odb/test/read_3dbx-fail.ok @@ -1,3 +1,4 @@ Caught expected error: main file not found Caught expected error: include file not found +Caught expected error: DEF file not found pass diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index 3f2b9a3e13d..7af3d155383 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -27,4 +27,16 @@ if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { exit 1 } +# Test 3: 3DBV chiplet references a non-existent DEF file +if { [catch {read_3dbv "data/fail_def.3dbv"} err_msg] } { + if { [string first "does not exist" $err_msg] < 0 } { + puts "FAIL: Wrong error for missing DEF file: $err_msg" + exit 1 + } + puts "Caught expected error: DEF file not found" +} else { + puts "FAIL: Expected an error for non-existent DEF file" + exit 1 +} + puts "pass" From 751493ebbbd87a35cea6390101823cf97338446a Mon Sep 17 00:00:00 2001 From: saumya Date: Wed, 15 Apr 2026 19:26:35 +0530 Subject: [PATCH 04/11] odb: address maintainer feedback on read_3dbx segfault fix - Remove redundant filesystem::exists checks in readDbv/readDbx; DbvParser::parseFile and DbxParser::parseFile already call logError (-> logger_->error) when ifstream fails to open the file - In dbBlock::create, use chip_->getDatabase()->getDbuPerMicron() as the fallback dbu_per_micron when tech is null, instead of hardcoding 1 - Update regression test to match actual parser error message ("Cannot open file") for missing 3DBX/3DBV files Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 10 ---------- src/odb/src/db/dbBlock.cpp | 4 ++-- src/odb/test/read_3dbx-fail.tcl | 4 ++-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index de933c78644..685578c1ed4 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -57,11 +57,6 @@ ThreeDBlox::ThreeDBlox(utl::Logger* logger, odb::dbDatabase* db, sta::Sta* sta) void ThreeDBlox::readDbv(const std::string& dbv_file) { - std::error_code ec; - if (!std::filesystem::exists(dbv_file, ec) || ec) { - logger_->error( - utl::ODB, 541, "3DBV file does not exist: {}", dbv_file); - } read_files_.insert(std::filesystem::absolute(dbv_file).string()); DbvParser parser(logger_); DbvData data = parser.parseFile(dbv_file); @@ -179,11 +174,6 @@ void ThreeDBlox::buildChipNetsFromVerilog(dbChip* chip, const DbxData& data) void ThreeDBlox::readDbx(const std::string& dbx_file) { - std::error_code ec; - if (!std::filesystem::exists(dbx_file, ec) || ec) { - logger_->error( - utl::ODB, 556, "3DBX file does not exist: {}", dbx_file); - } read_files_.insert(std::filesystem::absolute(dbx_file).string()); DbxParser parser(logger_); DbxData data = parser.parseFile(dbx_file); diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index 8bae19c780a..a7165f39a72 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -3000,8 +3000,8 @@ dbBlock* dbBlock::create(dbChip* chip_, const char* name_, char hier_delimiter_) chip->top_ = top->getOID(); if (chip_->getTech() != nullptr) { top->dbu_per_micron_ = chip_->getTech()->getDbUnitsPerMicron(); - } else if (top->dbu_per_micron_ <= 0) { - top->dbu_per_micron_ = 1; + } else { + top->dbu_per_micron_ = chip_->getDatabase()->getDbuPerMicron(); } return (dbBlock*) top; } diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index 7af3d155383..c3721860384 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -5,7 +5,7 @@ source "helpers.tcl" # Test 1: Main file does not exist if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { - if { [string first "does not exist" $err_msg] < 0 } { + if { [string first "Cannot open file" $err_msg] < 0 } { puts "FAIL: Wrong error for missing main file: $err_msg" exit 1 } @@ -17,7 +17,7 @@ if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { # Test 2: Main file exists but references a non-existent include if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { - if { [string first "does not exist" $err_msg] < 0 } { + if { [string first "Cannot open file" $err_msg] < 0 } { puts "FAIL: Wrong error for missing include file: $err_msg" exit 1 } From 116429113734a28bc6fa8edf5c90e9e80a07049d Mon Sep 17 00:00:00 2001 From: saumya Date: Wed, 15 Apr 2026 20:39:00 +0530 Subject: [PATCH 05/11] odb: address feedback on read_3dbx segfault fix - Simplify dbBlock::create to use chip_->getDb()->getDbuPerMicron() directly, replacing the if/else tech null check as suggested by maintainer - Add missing #include for std::error_code per clang-tidy - Fix alphabetical ordering of data files in Bazel BUILD regression_resources Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 1 + src/odb/src/db/dbBlock.cpp | 6 +----- src/odb/test/BUILD | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index 685578c1ed4..f05990211bf 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index a7165f39a72..11ef56a60f0 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -2998,11 +2998,7 @@ dbBlock* dbBlock::create(dbChip* chip_, const char* name_, char hier_delimiter_) _dbBlock* top = chip->block_tbl_->create(); top->initialize(chip, nullptr, name_, hier_delimiter_); chip->top_ = top->getOID(); - if (chip_->getTech() != nullptr) { - top->dbu_per_micron_ = chip_->getTech()->getDbUnitsPerMicron(); - } else { - top->dbu_per_micron_ = chip_->getDatabase()->getDbuPerMicron(); - } + top->dbu_per_micron_ = chip_->getDb()->getDbuPerMicron(); return (dbBlock*) top; } diff --git a/src/odb/test/BUILD b/src/odb/test/BUILD index 3c4aadf98ab..784a5c90dc9 100644 --- a/src/odb/test/BUILD +++ b/src/odb/test/BUILD @@ -284,13 +284,13 @@ filegroup( "data/design58.def", "data/example.3dbv", "data/example.3dbx", - "data/fail.3dbx", - "data/fail_def.3dbv", "data/example.bmap", "data/example1.bmap", "data/example2.bmap", "data/example3.bmap", "data/example4.bmap", + "data/fail.3dbx", + "data/fail_def.3dbv", "data/floorplan_initialize.def", "data/floorplan_initialize.v", "data/floorplan_initialize2.def", From 411554dbb721e1c9a55863996d8632e12fad9b47 Mon Sep 17 00:00:00 2001 From: saumya Date: Thu, 16 Apr 2026 19:57:11 +0530 Subject: [PATCH 06/11] odb: address feedback on read_3dbx segfault fix - Split DEF file check in createChiplet: ODB-0558 for filesystem access errors (e.g. permissions), ODB-0557 for file-not-found, so the error message is actionable in both cases - Update regression test assertions to match actual thrown error IDs: ORD-0072 for missing main file (Tcl proc catches before C++ layer), ODB-0521 for missing include (BaseParser::logError), ODB-0557 for missing DEF file (createChiplet check) Signed-off-by: saumya --- src/odb/src/3dblox/3dblox.cpp | 11 ++++++++++- src/odb/test/read_3dbx-fail.tcl | 12 ++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index f05990211bf..4222e784536 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -456,7 +456,16 @@ void ThreeDBlox::createChiplet(const ChipletDef& chiplet) // Read DEF file if (!chiplet.external.def_file.empty()) { std::error_code ec; - if (!std::filesystem::exists(chiplet.external.def_file, ec) || ec) { + const bool def_exists + = std::filesystem::exists(chiplet.external.def_file, ec); + if (ec) { + logger_->error(utl::ODB, + 558, + "Cannot access DEF file {}: {}", + chiplet.external.def_file, + ec.message()); + } + if (!def_exists) { logger_->error(utl::ODB, 557, "DEF file does not exist: {}", diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index c3721860384..d85f04c61e9 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -3,9 +3,9 @@ source "helpers.tcl" # Test that read_3dbx gives a proper error for a non-existent file # rather than segfaulting (regression test for issue #10082) -# Test 1: Main file does not exist +# Test 1: Main file does not exist (Tcl proc raises ORD-0072 before C++ layer) if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { - if { [string first "Cannot open file" $err_msg] < 0 } { + if { [string first "ORD-0072" $err_msg] < 0 } { puts "FAIL: Wrong error for missing main file: $err_msg" exit 1 } @@ -15,9 +15,9 @@ if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { exit 1 } -# Test 2: Main file exists but references a non-existent include +# Test 2: Main file exists but references a non-existent include (ODB-0521 from BaseParser::logError) if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { - if { [string first "Cannot open file" $err_msg] < 0 } { + if { [string first "ODB-0521" $err_msg] < 0 } { puts "FAIL: Wrong error for missing include file: $err_msg" exit 1 } @@ -27,9 +27,9 @@ if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { exit 1 } -# Test 3: 3DBV chiplet references a non-existent DEF file +# Test 3: 3DBV chiplet references a non-existent DEF file (ODB-0557 from createChiplet) if { [catch {read_3dbv "data/fail_def.3dbv"} err_msg] } { - if { [string first "does not exist" $err_msg] < 0 } { + if { [string first "ODB-0557" $err_msg] < 0 } { puts "FAIL: Wrong error for missing DEF file: $err_msg" exit 1 } From cdc35a31e97480f4d98c9d87b5e5aa348ca9882b Mon Sep 17 00:00:00 2001 From: saumya Date: Thu, 23 Apr 2026 02:45:02 +0530 Subject: [PATCH 07/11] odb: address feedback on read_3dbx segfault fix - Add static_cast for uint32_t->int in dbBlock::create (clang-tidy) - Fix fail_def.3dbv: use type "hier" instead of "die"; DIE chips require a tech LEF and would fire ODB-0422 before reaching the DEF file check - Update read_3dbx-fail.ok with the [ERROR ...] log lines the test runner captures (stderr is merged with stdout via 2>&1 in regression_test.sh) - Shorten overlong comment line in read_3dbx-fail.tcl to pass tclint Signed-off-by: saumya --- src/odb/src/db/dbBlock.cpp | 2 +- src/odb/test/data/fail_def.3dbv | 2 +- src/odb/test/read_3dbx-fail.ok | 3 +++ src/odb/test/read_3dbx-fail.tcl | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index 11ef56a60f0..2c4c40d29f4 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -2998,7 +2998,7 @@ dbBlock* dbBlock::create(dbChip* chip_, const char* name_, char hier_delimiter_) _dbBlock* top = chip->block_tbl_->create(); top->initialize(chip, nullptr, name_, hier_delimiter_); chip->top_ = top->getOID(); - top->dbu_per_micron_ = chip_->getDb()->getDbuPerMicron(); + top->dbu_per_micron_ = static_cast(chip_->getDb()->getDbuPerMicron()); return (dbBlock*) top; } diff --git a/src/odb/test/data/fail_def.3dbv b/src/odb/test/data/fail_def.3dbv index 0f091e27079..86d7a1180a2 100644 --- a/src/odb/test/data/fail_def.3dbv +++ b/src/odb/test/data/fail_def.3dbv @@ -5,6 +5,6 @@ Header: ChipletDef: TestChiplet: - type: die + type: hier external: DEF_file: nonexistent.def diff --git a/src/odb/test/read_3dbx-fail.ok b/src/odb/test/read_3dbx-fail.ok index e2e839840a1..8505e8a6596 100644 --- a/src/odb/test/read_3dbx-fail.ok +++ b/src/odb/test/read_3dbx-fail.ok @@ -1,4 +1,7 @@ +[ERROR ORD-0072] nonexistent_file.3dbx does not exist. Caught expected error: main file not found +[ERROR ODB-0521] Parser Error: 3DBV Parser Error: Cannot open file: data/nonexistent_include.3dbv Caught expected error: include file not found +[ERROR ODB-0557] DEF file does not exist: data/nonexistent.def Caught expected error: DEF file not found pass diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index d85f04c61e9..41bc7f0f4a3 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -15,7 +15,7 @@ if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { exit 1 } -# Test 2: Main file exists but references a non-existent include (ODB-0521 from BaseParser::logError) +# Test 2: Main file exists but references a non-existent include if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { if { [string first "ODB-0521" $err_msg] < 0 } { puts "FAIL: Wrong error for missing include file: $err_msg" From d10a359cba05ff2dbeda230f4b6676cc272d8b62 Mon Sep 17 00:00:00 2001 From: saumya Date: Thu, 23 Apr 2026 04:34:49 +0530 Subject: [PATCH 08/11] odb: fix tclfmt formatting in read_3dbx-fail.tcl Add spaces inside catch command braces to satisfy tclfmt --check (required by //:fmt_tcl_test). Signed-off-by: saumya --- src/odb/test/read_3dbx-fail.tcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odb/test/read_3dbx-fail.tcl b/src/odb/test/read_3dbx-fail.tcl index 41bc7f0f4a3..9a7e86138c4 100644 --- a/src/odb/test/read_3dbx-fail.tcl +++ b/src/odb/test/read_3dbx-fail.tcl @@ -4,7 +4,7 @@ source "helpers.tcl" # rather than segfaulting (regression test for issue #10082) # Test 1: Main file does not exist (Tcl proc raises ORD-0072 before C++ layer) -if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { +if { [catch { read_3dbx "nonexistent_file.3dbx" } err_msg] } { if { [string first "ORD-0072" $err_msg] < 0 } { puts "FAIL: Wrong error for missing main file: $err_msg" exit 1 @@ -16,7 +16,7 @@ if { [catch {read_3dbx "nonexistent_file.3dbx"} err_msg] } { } # Test 2: Main file exists but references a non-existent include -if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { +if { [catch { read_3dbx "data/fail.3dbx" } err_msg] } { if { [string first "ODB-0521" $err_msg] < 0 } { puts "FAIL: Wrong error for missing include file: $err_msg" exit 1 @@ -28,7 +28,7 @@ if { [catch {read_3dbx "data/fail.3dbx"} err_msg] } { } # Test 3: 3DBV chiplet references a non-existent DEF file (ODB-0557 from createChiplet) -if { [catch {read_3dbv "data/fail_def.3dbv"} err_msg] } { +if { [catch { read_3dbv "data/fail_def.3dbv" } err_msg] } { if { [string first "ODB-0557" $err_msg] < 0 } { puts "FAIL: Wrong error for missing DEF file: $err_msg" exit 1 From 2925c6af3611c38138ba8c957f719fd6622a2d00 Mon Sep 17 00:00:00 2001 From: saumya Date: Thu, 23 Apr 2026 06:24:14 +0530 Subject: [PATCH 09/11] odb: move read_3dbx-fail to PASSFAIL_TESTS in Bazel BUILD The test validates error codes via Tcl catch+string checks, so the exact log format does not need to be verified with a .ok file diff. Moving to PASSFAIL_TESTS (check last line is "pass") avoids fragile exact-match failures while retaining full behavioral coverage. Signed-off-by: saumya --- src/odb/test/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odb/test/BUILD b/src/odb/test/BUILD index 784a5c90dc9..b282e3708c0 100644 --- a/src/odb/test/BUILD +++ b/src/odb/test/BUILD @@ -186,7 +186,6 @@ COMPULSORY_TESTS = [ "read_abstract_lef", "read_3dbv", "read_3dbx", - "read_3dbx-fail", "read_db", "read_def", "read_def58", @@ -221,6 +220,7 @@ PASSFAIL_TESTS = [ # NOTE: cpp_tests excluded - it's a CMake-specific wrapper script that expects # build directory structure not compatible with Bazel # "cpp_tests", + "read_3dbx-fail", "test_block", "test_bterm", "test_destroy", From 8606ca9c1a7e54c2343cd79d1a64f6361467eafe Mon Sep 17 00:00:00 2001 From: saumya Date: Thu, 23 Apr 2026 19:39:02 +0530 Subject: [PATCH 10/11] odb: move read_3dbx-fail to PASSFAIL_TESTS in CMake Mirrors the same change made to the Bazel BUILD: the test validates error codes via Tcl catch+string checks, so exact log matching is not needed. PASSFAIL (last line = "pass") is more robust. Signed-off-by: saumya --- src/odb/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odb/test/CMakeLists.txt b/src/odb/test/CMakeLists.txt index 90b859a814f..95a12da29f1 100644 --- a/src/odb/test/CMakeLists.txt +++ b/src/odb/test/CMakeLists.txt @@ -42,7 +42,6 @@ or_integration_tests( read_abstract_lef read_3dbv read_3dbx - read_3dbx-fail read_db read_def read_def58 @@ -71,6 +70,7 @@ or_integration_tests( write_lef_polygon write_macro_placement PASSFAIL_TESTS + read_3dbx-fail cpp_tests test_block test_bterm From 805c9878f3536d0d7bd633a4e3e852022944024c Mon Sep 17 00:00:00 2001 From: saumya Date: Sun, 26 Apr 2026 21:09:41 +0530 Subject: [PATCH 11/11] ci: retrigger after GitHub 502 on boost.proto download Signed-off-by: saumya