Commit f3fc9b80 by Romain Geissler Committed by Jakub Jelinek

builtins.def (BUILT_IN_STPNCPY_CHK): New definition.

	* builtins.def (BUILT_IN_STPNCPY_CHK): New definition.
	* builtins.c (expand_builtin, fold_builtin_4, maybe_emit_chk_warning):
	Add BUILT_IN_STPNCPY_CHK case.
	* gimple-fold.c (gimple_fold_builtin): Likewise.
	* tree-object-size.c (pass_through_call): Likewise.
	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1,
	call_may_clobber_ref_p_1): Likewise.
	* tree-ssa-structalias.c (find_func_aliases_for_builtin_call,
	find_func_clobbers): Likewise.
	* tree.h (fold_builtin_strncpy_chk): Rename to fold_builtin_stxncpy_chk
	* builtins.c (fold_builtin_strncpy_chk): Likewise.
	Rewrite stpncpy_chk calls to strncpy_chk calls if returned value is
	ignored.

	* gcc.c-torture/execute/builtins/chk.h (stpncpy, stpncpy_disallowed):
	New definitions.
	* gcc.c-torture/execute/builtins/lib/chk.c (stpncpy_disallowed):
	Likewise.
	(stpncpy, __stpncpy_chk): New functions.
	* gcc.c-torture/execute/builtins/stpncpy-chk-lib.c: New file.
	* gcc.c-torture/execute/builtins/stpncpy-chk.c: Likewise.

