Skip to content

long clock passed to time() is a 64-bit bug on LLP64 (Windows): 8 bytes written into 4 #5

Description

@king-aj3

Building master for native Windows with mingw-w64 (gcc 16.2.0, ucrt64) I hit
one real correctness bug and three portability issues. The first is worth
separating from the rest, because it is a genuine 64-bit fault rather than a
build-environment complaint.

1. time() writes past its destination on Windows — parse_command_line.c

  long clock;
  ...
  time(&clock);
  fprintf(stdout, "  Date: %s", ctime(&clock));

Windows is LLP64: long is 4 bytes while time_t is 8. So time(&clock)
writes 8 bytes into a 4-byte object, and ctime(&clock) then reads a time_t
from it. On Linux/macOS (LP64) both are 8 bytes, which is why this has never
shown up there.

gcc 16 rejects it outright:

parse_command_line.c:534:39: error: passing argument 1 of 'ctime' from incompatible pointer type
   note: expected 'const time_t *' {aka 'const long long int *'} but argument is of type 'long int *'

⚠ Worth stressing: this one should not be silenced with
-Wno-incompatible-pointer-types. The diagnostic is correct and the write is
out of bounds.

Fix: declare it time_t clock;. That is correct on every platform —
time_t is the type time() is specified to take.

2. matherr collides with the mingw CRT — induct.c

induct.c defines the SunOS-era handler:

int matherr(exc)
struct exception *exc;

mingw's math.h does #define matherr _matherr and prototypes
int __cdecl _matherr(struct _exception *), so the definition collides:

induct.c:1242:19: error: argument 'exc' doesn't match prototype
   math.h:278:15: note: prototype declaration

⚠ A -D on the command line cannot work around this — math.h is included
first and its macro wins, so the rename has to happen in the source.

The function's whole body is printf("Err in math\n"); return(0);, and modern
CRTs never invoke it. Suggested fix: guard it (#ifndef _WIN32) or rename
it; either is a one-line change.

3. resusage.h requires a POSIX header under -DFOUR

-DFOUR selects the BSD getrusage timers, which #include <sys/resource.h>
— absent on mingw. The header already handles this: with neither FOUR nor
FIVE defined its #else branch defines no-op timers and needs no POSIX
includes. So this is only a documentation matter — the Windows build simply
must not define FOUR
— but it is the first thing anyone hits, and the
README/build notes recommend -DFOUR unconditionally.

4. sbrk and gethostname unresolved at link

Both are used for reporting only — the run header's host line and the memory
statistics. On mingw they do not exist, so the link fails after everything has
compiled. I linked a small shim returning a constant from sbrk and filling
gethostname from GetComputerNameA.

⚠ With that shim the reported memory figures are meaningless on Windows. If a
_WIN32 branch is ever added upstream I would suggest omitting the memory
report rather than printing a number that looks like a measurement.

Build-system note

The Makefile recurses with cd sparse; make. mingw ships the binary as
mingw32-make.exe only, so the sub-make dies with make: command not found
after every source file has compiled, which reads like a build failure rather
than a missing alias.

Result

With those four changes the binary builds and solves correctly. Sanity check —
a 10 mm × 1 mm² copper bar at 1 MHz:

Row 1:  n1  to  n2
Impedance matrix for frequency = 1e+06 1 x 1
   0.000172414    +0.0358409j

R = 1.724e-4 Ω is exactly ρL/A for copper, and X = 0.0358 Ω is 5.7 nH, both as
expected for that geometry. The resulting executable is self-contained — it
runs with only C:\Windows\system32 on PATH.

Happy to open a PR for #1 alone if that is easier to review, since it is the
one that is a bug rather than a portability preference.

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