Bug 2432481

Summary: gcc misdiagnosis with stringop-overflow
Product: [Fedora] Fedora Reporter: Frank Ch. Eigler <fche>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 45CC: dmalcolm, fweimer, jakub, jlaw, josmyers, jwakely, mcermak, mpolacek, msebor, nickc, nixuser, sam, sipoyare
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
preprocessed input none

Description Frank Ch. Eigler 2026-01-23 20:43:18 UTC
A simple systemtap script can generate C code.  When one of these is when fed to gcc, it produces what looks like erroneous stringop-overflow warnings.  Since systemtap uses -Werror in its processing, these turn into errors.

/tmp/stap6KnM9x/stap_3930209_src.c:800:11: error: ‘strlcpy’ writing 512 bytes into a region of size 8 overflows the destination [-Werror=stringop-overflow=]
  800 |           strlcpy (l->__tmp16, global(s___global_spaces), MAXSTRINGLEN);
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                                                                                                                                                                                                                               
/tmp/stap6KnM9x/stap_3930209_src.c:46:19: note: destination object ‘__tmp10’ of size 8
   46 |           int64_t __tmp10;
      |                   ^~~~~~~


Attaching the .i file.

gcc --std=gnu99 -c foo.i -fvisibility=hidden -O2  -Wall -Werror -Wno-unused -Wno-strict-aliasing -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-pragmas -Wno-pointer-sign -Wno-format

Almost the same errors are detected on gcc15.2.1 (f43) and gcc16.0.1 (rawhide).  The data structure holding those __tmp values is tricky, and has nested anonymous structures and unions (because they are temporaries for evaluating the compiled systemtap script code).  But the C code looks OK, and such constructs aren't new.

Reproducible: Always

Comment 1 Frank Ch. Eigler 2026-01-23 20:44:00 UTC
Created attachment 2123539 [details]
preprocessed input

Comment 2 Siddhesh Poyarekar 2026-01-23 21:04:52 UTC
With gcc trunk I also see:

In file included from /usr/share/systemtap/runtime/dyninst/print.c:19,                                   
                 from /usr/share/systemtap/runtime/print.c:21,                                           
                 from /usr/share/systemtap/runtime/runtime_context.h:22,
                 from /tmp/stap6KnM9x/stap_3930209_src.c:281:
/usr/share/systemtap/runtime/vsprintf.c: In function ‘_stp_vsprint_memory.constprop’:
/usr/share/systemtap/runtime/vsprintf.c:341:23: error: ‘strnlen’ specified bound 8192 exceeds source size
 7 [-Werror=stringop-overread]
  341 |                 len = strnlen(ptr, clamp_t(size_t, precision, 0, STP_BUFFER_SIZE));
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Comment 3 Frank Ch. Eigler 2026-01-23 21:06:52 UTC
(Yeah, I think that's a separate false positive.)

Comment 4 Siddhesh Poyarekar 2026-01-23 22:37:52 UTC
Based on the preprocessed source, simply updating the precision when ptr is reset to "<NULL>" should get rid of the warning:

--- /tmp/foo2.i	2026-01-23 17:06:09.174220695 -0500
+++ /tmp/foo3.i	2026-01-23 17:06:01.664693280 -0500
@@ -16654,8 +16654,10 @@
  struct context * __restrict__ c;
 
  if (format == 's') {
-  if ((unsigned long)ptr < (1UL << 12))
+  if ((unsigned long)ptr < (1UL << 12)) {
    ptr = "<NULL>";
+   precision = sizeof (ptr) - 1;
+  }
   len = strnlen(ptr, ({ size_t __val = (precision); size_t __min = (0); size_t __max = (8192); __val = __val < __min ? __min: __val; __val > __max ? __max: __val; }));
  }
  else if (precision > 0)


Back to the original issue, here's a reduced reproducer:



#define SIZE 8

struct probe_144795_locals *probe_144795_l;

void strlcpy (char *, const char *, long)
    __attribute__ ((__access__ (__write_only__, 1, 3)));

struct probe_144795_locals
{
  union
    {
      struct
        {
          char __tmp7[SIZE];
          int __tmp10;
          int __tmp11;
        };
      struct
        {
          char __tmp15[SIZE];
          char __tmp16[SIZE];
        };
    };
};

void probe_144795(const char *in)
{
  probe_144795_l->__tmp10 = probe_144795_l->__tmp11 = 0;
  strlcpy (probe_144795_l->__tmp16, in, SIZE);
}

$ gcc -c ~/waccess-bug.c -O2  -Werror=stringop-overflow

Looks like the vectorizer somehow confuses waccess into thinking that the access is to __tmp10 instead of actually __tmp16.  I've traced it back to r12-4240, so this has been around for a while.  I'll file this upstream if there isn't already a report on this.

Comment 5 Frank Ch. Eigler 2026-01-23 23:48:23 UTC
nice work, thanks!

Comment 6 Aoife Moloney 2026-08-17 14:05:33 UTC
This bug appears to have been reported against 'rawhide' during the Fedora Linux 45 development cycle.
Changing version to 45.