[ENG-2416] .stadb - #68
Conversation
Greptile SummaryThe PR replaces the Liberty-only
Confidence Score: 1/5The PR is not safe to merge until malformed The new file reader trusts arithmetic and allocation metadata from command-selected cache files, allowing crafted inputs to bypass section bounds or exhaust process memory before corruption handling can reject them. Files Needing Attention: stadb/StaDbFile.cc, stadb/StaDbGraph.cc
|
| Filename | Overview |
|---|---|
| stadb/StaDbFile.cc | Introduces the container format and section decoding, but its malformed-file validation permits an overflowing range and unbounded allocations. |
| stadb/StaDbReader.cc | Restores Liberty, network, graph, SDC, and search sections in the required dependency order. |
| stadb/StaDbWriter.cc | Serializes Liberty and network state and coordinates the remaining session sections. |
| stadb/StaDbGraph.cc | Rebuilds graph objects and timing data, including a collection count that should be bounded before allocation. |
| stadb/StaDbSdc.cc | Adds extensive tagged serialization and replay for constraint state. |
| stadb/StaDbSearch.cc | Restores search pools, paths, simulation state, and validity flags. |
| test/stadb.tcl | Exercises warm restoration, report equivalence, skip counters, editability, and byte stability. |
Sequence Diagram
sequenceDiagram
participant Tcl as read_sta_db
participant File as DbFileReader
participant Lib as Liberty reader
participant Net as Network reader
participant Graph as Graph reader
participant Sdc as SDC reader
participant Search as Search reader
Tcl->>File: read(filename)
File->>File: validate header and decode sections
File-->>Lib: liberty section
Lib-->>Net: restored libraries
File-->>Net: network section
File-->>Graph: graph section
File-->>Sdc: constraints section
File-->>Search: search section
Search-->>Tcl: linked, constrained, timed session
Reviews (1): Last reviewed commit: "attribute tests" | Re-trigger Greptile
| if (offset + stored_size > file.size()) | ||
| throw DbCorrupt("stadb section extends past end of file"); | ||
| const uint8_t *stored = file.data() + offset; |
There was a problem hiding this comment.
Overflowing section bounds check
When a .stadb section's 64-bit offset and stored size overflow when added, this check accepts an out-of-buffer range, causing the subsequent checksum, copy, or decompression operation to read out-of-bounds memory and potentially crash OpenSTA. Use subtraction-based bounds validation before constructing the pointer. How this was verified: Both range operands are decoded from the file as uint64_t values and their unchecked sum is validated immediately before the resulting pointer is read.
| if (offset + stored_size > file.size()) | |
| throw DbCorrupt("stadb section extends past end of file"); | |
| const uint8_t *stored = file.data() + offset; | |
| if (offset > file.size() | |
| || stored_size > file.size() - offset) | |
| throw DbCorrupt("stadb section extends past end of file"); | |
| const uint8_t *stored = file.data() + offset; |
| std::vector<uint8_t> &raw) | ||
| { | ||
| #ifdef ZLIB_FOUND | ||
| raw.resize(raw_size); |
There was a problem hiding this comment.
Unbounded cache metadata allocations
When a small crafted .stadb declares an enormous decompressed size, string count, or graph-object count, the reader passes that metadata to resize or reserve before proving it is consistent with the bounded section payload, causing OpenSTA to terminate through allocation failure or operating-system OOM handling instead of rejecting the cache. Bound every allocation-driving value by format limits and available section bytes before allocating. How this was verified: File-controlled values flow directly into resize and reserve before any section-derived or explicit resource limit is enforced.
|
@gigeresk will take over |
Summary
Replace the old
.libdbliberty-only cache with.stadb: a binary sessioncache that restores a linked, constrained, timed OpenSTA session so
report_checksworks immediately — without re-running liberty parse,link_design, graph build/levelize, delay calc, or search.On large industrial designs those cold steps can each take ~10–20 minutes.
.stadbis a derivable cache (version/ABI mismatch → regenerate), not along-lived archive.
Commands
What is serialized (v1, single scene)
read_libertyLibertyBuilder; CCS dropped with warning 2741read_verilog+link_designConcreteNetwork::make*API only (no private list surgery); instance attrs includingsrc/verilog_srcSdcmutatorsmakeVertex/makeEdge; delays/slews + annotation bits; Levelize/Dcalc “already done” flagsParasitics section id is reserved but not written yet.
Restore order (important)
Cold STA is constrain-then-build. Restore intentionally does:
liberty → network → graph → sdc → search
SDC’s
create_generated_clockpath callsupdateGeneratedClks→ levelize →ensureGraph(). If the graph is not already installed, that rebuilds it fromthe network and defeats the cache. Installing a levelized graph first makes
that path a no-op.
Liveness
Restored sessions stay editable. Computed delay annotation bits are left
clear so
replace_cellstill triggers incremental delay calc; SDF bitsstay set. Regressions assert both “report matches cold” and “edit after
restore matches cold edit.”
Guarantees / guards
scenes().size() != 1→ skip write)sizeofof critical types → automatic cache miss on layout driftliberty_cells_parsed,graph_vertices_made,levelize_runs,dcalc_vertices_computed,search_vertices_visited) muststay 0 after warm restore + first
report_checkssearch tag order is non-deterministic)
Explicit non-goals / gaps (v1)
read_spefstill required if you need them live)generated_clockdefinitions and networkgeneratedClockPinsToCellMap_(SDCcreate_generated_clockis fullysupported; liberty-originated genclks that were already materialized into
Sdc::clocks_round-trip as normal generated clocks and report correctly,but cannot be re-spawned from liberty after restore)
Also in this PR
.libdb(LibDb*, Tcl/SWIG entry points)test/stadbandtest/stadb_attrsregressions