Skip to content

Fix crash in netlist verify/ripup/cull from stale DBSrConnect callback signatures - #554

Open
ananthchellappa wants to merge 1 commit into
RTimothyEdwards:masterfrom
ananthchellappa:fix/dbsrconnect-callback-arity
Open

Fix crash in netlist verify/ripup/cull from stale DBSrConnect callback signatures#554
ananthchellappa wants to merge 1 commit into
RTimothyEdwards:masterfrom
ananthchellappa:fix/dbsrconnect-callback-arity

Conversation

@ananthchellappa

Copy link
Copy Markdown

verify, ripup, and cull segfault — stale DBSrConnect callback signatures

Version: 8.3.681 (commit 4432d7ec)
Component: netmenu/NMwiring.c, lef/defWrite.c
Severity: High — reproducible crash, takes the whole session down

Summary

Three netlist-window commands — verify, ripup, cull — segfault as soon as they trace any tile. This makes the netlist window's connectivity-checking functionality unusable.

A survey of all DBSrConnect clients found four stale callbacks, not three: the same defect is present in defBlockageGeometryFunc in lef/defWrite.c, which affects DEF blockage output.

Callback File Style Reached by
nmwRipTileFunc netmenu/NMwiring.c:126 K&R ripup, cull
nmwNetTileFunc netmenu/NMwiring.c:481 K&R netlist extract
nmwVerifyTileFunc netmenu/NMwiring.c:719 ANSI verify
defBlockageGeometryFunc lef/defWrite.c:2642 (+ forward decl at :2613) ANSI def write with blockages

DBSrConnect has only two callers outside itself — netmenu/NMwiring.c (4 sites) and lef/defWrite.c (3 sites) — so this list is complete. The correct signature is already used by defNetGeometryFunc (lef/defWrite.c:935) and defSimpleBlockageFunc (lef/defWrite.c:2701); the latter actually uses dinfo, as TiGetTypeExact(tile) | dinfo.

Each of the four is passed only to DBSrConnect and to nothing else, so correcting the arity affects no other caller.

Root cause

DBSrConnect invokes its client callback with four arguments (database/DBconnect.c:456):

if ((*csa->csa_clientFunc)(tile, dinfo, pNum, csa->csa_clientData) != 0)

but netmenu's callbacks still have the three-argument signature from before dinfo was added:

/* netmenu/NMwiring.c:126 */
nmwRipTileFunc(tile, plane, listHead)
    Tile *tile;
    int plane;
    struct nmwarea **listHead;

/* netmenu/NMwiring.c:719 */
nmwVerifyTileFunc(
    Tile *tile,
    int plane,
    ClientData cdata)

The callbacks therefore receive dinfo where they expect the plane number, and the plane number where they expect their ClientData — which they then dereference. Under gdb the crash shows a jump to a small integer address:

Program received signal SIGSEGV
#0  0x0000000000000009
#1  nmwVerifyTileFunc (tile=..., plane=0, cdata=0x...)

and for ripup:

#0  nmwRipTileFunc (tile=..., plane=0, listHead=0x9) at NMwiring.c:136
#3  NMRipup () at NMwiring.c:174

listHead=0x9 is the plane number arriving in the ClientData slot.

Reproduction

Any layout and netlist will do — the crash occurs on the first traced tile, on both correctly wired and unwired designs.

Build a cell with two disconnected labelled rectangles:

box 0 0 10 2 ; paint metal1 ; label A
box 40 0 50 2 ; paint metal1 ; label B
save nmcell

with nmcell.net containing:

 Netlist File

A
B

then:

load nmcell
specialopen netlist
netlist nmcell
verify                  # <-- dumps core here

Observed on 8.3.681: the process dies immediately after the netlist is read. ripup (with a box set before specialopen) crashes identically.

After the fix, the same script reports Terminal "B" not connected. and generates one feedback area; joining the two rectangles with box 0 0 50 2 ; paint metal1 then gives No wiring errors found.

Expected behaviour

verify reports opens and shorts against the netlist; ripup removes routing; cull prunes. None of them crash.

Fix

Add the missing TileType dinfo parameter to all four callbacks and to the one forward declaration, matching defNetGeometryFunc. None of the four needs the split-tile information, so the argument is accepted and ignored:

int
nmwVerifyTileFunc(
    Tile *tile,			/* Tile that is connected to this net. */
    TileType dinfo,		/* Split tile information (unused) */
    int plane,			/* Plane index of the tile. */
    ClientData cdata)		/* Processing function for each tile. */

Total change: 8 insertions, 3 deletions across two files. Builds clean with no new warnings.

A separate question, deliberately not addressed here: three of these callbacks call TiGetType(tile) rather than TiGetTypeExact(tile) | dinfo, so they will still take the wrong type for split (non-Manhattan) tiles. That is a pre-existing correctness issue independent of the crash, and it deserves its own change.

Impact note

This silently removes the only connectivity-verification path Magic has for hand-routed layout. Users hitting it are likely to conclude the netlist window is abandoned rather than that it has a two-line bug.

DBSrConnect() passes four arguments to its client function (tile, dinfo,
plane, clientData), the "dinfo" split-tile argument having been added
when non-Manhattan geometry handling was extended.  Four client
functions were never updated and still declared the original three
arguments, so each one received "dinfo" where it expected the plane
number and the plane number where it expected its ClientData, which it
then dereferenced.

In netmenu, this crashed the "verify", "ripup" and "cull" commands as
soon as any tile was traced, making the netlist window's connectivity
checking unusable.  In lef, defBlockageGeometryFunc() has the same
defect and would misbehave when writing DEF blockages.

The affected functions are nmwRipTileFunc(), nmwNetTileFunc() and
nmwVerifyTileFunc() in netmenu/NMwiring.c, plus
defBlockageGeometryFunc() and its forward declaration in
lef/defWrite.c.  None of them needs the split-tile information, so the
argument is accepted and ignored, matching defNetGeometryFunc() and
defSimpleBlockageFunc() which already have the correct signature.

Verified against a two-terminal test netlist:  before the change,
"verify" and "ripup" both dumped core;  after it, "verify" correctly
reports 'Terminal "B" not connected.' on a disconnected layout and
"No wiring errors found." once the terminals are joined, and "ripup"
completes normally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vdvntfrih4TA8gjnKZ7fD
@RTimothyEdwards

Copy link
Copy Markdown
Owner

Looks reasonable. I will do a complete check and review, but I won't be able to get to it for a couple of days. If I haven't reviewed it within a week, please feel free to post a reminder.

@ananthchellappa

ananthchellappa commented Aug 21, 2026 via email

Copy link
Copy Markdown
Author

@RTimothyEdwards

Copy link
Copy Markdown
Owner

@ananthchellappa : I've caught Claude being wrong before (not Fable 5, yet, but Opus, definitely).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants