Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions liberty/LibertyReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,10 @@ LibertyReader::makeBundlePort(LibertyCell *cell,
debugPrint(debug_, "liberty", 1, " bundle {}", bundle_name);

const LibertyComplexAttr *member_attr = bundle_group->findComplexAttr("members");
if (member_attr == nullptr) {
warn(1315, bundle_group, "bundle {} missing members.", bundle_name);
return;
}
ConcretePortSeq *members = new ConcretePortSeq;
for (const LibertyAttrValue *member_value : member_attr->values()) {
if (member_value->isString()) {
Expand Down Expand Up @@ -1628,7 +1632,7 @@ LibertyReader::makePortFuncs(LibertyCell *cell,
FuncExpr *func_expr = parseFunc(func, "function", cell, func_attr->line());
for (LibertyPort *port : ports) {
port->setFunction(func_expr);
if (func_expr->checkSize(port)) {
if (func_expr && func_expr->checkSize(port)) {
warn(1195, func_attr->line(),
"port {} function size does not match port size.",
port->name());
Expand All @@ -1644,11 +1648,13 @@ LibertyReader::makePortFuncs(LibertyCell *cell,
FuncExpr *tri_disable_expr = parseFunc(tri_disable,
"three_state", cell,
tri_attr->line());
FuncExpr *tri_enable_expr = tri_disable_expr->invert();
for (LibertyPort *port : ports) {
port->setTristateEnable(tri_enable_expr);
if (port->direction() == PortDirection::output())
port->setDirection(PortDirection::tristate());
if (tri_disable_expr) {
FuncExpr *tri_enable_expr = tri_disable_expr->invert();
for (LibertyPort *port : ports) {
port->setTristateEnable(tri_enable_expr);
if (port->direction() == PortDirection::output())
port->setDirection(PortDirection::tristate());
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions liberty/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ sta_module_tests("liberty"
equiv_map_libs
func_expr
leakage_power_deep
malformed_ports
multi_corner
multi_lib_equiv
opcond_scale
Expand Down
26 changes: 26 additions & 0 deletions liberty/test/liberty_malformed_ports.lib
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* Liberty with malformed port attributes, used by liberty_malformed_ports.tcl.
Each cell exercises a LibertyReader code path that previously dereferenced a
null FuncExpr / null members attribute and crashed (SIGSEGV). After the fix
the reader emits a warning and continues. */
library (malformed_ports) {
delay_model : table_lookup;

/* "function" references an undeclared pin, so parseFunc() returns null. */
cell (BAD_FUNC) {
pin (A) { direction : input; }
pin (Z) { direction : output; function : "A & NOPIN"; }
}

/* "three_state" references an undeclared pin, so parseFunc() returns null. */
cell (BAD_TRI) {
pin (A) { direction : input; }
pin (EN) { direction : input; }
pin (Z) { direction : output; three_state : "BADPIN"; function : "A"; }
}

/* "bundle" group with no "members" attribute. */
cell (BAD_BUNDLE) {
pin (A) { direction : input; }
bundle (B) { direction : output; }
}
}
4 changes: 4 additions & 0 deletions liberty/test/liberty_malformed_ports.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Warning 1130: liberty_malformed_ports.lib line 11, function references unknown port NOPIN.
Warning 1130: liberty_malformed_ports.lib line 18, three_state references unknown port BADPIN.
Warning 1315: liberty_malformed_ports.lib line 24, bundle B missing members.
read_liberty completed, cells loaded: 3
8 changes: 8 additions & 0 deletions liberty/test/liberty_malformed_ports.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Malformed port attributes must produce a clean warning, not crash the reader.
# Regression for LibertyReader null-dereferences:
# - makePortFuncs(): "function" expression that parses to null (undeclared pin)
# - makePortFuncs(): "three_state" expression that parses to null
# - makeBundlePort(): "bundle" group with no "members" attribute
# Before the fix each of these dereferenced a null pointer and crashed (SIGSEGV).
read_liberty liberty_malformed_ports.lib
puts "read_liberty completed, cells loaded: [llength [get_lib_cells malformed_ports/*]]"