Skip to content

fix: add bounds-check guards for file reading functions#293

Merged
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/gerb-file-bounds-guards
Feb 28, 2026
Merged

fix: add bounds-check guards for file reading functions#293
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/gerb-file-bounds-guards

Conversation

@rampageservices
Copy link
Copy Markdown
Contributor

Summary

gerb_file_t has two allocation paths in gerb_fopen():

  • mmap path (Linux/macOS): buffer is exactly st_size bytes with no null terminator
  • calloc path (Windows): buffer has a null terminator at data[datalen]

strtol() and strtod() scan forward until they hit a non-matching character or '\0'. On the mmap path, if a file ends with digits and no trailing newline/command, these functions can read past the mapped region.

Additionally, gerb_fgetdouble() accesses start[0]/start[1] for the hex-float guard (added in #285) without checking that at least 2 bytes remain.

This PR:

  • Copies mmap'd data into a heap buffer with '\0' terminator before munmap, making both code paths produce identical null-terminated buffers
  • Simplifies gerb_fclose()fd->data is now always heap-allocated, so the #ifdef/munmap branch is removed
  • Adds early-return guards to gerb_fgetint() and gerb_fgetdouble() when the read pointer is at or past end-of-data
  • Guards the hex-float check in gerb_fgetdouble() with remaining >= 2 before accessing start[1]

Affected functions

Function Fix
gerb_fopen() Null-terminate mmap buffer via heap copy
gerb_fclose() Remove munmap branch, use g_free() unconditionally
gerb_fgetint() Early return at end-of-data
gerb_fgetdouble() Early return at end-of-data + bounds-check hex guard

Already safe (unchanged): gerb_fgetc() (checks ptr >= datalen), gerb_fgetstring() (uses iend bound).

Testing

  • Clean build, no new warnings
  • 94/104 tests pass (same 10 pre-existing rendering mismatches, unrelated)
  • Hex-expression test (test-amacro-hex-expression.gbx) renders correctly
  • X2 attributes test (test-gerber-x2-attributes.gbx) renders correctly
  • Truncated file ending in digits with no trailing newline — no crash

The mmap path in gerb_fopen() does not null-terminate the buffer,
so strtol/strtod in gerb_fgetint() and gerb_fgetdouble() could read
past the mapped region if a file ends with digits and no trailing
newline.

Copy mmap'd data into a heap buffer with a null terminator, matching
the existing calloc path behavior. This also simplifies gerb_fclose()
since fd->data is now always heap-allocated.

Add early-return guards to gerb_fgetint() and gerb_fgetdouble() when
the read pointer is at or past end-of-data. Guard the hex-float check
in gerb_fgetdouble() against single-byte remaining buffers.
@spe-ciellt
Copy link
Copy Markdown
Contributor

I merge this patch for now, looks simple and on point.

This patch makes the Linux file operations and Windows file operation more similar, so they could probably be more "the same". The reason for selecting the mmap()/unmap() in the beginning was that it made parsing faster. So for Unix like system I would still prefer the mmap()/unmap().

@spe-ciellt spe-ciellt merged commit bf0c872 into gerbv:develop Feb 28, 2026
1 check passed
@spe-ciellt spe-ciellt added the fix Solution for a potential problem or omission. label Feb 28, 2026
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