Skip to content

Conversation

@lemenkov
Copy link
Contributor

Summary
Fix format specifier warnings on 32-bit architectures (i686) with GCC 15

Details
This PR fixes compilation warnings that appear on 32-bit architectures (i686) when using GCC 15. The warnings are caused by using incorrect format specifiers for size_t, int64_t, and uint64_t types, which have different sizes on 32-bit vs 64-bit platforms.

On x86_64, size_t and int64_t are aliases for unsigned long and long int respectively, so %ld and %lu work fine. However, on i686 (32-bit):

  • size_t is unsigned int (4 bytes), not unsigned long
  • int64_t is long long int (8 bytes), not long int
  • uint64_t is unsigned long long int (8 bytes), not unsigned long int

This causes GCC to emit -Wformat warnings on 32-bit builds, as the format specifiers don't match the actual argument types.

Affected modules:

  • http2d: Incorrect %ld for size_t in server.c
  • aaa_diameter: Incorrect %ld/%lu for int64_t/uint64_t in dm_impl.c

Solution
Replace architecture-specific format specifiers with portable C99 standard specifiers:

  1. Use %zu for size_t (defined in C99, works on all architectures)
  2. Use %" PRId64 for int64_t (from <inttypes.h>, expands to correct specifier per platform)
  3. Use %" PRIu64 for uint64_t (from <inttypes.h>, expands to correct specifier per platform)

These portable specifiers automatically adapt to the platform:

  • On 64-bit: %zu → format as unsigned long, PRId64"ld", PRIu64"lu"
  • On 32-bit: %zu → format as unsigned int, PRId64"lld", PRIu64"llu"

Compatibility
No compatibility impact. This is purely a build-time fix that doesn't change runtime behavior or APIs. The same values are printed, just with correct format specifiers.

Closing issues
N/A

During compilation on i686 (32-bit) architecture with GCC 15, format
specifier warnings appear due to type size differences between 32-bit
and 64-bit platforms.

```
server.c: In function 'on_frame_recv_callback':
warning: format '%ld' expects argument of type 'long int', but argument 14
has type 'size_t' {aka 'unsigned int'} [-Wformat=]
  638 |  LM_DBG("h2 header [%d], %p %ld\n", frame->hd.type, frame->headers.nva, frame->headers.nvlen);

dm_impl.c: In function 'dm_avps2json':
warning: format '%ld' expects argument of type 'long int', but argument 15
has type 'int64_t' {aka 'long long int'} [-Wformat=]
  484 |  LM_DBG("%2d. got int64   AVP %s (%u), value: %ld\n", i, dm_avp.avp_name, h->avp_code, h->avp_value->i64);

warning: format '%lu' expects argument of type 'long unsigned int', but argument 15
has type 'uint64_t' {aka 'long long unsigned int'} [-Wformat=]
  494 |  LM_DBG("%2d. got uint64  AVP %s (%u), value: %lu\n", i, dm_avp.avp_name, h->avp_code, h->avp_value->u64);
```

Type sizes differ between 32-bit and 64-bit architectures:

**On x86_64 (64-bit):**
- `size_t` = `unsigned long` (8 bytes)
- `int64_t` = `long int` (8 bytes)

**On i686 (32-bit):**
- `size_t` = `unsigned int` (4 bytes)
- `int64_t` = `long long int` (8 bytes)
- `uint64_t` = `unsigned long long int` (8 bytes)

Use portable C99 format specifiers that work correctly on all
architectures:

- `%zu` for `size_t` (modules/http2d/server.c line 638)
- `%" PRId64` for `int64_t` (modules/aaa_diameter/dm_impl.c line 484)
- `%" PRIu64` for `uint64_t` (modules/aaa_diameter/dm_impl.c line 494)

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Assisted-by: Claude (Anthropic) <https://claude.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant