https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97053

            Bug ID: 97053
           Summary: an O3 codegen bug
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: cuzdav at gmail dot com
  Target Milestone: ---

Created attachment 49217
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49217&action=edit
preprocessed code in case something changes after submitting

"Wrong" output codegen bug.  Very sensitive, almost any code change prevents
the problem, including O2 or less, as well as running under ubsan or asan,
reordering variables, and in some cases changing the values involved (such as
setting p=0 instead of 1)

Copying a buffer of 8 bytes of data (null terminated) results in a 6-bytes (of
data) null terminated "string", losing 2 bytes from the end.

A variable "len" holds the strlen() of this string, reports 6, but some code
affected by optimizer seems to think it is a larger value.

Expected output:

  runtime len=8
  orig=ABCDXXXX
  copy=ABCDXXXX

actual output:

  runtime len=6
  orig=ABCDXXXX
  copy=ABCDXX


Even though above the actual output shows len=6 when printing "len", a separate
line of code is not present in the assembly (presumably optimized away under a
confused compile-time eval.)

    if (len < 8)
        printf("len < 8\n"); // but len == 6


Problem visible in 10.1 and 10.2 at -O2 and -O3, but not -O1 or less, nor in in
9.x or earlier.  

CODE: 

#include <cstdio>
#include <cstring>

struct Data
{
    short n;
    char name[8 + 1];
    int p;
    char s;
    int b;
};

int main(int argc, char** argv)
{
    int p = 1;  
    char orig[9]{"XXXXXXXX"};
    std::memcpy(orig, "ABCD", 4);

    Data data{};
    data.n = 5u;

    // this should copy ABCDXXXX but loses final 2 XX's
    std::memcpy(data.name, orig, 8); 

    data.s = 'X';
    data.b = p;

    const size_t len = strlen(data.name);
    if (len < 8) 
        printf("len < 8\n"); // does not print

    std::printf("runtime len=%lu\n", len); // this, however, prints 6
    std::printf("orig=%s\ncopy=%s\n", orig, data.name);
}


Live on godbolt:  https://godbolt.org/z/v6xqh8

Reply via email to