From-SVN: r182378
parent ee7a54c5
2011-12-15 Romain Geissler <romain.geissler@gmail.com>
* builtins.def (BUILT_IN_STPNCPY_CHK): New definition.
* builtins.c (expand_builtin, fold_builtin_4, maybe_emit_chk_warning):
Add BUILT_IN_STPNCPY_CHK case.
* gimple-fold.c (gimple_fold_builtin): Likewise.
* tree-object-size.c (pass_through_call): Likewise.
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1,
call_may_clobber_ref_p_1): Likewise.
* tree-ssa-structalias.c (find_func_aliases_for_builtin_call,
find_func_clobbers): Likewise.
* tree.h (fold_builtin_strncpy_chk): Rename to fold_builtin_stxncpy_chk
* builtins.c (fold_builtin_strncpy_chk): Likewise.
Rewrite stpncpy_chk calls to strncpy_chk calls if returned value is
ignored.
2011-12-15 Richard Guenther <rguenther@suse.de> 2011-12-15 Richard Guenther <rguenther@suse.de>
PR lto/51567 PR lto/51567
...@@ -6771,6 +6771,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, ...@@ -6771,6 +6771,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
case BUILT_IN_STRCPY_CHK: case BUILT_IN_STRCPY_CHK:
case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_SNPRINTF_CHK:
...@@ -10935,7 +10936,9 @@ fold_builtin_4 (location_t loc, tree fndecl, ...@@ -10935,7 +10936,9 @@ fold_builtin_4 (location_t loc, tree fndecl,
DECL_FUNCTION_CODE (fndecl)); DECL_FUNCTION_CODE (fndecl));
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
return fold_builtin_strncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE); case BUILT_IN_STPNCPY_CHK:
return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
ignore, fcode);
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3); return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
...@@ -12498,6 +12501,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) ...@@ -12498,6 +12501,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
break; break;
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
len = CALL_EXPR_ARG (exp, 2); len = CALL_EXPR_ARG (exp, 2);
size = CALL_EXPR_ARG (exp, 3); size = CALL_EXPR_ARG (exp, 3);
break; break;
...@@ -12852,13 +12856,15 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest, ...@@ -12852,13 +12856,15 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
return build_call_expr_loc (loc, fn, 2, dest, src); return build_call_expr_loc (loc, fn, 2, dest, src);
} }
/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE /* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
are the arguments to the call. If MAXLEN is not NULL, it is maximum are the arguments to the call. If MAXLEN is not NULL, it is maximum
length passed as third argument. */ length passed as third argument. IGNORE is true if return value can be
ignored. FCODE is the BUILT_IN_* code of the builtin. */
tree tree
fold_builtin_strncpy_chk (location_t loc, tree dest, tree src, fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
tree len, tree size, tree maxlen) tree len, tree size, tree maxlen, bool ignore,
enum built_in_function fcode)
{ {
tree fn; tree fn;
...@@ -12868,6 +12874,15 @@ fold_builtin_strncpy_chk (location_t loc, tree dest, tree src, ...@@ -12868,6 +12874,15 @@ fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
|| !validate_arg (size, INTEGER_TYPE)) || !validate_arg (size, INTEGER_TYPE))
return NULL_TREE; return NULL_TREE;
if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
{
/* If return value of __stpncpy_chk is ignored,
optimize into __strncpy_chk. */
fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
if (fn)
return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
}
if (! host_integerp (size, 1)) if (! host_integerp (size, 1))
return NULL_TREE; return NULL_TREE;
...@@ -12888,8 +12903,9 @@ fold_builtin_strncpy_chk (location_t loc, tree dest, tree src, ...@@ -12888,8 +12903,9 @@ fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
return NULL_TREE; return NULL_TREE;
} }
/* If __builtin_strncpy_chk is used, assume strncpy is available. */ /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
fn = builtin_decl_explicit (BUILT_IN_STRNCPY); fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
if (!fn) if (!fn)
return NULL_TREE; return NULL_TREE;
......
...@@ -760,6 +760,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CON ...@@ -760,6 +760,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CON
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY_CHK, "__stpncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
......
...@@ -834,6 +834,7 @@ gimple_fold_builtin (gimple stmt) ...@@ -834,6 +834,7 @@ gimple_fold_builtin (gimple stmt)
case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMSET_CHK: case BUILT_IN_MEMSET_CHK:
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
arg_idx = 2; arg_idx = 2;
type = 2; type = 2;
break; break;
...@@ -940,12 +941,14 @@ gimple_fold_builtin (gimple stmt) ...@@ -940,12 +941,14 @@ gimple_fold_builtin (gimple stmt)
break; break;
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
if (val[2] && is_gimple_val (val[2]) && nargs == 4) if (val[2] && is_gimple_val (val[2]) && nargs == 4)
result = fold_builtin_strncpy_chk (loc, gimple_call_arg (stmt, 0), result = fold_builtin_stxncpy_chk (loc, gimple_call_arg (stmt, 0),
gimple_call_arg (stmt, 1), gimple_call_arg (stmt, 1),
gimple_call_arg (stmt, 2), gimple_call_arg (stmt, 2),
gimple_call_arg (stmt, 3), gimple_call_arg (stmt, 3),
val[2]); val[2], ignore,
DECL_FUNCTION_CODE (callee));
break; break;
case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_SNPRINTF_CHK:
......
2011-12-15 Romain Geissler <romain.geissler@gmail.com>
* gcc.c-torture/execute/builtins/chk.h (stpncpy, stpncpy_disallowed):
New definitions.
* gcc.c-torture/execute/builtins/lib/chk.c (stpncpy_disallowed):
Likewise.
(stpncpy, __stpncpy_chk): New functions.
* gcc.c-torture/execute/builtins/stpncpy-chk-lib.c: New file.
* gcc.c-torture/execute/builtins/stpncpy-chk.c: Likewise.
2011-12-15 Richard Guenther <rguenther@suse.de> 2011-12-15 Richard Guenther <rguenther@suse.de>
PR lto/51567 PR lto/51567
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#undef strncpy #undef strncpy
#define strncpy(dst, src, len) \ #define strncpy(dst, src, len) \
__builtin___strncpy_chk (dst, src, len, os (dst)) __builtin___strncpy_chk (dst, src, len, os (dst))
#undef stpncpy
#define stpncpy(dst, src, len) \
__builtin___stpncpy_chk (dst, src, len, os (dst))
#undef strncat #undef strncat
#define strncat(dst, src, len) \ #define strncat(dst, src, len) \
__builtin___strncat_chk (dst, src, len, os (dst)) __builtin___strncat_chk (dst, src, len, os (dst))
...@@ -76,8 +79,8 @@ extern void *chk_fail_buf[]; ...@@ -76,8 +79,8 @@ extern void *chk_fail_buf[];
extern volatile int chk_fail_allowed, chk_calls; extern volatile int chk_fail_allowed, chk_calls;
extern volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed; extern volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
extern volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed; extern volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
extern volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed; extern volatile int strncpy_disallowed, stpncpy_disallowed, strcat_disallowed;
extern volatile int sprintf_disallowed, vsprintf_disallowed; extern volatile int strncat_disallowed, sprintf_disallowed, vsprintf_disallowed;
extern volatile int snprintf_disallowed, vsnprintf_disallowed; extern volatile int snprintf_disallowed, vsnprintf_disallowed;
/* A storage class that ensures that declarations bind locally. We want /* A storage class that ensures that declarations bind locally. We want
......
...@@ -10,8 +10,8 @@ void *chk_fail_buf[256] __attribute__((aligned (16))); ...@@ -10,8 +10,8 @@ void *chk_fail_buf[256] __attribute__((aligned (16)));
volatile int chk_fail_allowed, chk_calls; volatile int chk_fail_allowed, chk_calls;
volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed; volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed; volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed; volatile int strncpy_disallowed, stpncpy_disallowed, strcat_disallowed;
volatile int sprintf_disallowed, vsprintf_disallowed; volatile int strncat_disallowed, sprintf_disallowed, vsprintf_disallowed;
volatile int snprintf_disallowed, vsnprintf_disallowed; volatile int snprintf_disallowed, vsnprintf_disallowed;
extern __SIZE_TYPE__ strlen (const char *); extern __SIZE_TYPE__ strlen (const char *);
extern int vsprintf (char *, const char *, va_list); extern int vsprintf (char *, const char *, va_list);
...@@ -201,6 +201,38 @@ __stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size) ...@@ -201,6 +201,38 @@ __stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
} }
char * char *
stpncpy (char *dst, const char *src, __SIZE_TYPE__ n)
{
#ifdef __OPTIMIZE__
if (stpncpy_disallowed && inside_main)
abort ();
#endif
for (; *src && n; n--)
*dst++ = *src++;
char *ret = dst;
while (n--)
*dst++ = 0;
return ret;
}
char *
__stpncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
{
/* If size is -1, GCC should always optimize the call into stpncpy. */
if (size == (__SIZE_TYPE__) -1)
abort ();
++chk_calls;
if (n > size)
__chk_fail ();
return stpncpy (s1, s2, n);
}
char *
strncpy (char *s1, const char *s2, __SIZE_TYPE__ n) strncpy (char *s1, const char *s2, __SIZE_TYPE__ n)
{ {
char *dest = s1; char *dest = s1;
......
/* Copyright (C) 2004, 2005, 2011 Free Software Foundation.
Ensure builtin __stpncpy_chk performs correctly. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern size_t strlen(const char *);
extern void *memcpy (void *, const void *, size_t);
extern char *stpncpy (char *, const char *, size_t);
extern int memcmp (const void *, const void *, size_t);
extern int strcmp (const char *, const char *);
extern int strncmp (const char *, const char *, size_t);
extern void *memset (void *, int, size_t);
#include "chk.h"
const char s1[] = "123";
char p[32] = "";
char * volatile s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
char * volatile s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
char *s4;
volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
int i;
void
__attribute__((noinline))
test1 (void)
{
const char *const src = "hello world";
const char *src2;
char dst[64], *dst2;
chk_calls = 0;
memset (dst, 0, sizeof (dst));
if (stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
abort();
memset (dst, 0, sizeof (dst));
if (stpncpy (dst+16, src, 4) != dst+20 || strncmp (dst+16, src, 4))
abort();
memset (dst, 0, sizeof (dst));
if (stpncpy (dst+32, src+5, 4) != dst+36 || strncmp (dst+32, src+5, 4))
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst;
if (stpncpy (++dst2, src+5, 4) != dst+5 || strncmp (dst2, src+5, 4)
|| dst2 != dst+1)
abort();
memset (dst, 0, sizeof (dst));
if (stpncpy (dst, src, 0) != dst || strcmp (dst, ""))
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst; src2 = src;
if (stpncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
|| dst2 != dst+1 || src2 != src+1)
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst; src2 = src;
if (stpncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
|| dst2 != dst+1 || src2 != src+1)
abort();
memset (dst, 0, sizeof (dst));
if (stpncpy (dst, src, 12) != dst+11 || strcmp (dst, src))
abort();
/* Test at least one instance of the __builtin_ style. We do this
to ensure that it works and that the prototype is correct. */
memset (dst, 0, sizeof (dst));
if (__builtin_stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
abort();
memset (dst, 0, sizeof (dst));
if (stpncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst+3
|| strcmp (dst, "bar")
|| i != 1)
abort ();
/* If return value of stpncpy is ignored, it should be optimized into
stpncpy call. */
stpncpy_disallowed = 1;
stpncpy (dst + 1, src, 4);
stpncpy_disallowed = 0;
if (strncmp (dst + 1, src, 4))
abort ();
if (chk_calls)
abort ();
}
void
__attribute__((noinline))
test2 (void)
{
chk_calls = 0;
/* No runtime checking should be done here, both destination
and length are unknown. */
size_t cpy_length = l1 < 4 ? l1 + 1 : 4;
if (stpncpy (s4, "abcd", l1 + 1) != s4 + cpy_length || strncmp (s4, "abcd", cpy_length))
abort ();
if (chk_calls)
abort ();
}
/* Test whether compile time checking is done where it should
and so is runtime object size checking. */
void
__attribute__((noinline))
test3 (void)
{
struct A { char buf1[10]; char buf2[10]; } a;
char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
char buf3[20];
int i;
const char *l;
size_t l2;
/* The following calls should do runtime checking
- source length is not known, but destination is.
The returned value is checked so that stpncpy calls
are not rewritten to strncpy calls. */
chk_calls = 0;
if (!stpncpy (a.buf1 + 2, s3 + 3, l1))
abort();
if (!stpncpy (r, s3 + 2, l1 + 2))
abort();
r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
if (!stpncpy (r, s2 + 2, l1 + 2))
abort();
if (!stpncpy (r + 2, s3 + 3, l1))
abort();
r = buf3;
for (i = 0; i < 4; ++i)
{
if (i == l1 - 1)
r = &a.buf1[1];
else if (i == l1)
r = &a.buf2[7];
else if (i == l1 + 1)
r = &buf3[5];
else if (i == l1 + 2)
r = &a.buf1[9];
}
if (!stpncpy (r, s2 + 4, l1))
abort();
if (chk_calls != 5)
abort ();
/* Following have known destination and known length,
so if optimizing certainly shouldn't result in the checking
variants. */
chk_calls = 0;
if (!stpncpy (a.buf1 + 2, "", 3))
abort ();
if (!stpncpy (a.buf1 + 2, "", 0))
abort ();
if (!stpncpy (r, "a", 1))
abort ();
if (!stpncpy (r, "a", 3))
abort ();
r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
if (!stpncpy (r, s1 + 1, 3))
abort ();
if (!stpncpy (r, s1 + 1, 2))
abort ();
r = buf3;
l = "abc";
l2 = 4;
for (i = 0; i < 4; ++i)
{
if (i == l1 - 1)
r = &a.buf1[1], l = "e", l2 = 2;
else if (i == l1)
r = &a.buf2[7], l = "gh", l2 = 3;
else if (i == l1 + 1)
r = &buf3[5], l = "jkl", l2 = 4;
else if (i == l1 + 2)
r = &a.buf1[9], l = "", l2 = 1;
}
if (!stpncpy (r, "", 1))
abort ();
/* Here, strlen (l) + 1 is known to be at most 4 and
__builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
runtime checking. */
if (!stpncpy (&buf3[16], l, l2))
abort ();
if (!stpncpy (&buf3[15], "abc", l2))
abort ();
if (!stpncpy (&buf3[10], "fghij", l2))
abort ();
if (chk_calls)
abort ();
chk_calls = 0;
}
/* Test whether runtime and/or compile time checking catches
buffer overflows. */
void
__attribute__((noinline))
test4 (void)
{
struct A { char buf1[10]; char buf2[10]; } a;
char buf3[20];
chk_fail_allowed = 1;
/* Runtime checks. */
if (__builtin_setjmp (chk_fail_buf) == 0)
{
if (stpncpy (&a.buf2[9], s2 + 4, l1 + 1))
// returned value used to prevent stpncpy calls
// to be rewritten in strncpy calls
i++;
abort ();
}
if (__builtin_setjmp (chk_fail_buf) == 0)
{
if (stpncpy (&a.buf2[7], s3, l1 + 4))
i++;
abort ();
}
/* This should be detectable at compile time already. */
if (__builtin_setjmp (chk_fail_buf) == 0)
{
if (stpncpy (&buf3[19], "abc", 2))
i++;
abort ();
}
if (__builtin_setjmp (chk_fail_buf) == 0)
{
if (stpncpy (&buf3[18], "", 3))
i++;
abort ();
}
chk_fail_allowed = 0;
}
void
main_test (void)
{
#ifndef __OPTIMIZE__
/* Object size checking is only intended for -O[s123]. */
return;
#endif
__asm ("" : "=r" (s2) : "0" (s2));
__asm ("" : "=r" (s3) : "0" (s3));
__asm ("" : "=r" (l1) : "0" (l1));
test1 ();
s4 = p;
test2 ();
test3 ();
test4 ();
}
...@@ -465,6 +465,7 @@ pass_through_call (const_gimple call) ...@@ -465,6 +465,7 @@ pass_through_call (const_gimple call)
case BUILT_IN_MEMSET_CHK: case BUILT_IN_MEMSET_CHK:
case BUILT_IN_STRCPY_CHK: case BUILT_IN_STRCPY_CHK:
case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
case BUILT_IN_ASSUME_ALIGNED: case BUILT_IN_ASSUME_ALIGNED:
......
...@@ -1223,6 +1223,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref) ...@@ -1223,6 +1223,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMPCPY_CHK:
case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
{ {
ao_ref dref; ao_ref dref;
tree size = NULL_TREE; tree size = NULL_TREE;
...@@ -1560,6 +1561,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) ...@@ -1560,6 +1561,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMPCPY_CHK:
case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
case BUILT_IN_MEMSET_CHK: case BUILT_IN_MEMSET_CHK:
......
...@@ -4022,6 +4022,7 @@ find_func_aliases_for_builtin_call (gimple t) ...@@ -4022,6 +4022,7 @@ find_func_aliases_for_builtin_call (gimple t)
case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMPCPY_CHK:
case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
case BUILT_IN_TM_MEMCPY: case BUILT_IN_TM_MEMCPY:
...@@ -4039,7 +4040,8 @@ find_func_aliases_for_builtin_call (gimple t) ...@@ -4039,7 +4040,8 @@ find_func_aliases_for_builtin_call (gimple t)
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHK || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHK
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY_CHK) || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY_CHK
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY_CHK)
get_constraint_for_ptr_offset (dest, NULL_TREE, &rhsc); get_constraint_for_ptr_offset (dest, NULL_TREE, &rhsc);
else else
get_constraint_for (dest, &rhsc); get_constraint_for (dest, &rhsc);
...@@ -4757,6 +4759,7 @@ find_func_clobbers (gimple origt) ...@@ -4757,6 +4759,7 @@ find_func_clobbers (gimple origt)
case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMPCPY_CHK:
case BUILT_IN_STPCPY_CHK: case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK: case BUILT_IN_STRNCAT_CHK:
{ {
......
...@@ -5429,7 +5429,8 @@ extern tree fold_builtin_memory_chk (location_t, tree, tree, tree, tree, tree, t ...@@ -5429,7 +5429,8 @@ extern tree fold_builtin_memory_chk (location_t, tree, tree, tree, tree, tree, t
enum built_in_function); enum built_in_function);
extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, bool, extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, bool,
enum built_in_function); enum built_in_function);
extern tree fold_builtin_strncpy_chk (location_t, tree, tree, tree, tree, tree); extern tree fold_builtin_stxncpy_chk (location_t, tree, tree, tree, tree, tree, bool,
enum built_in_function);
extern tree fold_builtin_snprintf_chk (location_t, tree, tree, enum built_in_function); extern tree fold_builtin_snprintf_chk (location_t, tree, tree, enum built_in_function);
extern bool fold_builtin_next_arg (tree, bool); extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (const_tree); extern enum built_in_function builtin_mathfn_code (const_tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment