From 0e40b4f8a1c4b6af7225da31cd88a1d29d8a04a2 Mon Sep 17 00:00:00 2001 From: Andreas Wendleder Date: Mon, 13 Apr 2026 15:35:10 +0200 Subject: [PATCH] Fix UB in dcalc tests: remove fake Pin* pointers from LoadPinIndexMap LoadPinIndexMap uses PinIdLess as its comparator, which calls network_->id(pin) and dereferences the Pin pointer. Three tests created fake Pin* via reinterpret_cast(&int_var) and inserted them into LoadPinIndexMap, causing undefined behavior. With GCC 15.2.0's hardened std::vector::operator[] bounds checking, this UB manifests as an assertion failure: vector::operator[]: Assertion '__n < this->size()' failed Fix by using empty LoadPinIndexMap for gateDelay/gateDelays/ inputPortDelay calls (the comparator is never invoked on an empty map) and testing wire delay/load slew accessors via ArcDcalcResult::setLoadCount() directly. --- dcalc/test/cpp/TestDcalc.cc | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/dcalc/test/cpp/TestDcalc.cc b/dcalc/test/cpp/TestDcalc.cc index a471575a..52370f48 100644 --- a/dcalc/test/cpp/TestDcalc.cc +++ b/dcalc/test/cpp/TestDcalc.cc @@ -802,22 +802,23 @@ TEST_F(StaDcalcTest, AllCalcsCopyDestroy) { } // Test UnitDelayCalc with non-empty load_pin_index_map +// Note: LoadPinIndexMap uses PinIdLess which calls network_->id(pin), +// so we cannot use fake Pin* pointers. Test with an empty map +// (load sizing is already covered by ArcDcalcResultTest). TEST_F(StaDcalcTest, UnitDelayCalcGateDelayWithLoads) { ArcDelayCalc *calc = makeDelayCalc("unit", sta_); ASSERT_NE(calc, nullptr); LoadPinIndexMap load_pin_index_map(sta_->network()); - // Use dummy pin pointers for the index map - int dummy1 = 1, dummy2 = 2; - const Pin *pin1 = reinterpret_cast(&dummy1); - const Pin *pin2 = reinterpret_cast(&dummy2); - load_pin_index_map[pin1] = 0; - load_pin_index_map[pin2] = 1; ArcDcalcResult result = calc->gateDelay(nullptr, nullptr, 0.0, 0.0, nullptr, load_pin_index_map, nullptr, nullptr); EXPECT_GE(delayAsFloat(result.gateDelay()), 0.0f); - // UnitDelayCalc may leave uninitialized subnormal floats for wire delays; - // use EXPECT_NEAR with a tolerance to avoid flakiness. + // Verify wire delay / load slew accessors via ArcDcalcResult directly. + result.setLoadCount(2); + result.setWireDelay(0, 0.0); + result.setWireDelay(1, 0.0); + result.setLoadSlew(0, 0.0); + result.setLoadSlew(1, 0.0); EXPECT_NEAR(delayAsFloat(result.wireDelay(0)), 0.0f, 1e-10f); EXPECT_NEAR(delayAsFloat(result.wireDelay(1)), 0.0f, 1e-10f); EXPECT_NEAR(delayAsFloat(result.loadSlew(0)), 0.0f, 1e-10f); @@ -832,14 +833,10 @@ TEST_F(StaDcalcTest, UnitDelayCalcGateDelaysWithLoads) { ArcDcalcArgSeq args; args.push_back(ArcDcalcArg()); LoadPinIndexMap load_pin_index_map(sta_->network()); - int dummy1 = 1; - const Pin *pin1 = reinterpret_cast(&dummy1); - load_pin_index_map[pin1] = 0; ArcDcalcResultSeq results = calc->gateDelays(args, load_pin_index_map, nullptr, nullptr); EXPECT_EQ(results.size(), 1u); EXPECT_GE(delayAsFloat(results[0].gateDelay()), 0.0f); - EXPECT_FLOAT_EQ(delayAsFloat(results[0].wireDelay(0)), 0.0f); delete calc; } @@ -848,9 +845,6 @@ TEST_F(StaDcalcTest, UnitDelayCalcInputPortDelayWithLoads) { ArcDelayCalc *calc = makeDelayCalc("unit", sta_); ASSERT_NE(calc, nullptr); LoadPinIndexMap load_pin_index_map(sta_->network()); - int dummy1 = 1; - const Pin *pin1 = reinterpret_cast(&dummy1); - load_pin_index_map[pin1] = 0; ArcDcalcResult result = calc->inputPortDelay(nullptr, 1e-10, nullptr, nullptr, load_pin_index_map, nullptr, nullptr);