Skip to content

parse_command_line.c: long clock passed to time() overruns the stack on LLP64 (Windows); plus GCC 15 needs -std=gnu17 #4

Description

@king-aj3

Two issues found while building master (363e43ed) with MinGW-w64 GCC 15.2.0 for Windows x64 on 2026-08-04. The first is a real defect on any LLP64 target, including MSVC — so it likely affects the WinMSVS branch too if it shares this file. The second will start hitting Linux users as distributions ship GCC 15.


1. time(&clock) with a long writes 8 bytes into a 4-byte slot on Windows

src/fasthenry/parse_command_line.c, in fix_and_print_opts():

long clock;
char hostname[BUFSIZ];
...
time(&clock);
fprintf(stdout, "  Date: %s", ctime(&clock));

time() takes a time_t *. On Linux and macOS this is harmless because those are LP64: long is 64-bit, so long and time_t are the same width and the write fits. Windows is LLP64long is 32-bit while time_t is 64-bit (__time64_t). time() therefore writes 8 bytes into a 4-byte stack object, corrupting the 4 bytes that follow it, on every run.

GCC 15 reports it as:

parse_command_line.c:533:8: error: passing argument 1 of 'time' from incompatible pointer type [-Wincompatible-pointer-types]
parse_command_line.c:534:39: error: passing argument 1 of 'ctime' from incompatible pointer type [-Wincompatible-pointer-types]

This one is worth flagging specifically because the tempting fix is the wrong one: adding -Wno-incompatible-pointer-types silences both lines and produces a binary that quietly corrupts its own stack.

Suggested fix — one word, correct on every platform, since time_t is the type time() has always taken:

time_t clock;

I have not sent a pull request because the licence terms in the source headers make me unsure whether I should be submitting modifications; happy to open one if you would like it.


2. GCC 15 defaults to C23, which rejects the K&R sources wholesale

Building with GCC 15 fails across induct.c, spAllocate.c and others with hundreds of errors of this shape:

induct.c:1165:29: error: too many arguments to function 'insert_in_list'; expected 0, have 2
spAllocate.c:206:5: error: too many arguments to function 'RecordAllocation'; expected 0, have 2

The cause is not a new warning being promoted — it is a language change. GCC 15 defaults to -std=gnu23, and in C23 an empty parameter list () means "takes no parameters" (as (void) always did) rather than "unspecified". Every K&R-style declaration in FastHenry therefore declares a zero-argument function, and every call becomes an arity error.

This matters because it is not suppressible: these are semantic errors, so no -Wno-... flag reaches them. The existing suppressions that FastHenry needs on modern compilers (-Wno-implicit-int, -Wno-implicit-function-declaration, -Wno-return-mismatch) are all still necessary and are no longer sufficient.

Suggested fix — pin the dialect in the makefiles, which older GCC and every clang also accept:

CFLAGS = -O -DFOUR -m64 -fcommon -std=gnu17 \
         -Wno-implicit-int -Wno-implicit-function-declaration -Wno-return-mismatch

src/fasthenry/sparse/Makefile needs the same treatment.


FYI: two more items specific to a MinGW build

Not requests — recorded only in case a native Windows (non-MSVC) build is ever of interest.

  • matherr collides with MinGW's <math.h>, which does #define matherr _matherr and declares int _matherr(struct _exception *). FastHenry's SunOS-era hook in induct.c then conflicts with that prototype. It is defined once, called nowhere, and no modern libm invokes it unless it is registered via __setusermatherr, so guarding it with #ifndef _WIN32 is enough.
  • sbrk is unavailable on Windows. The allocator itself is already portable — MORECORE in uglieralloc.c has been calloc since your port — and the remaining uses are two memory reporting sites (DUMPALLOCSIZ, which only fires on the out-of-memory path, and uallocEfcy). Reporting the figure as unavailable on Windows is sufficient; nothing computational depends on it.

With items 1 and 2 fixed and these two guarded, master builds and runs correctly under MinGW-w64 GCC 15.2.0. On a 100 mm × 1 mm × 1 mm copper bar swept 1 kHz → 10 MHz, the resulting Zc.mat is byte-identical to the Linux build's across all five decades.

Thanks for maintaining this — the 64-bit porting work on master is what makes FastHenry usable at all on current systems.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions