Bug 2432481 - gcc misdiagnosis with stringop-overflow
Summary: gcc misdiagnosis with stringop-overflow
Keywords:
Status: NEW
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 45
Hardware: Unspecified
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-01-23 20:43 UTC by Frank Ch. Eigler
Modified: 2026-08-17 14:05 UTC (History)
13 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Type: ---
Embargoed:


Attachments (Terms of Use)
preprocessed input (531.71 KB, text/plain)
2026-01-23 20:44 UTC, Frank Ch. Eigler
no flags Details


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 123801 0 P3 UNCONFIRMED [12/13/14/15/16 Regression] Wstringop-overflow false positive since r12-4240 2026-01-23 22:50:02 UTC

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.


Note You need to log in before you can comment on or make changes to this bug.