This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/71319] New: unnecessary call to __strcat_chk emitted after buffer reset
- From: "msebor at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sat, 28 May 2016 00:02:28 +0000
- Subject: [Bug middle-end/71319] New: unnecessary call to __strcat_chk emitted after buffer reset
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71319
Bug ID: 71319
Summary: unnecessary call to __strcat_chk emitted after buffer
reset
Product: gcc
Version: 7.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: ---
Similar to bug 71304, in the following test case, since the string in the
destination buffer is truncated at a known offset after it has been copied
there by the checked call, the subsequent strcat call doesn't need to expand to
a checked call because there is enough space in the buffer to append the source
string to its contents. GCC performs this optimization in the first test case
(function f) when the string a truncated by calling strcpy, but it doesn't do
the same thing when the string is truncated by inserting a NUL into the same
position.
$ cat strcat.c && /home/msebor/build/gcc-6-branch/gcc/xgcc
-B/home/msebor/build/gcc-6-branch/gcc -O2 -S -fdump-tree-optimized=/dev/stdout
strcat.c
#define strcat(d, s)\
__builtin___strcat_chk (d, s, __builtin_object_size (d, 0))
#define strcpy(d, s) \
__builtin___strcpy_chk (d, s, __builtin_object_size (d, 0))
void sink (const char*);
int f (const char *s)
{
char a [4] = "1";
strcat (a, "2"); // safe
strcat (a, s); // must be checked
strcpy (a, "1");
strcat (a, "3"); // safe
sink (a);
}
int g (const char *s)
{
char a [4] = "1";
strcat (a, "2"); // safe
strcat (a, s); // must be checked
a [1] = '\0';
strcat (a, "3"); // safe but checked (missing optimization)
sink (a);
}
;; Function f (f, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0)
f (const char * s)
{
char a[4];
<bb 2>:
a = "1";
__builtin___strcpy_chk (&MEM[(void *)&a + 2B], s_4(D), 4);
MEM[(char * {ref-all})&a] = 49;
__builtin_memcpy (&MEM[(void *)&a + 1B], "3", 2);
sink (&a);
a ={v} {CLOBBER};
return;
}
;; Function g (g, funcdef_no=1, decl_uid=1762, cgraph_uid=1, symbol_order=1)
g (const char * s)
{
char a[4];
<bb 2>:
a = "1";
__builtin___strcpy_chk (&MEM[(void *)&a + 2B], s_4(D), 4);
a[1] = 0;
__builtin___strcat_chk (&a, "3", 4);
sink (&a);
a ={v} {CLOBBER};
return;
}