Skip to content

dhcpv6-ia: zero-initialize first_key to silence -Wmaybe-uninitialized - #409

Open
micpf wants to merge 1 commit into
openwrt:masterfrom
micpf:dhcpv6-ia-silence-maybe-uninitialized
Open

dhcpv6-ia: zero-initialize first_key to silence -Wmaybe-uninitialized#409
micpf wants to merge 1 commit into
openwrt:masterfrom
micpf:dhcpv6-ia-silence-maybe-uninitialized

Conversation

@micpf

@micpf micpf commented Jul 21, 2026

Copy link
Copy Markdown

Problem

Building odhcpd on an aarch64 glibc target (NXP LS1046, GCC 12.3.0) with _FORTIFY_SOURCE enabled fails with:

In function 'memcpy',
    inlined from 'dhcpv6_ia_handle_IAs' at src/dhcpv6-ia.c:1222:8:
bits/string_fortified.h:29:10: error: '*(__int128 unsigned *)(&first_key[0])'
    may be used uninitialized [-Werror=maybe-uninitialized]
src/dhcpv6-ia.c:970:17: note: '*(__int128 unsigned *)(&first_key[0])' was declared here
  970 |         uint8_t first_key[16];

CMakeLists.txt sets -Werror, so this turns the warning into a hard build failure.

Analysis

The code is correct: first_key[] is only read on the branch guarded by first_key_valid, and first_key_valid is only set to true after memcpy(first_key, a->key, sizeof(first_key)). GCC's -Wmaybe-uninitialized analysis cannot correlate the boolean guard with the array's initialization state — a well-known limitation.

The warning becomes visible only when three conditions coincide:

  1. glibc, so memcpy is expanded inline as __builtin___memcpy_chk via bits/string_fortified.h.
  2. _FORTIFY_SOURCE enabled at the caller.
  3. aarch64 GCC 12, which lowers the 16-byte copy to a single 128-bit (__int128) access, exposing the correlation problem in the diagnostic simplifier.

musl builds and non-fortified builds are unaffected because they don't inline the fortified wrapper the same way. That's why upstream CI hasn't hit this.

Fix

Zero-initialize first_key[16]. Runtime behavior is unchanged — when first_key_valid is true, the buffer has already been overwritten by memcpy(first_key, a->key, …). The added cost is one zeroing store on function entry.

first_key[] is only read on the path guarded by first_key_valid, and
first_key_valid is only set to true after first_key has been populated
by memcpy(). The code is therefore correct, but GCC's uninitialized
analysis cannot correlate the boolean guard with the array's
initialization state.

With glibc's _FORTIFY_SOURCE enabled, memcpy() is expanded inline as
__builtin___memcpy_chk(), and on aarch64 the 16-byte copy is further
lowered to a single 128-bit access. GCC 12 then emits:

  error: '*(__int128 unsigned *)(&first_key[0])' may be used
         uninitialized [-Werror=maybe-uninitialized]

which -Werror in CMakeLists.txt turns into a build failure on
aarch64 glibc targets (e.g. NXP LS1046). musl and non-fortified
builds are unaffected because they don't inline the fortified
wrapper the same way.

Zero-initialize the buffer to silence the false positive. Runtime
behavior is unchanged: when first_key_valid is true, the buffer has
already been overwritten by memcpy(first_key, a->key, ...).

Signed-off-by: Michael Pfeifroth <micpf@westermo.com>
@micpf
micpf force-pushed the dhcpv6-ia-silence-maybe-uninitialized branch from 94f96d7 to 43b9aeb Compare July 21, 2026 06:47
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