[Bug middle-end/94313] New: stores into string literals sometimes silently eliminated

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Mar 24 21:54:48 GMT 2020


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

            Bug ID: 94313
           Summary: stores into string literals sometimes silently
                    eliminated
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

Modifying a const-qualified object or a string literal is undefined in both C
and C++ and can result in subtle bugs.  Detecting attempts to do so as
requested in pr90404 will help prevent such hard-to-find bugs.  However,
reliable detection is made difficult by optimizations that silently eliminate
stores to such objects.  The test case below shows that the second of the four
invalid stores below (in g1) is silently eliminated (by DSE) while the others
are retained.  (None of them is diagnosed.)  The first two will likely crash if
the strings are stored in ROM.  The second two could lead in unexpected results
as a result of other optimizations (such as the strlen pass) that assume that
const objects cannot change.

The last revision I have access to that did not eliminate the store is r145753.
 The first revision that does is r145825, so the change was introduced sometime
in between these two.

$ cat z.c && gcc -O2 -S -Wall -Wwrite-strings -fdump-tree-optimized=/dev/stdout
z.c
void f (void*);

static char* str (void) { return (char*)"abc"; }

void g0 (int x)
{
  char *s = __builtin_strchr (str (), 'a');
  *s = 'x';   // not eliminated (okay)
  f (s);
}

void g1 (int x)
{
  char *s = __builtin_strchr (str (), x);
  *s = 'x';   // eliminated
  f (s);
}

const char a[] = "bcd";

void g2 (void)
{
  char *s = __builtin_strchr (a, 'b');
  *s = 'x';   // not eliminated (okay)
  f (s);
}

void g3 (int x)
{
  const char a[] = "cde";
  char *s = __builtin_strchr (a, 'c');
  *s = 'x';   // not eliminated (okay)
  f (s);
}


;; Function g0 (g0, funcdef_no=1, decl_uid=1935, cgraph_uid=2, symbol_order=1)

g0 (int x)
{
  <bb 2> [local count: 1073741824]:
  MEM[(char *)"abc"] = 120;
  f ("abc"); [tail call]
  return;

}



;; Function g1 (g1, funcdef_no=2, decl_uid=1939, cgraph_uid=3, symbol_order=2)

g1 (int x)
{
  char * s;

  <bb 2> [local count: 1073741824]:
  s_3 = __builtin_strchr ("abc", x_2(D));
  f (s_3); [tail call]
  return;

}



;; Function g2 (g2, funcdef_no=3, decl_uid=1944, cgraph_uid=4, symbol_order=4)

g2 ()
{
  <bb 2> [local count: 1073741824]:
  MEM[(char *)&a] = 120;
  f (&a); [tail call]
  return;

}



;; Function g3 (g3, funcdef_no=4, decl_uid=1948, cgraph_uid=5, symbol_order=5)

g3 (int x)
{
  char * s;
  const char a[4];

  <bb 2> [local count: 1073741824]:
  a = "cde";
  s_3 = __builtin_strchr (&a, 99);
  *s_3 = 120;
  f (s_3);
  a ={v} {CLOBBER};
  return;

}


More information about the Gcc-bugs mailing list