Skip to content

fix: replace unsafe dprintf macro with safe DPRINTF variadic macro#320

Merged
spe-ciellt merged 2 commits intogerbv:developfrom
SourceParts:fix/unsafe-dprintf-macro
Mar 3, 2026
Merged

fix: replace unsafe dprintf macro with safe DPRINTF variadic macro#320
spe-ciellt merged 2 commits intogerbv:developfrom
SourceParts:fix/unsafe-dprintf-macro

Conversation

@rampageservices
Copy link
Copy Markdown
Contributor

Summary

  • Replace unsafe #define dprintf if(DEBUG) printf macro with #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0) across all 17 source files
  • Add missing braces around single-statement if/else bodies in drill.c (SEI CERT EXP19-C)
  • Remove all goto patterns in drill.c, replacing with structured control flow

Problem

The dprintf macro defined in 16 files as #define dprintf if(DEBUG) printf has two issues:

  1. Dangling-else bug — the unbraced if causes else to bind incorrectly:

    if (error)
        dprintf("bad");    // expands to: if(0) printf("bad");
    else
        handle_ok();       // else binds to if(0), runs unconditionally
  2. Shadows POSIX dprintf(3)dprintf is a standard function for writing to file descriptors

main.c had an even more dangerous variant with two unbraced statements:

#define dprintf printf("%s():  ", __FUNCTION__); printf

Changes

Commit 1 — drill.c:

  • Replace macro definition with safe DPRINTF(...) variadic macro
  • Rename all call sites from dprintf() to DPRINTF()
  • Add braces to single-statement if/else bodies
  • Remove 3 goto patterns, replacing with structured control flow (parsing_done flag, for(;;) loop, found_junk flag)
  • Add [[fallthrough]] annotation for pre-existing intentional fallthrough

Commit 2 — remaining 15 files + main.c:

  • Same macro replacement across: gerber.c, gerbv.c, gerb_file.c, gerb_stats.c, project.c, interface.c, callbacks.c, render.c, attribute.c, draw.c, draw-gdk.c, export-drill.c, export-isel-drill.c, export-rs274x.c, drill_stats.c, main.c

Acknowledgment

The unsafe macro problem was originally identified by @henrygab in PR #226 (and earlier PR #210), which proposed fixes for drill.c. Those PRs were closed without merging. This PR applies the same category of fix using C99 variadic macros (appropriate for the project's C23 standard) and extends it to the full codebase.

Addresses

Test plan

  • Clean build with zero new warnings (cmake .. && make -j$(nproc))
  • Test suite: 94/104 pass (same baseline as develop)
  • grep -r '#define dprintf' src/ returns zero results

rampageservices and others added 2 commits March 1, 2026 22:03
Replace `#define dprintf if(DEBUG) printf` with a safe variadic macro:

    #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)

The old macro has two problems:
1. It shadows POSIX dprintf(3)
2. The unbraced `if(DEBUG)` causes a dangling-else bug when used
   inside an `if` without braces — the `else` binds to `if(DEBUG)`
   instead of the outer `if`.

Also:
- Add braces to all single-statement if/else bodies (SEI CERT EXP19-C)
- Remove all goto statements, replacing with structured control flow:
  - `goto drill_parse_end` → `parsing_done` flag checked in while loop
  - `goto header_again` → `for(;;)` loop with `continue`
  - `goto header_junk` → `found_junk` flag checked after switch
- Add [[fallthrough]] annotation for DRILL_M_END → DRILL_M_ENDREWIND

Addresses issues gerbv#220 and gerbv#216.

Co-Authored-By: Henry Gabryjelski <74016805+henrygab@users.noreply.github.com>
Extend the drill.c fix to the rest of the codebase. All 16 files used
the same unsafe pattern: #define dprintf if(DEBUG) printf — which
causes dangling-else bugs and shadows POSIX dprintf(3).

main.c had an even more dangerous variant using two unbraced
statements: printf("%s(): ", __FUNCTION__); printf

Replaced all with the safe variadic macro:
#define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)

Addresses issue gerbv#220 (POSIX dprintf shadow / dangling-else hazard).
@spe-ciellt
Copy link
Copy Markdown
Contributor

Verdict is "good to merge". FYI you could use cmake --preset linux-gnu-gcc -DDEBUG_PRINTOUT=TRUE to build with debug print.

@spe-ciellt spe-ciellt merged commit eb225a4 into gerbv:develop Mar 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Solution for a potential problem or omission.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants