aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-05-04 20:54:43 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-05-04 14:54:43 -0600
commite50d56a502c1140502e498942a739953e85edf1f (patch)
tree052b919e3dc3dfdaf0c430202ec00ab03681aa7a /gcc/builtins.c
parent0f05d90543023e62bb272e6d97d0de3ddc32ab30 (diff)
downloadgcc-e50d56a502c1140502e498942a739953e85edf1f.zip
gcc-e50d56a502c1140502e498942a739953e85edf1f.tar.gz
gcc-e50d56a502c1140502e498942a739953e85edf1f.tar.bz2
PR preprocessor/79214 - -Wno-system-header defeats strncat buffer overflow warnings
PR preprocessor/79214 - -Wno-system-header defeats strncat buffer overflow warnings PR middle-end/79222 - missing -Wstringop-overflow= on a stpcpy overflow PR middle-end/79223 - missing -Wstringop-overflow on a memmove overflow gcc/ChangeLog: PR preprocessor/79214 PR middle-end/79222 PR middle-end/79223 * builtins.c (check_sizes): Add inlinining context and issue warnings even when -Wno-system-headers is set. (check_strncat_sizes): Same. (expand_builtin_strncat): Same. (expand_builtin_memmove): New function. (expand_builtin_stpncpy): Same. (expand_builtin): Handle memmove and stpncpy. gcc/testsuite/ChangeLog: PR preprocessor/79214 PR middle-end/79222 PR middle-end/79223 * gcc.dg/pr79214.c: New test. * gcc.dg/pr79214.h: New test header. * gcc.dg/pr79222.c: New test. * gcc.dg/pr79223.c: New test. * gcc.dg/pr78138.c: Adjust. * gfortran.dg/unconstrained_commons.f: Same. From-SVN: r247618
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c105
1 files changed, 98 insertions, 7 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 5567fd2..9f2e447 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -121,6 +121,7 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode);
static rtx expand_builtin_memcpy (tree, rtx);
static rtx expand_builtin_memcpy_with_bounds (tree, rtx);
static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree);
+static rtx expand_builtin_memmove (tree, rtx);
static rtx expand_builtin_mempcpy (tree, rtx, machine_mode);
static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode);
static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
@@ -129,6 +130,7 @@ static rtx expand_builtin_strcat (tree, rtx);
static rtx expand_builtin_strcpy (tree, rtx);
static rtx expand_builtin_strcpy_args (tree, tree, rtx);
static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
+static rtx expand_builtin_stpncpy (tree, rtx);
static rtx expand_builtin_strncat (tree, rtx);
static rtx expand_builtin_strncpy (tree, rtx);
static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, machine_mode);
@@ -3125,6 +3127,7 @@ check_sizes (int opt, tree exp, tree size, tree maxlen, tree str, tree objsize)
if (range[0] && tree_int_cst_lt (maxobjsize, range[0]))
{
location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
if (range[0] == range[1])
warning_at (loc, opt,
@@ -3157,17 +3160,18 @@ check_sizes (int opt, tree exp, tree size, tree maxlen, tree str, tree objsize)
unsigned HOST_WIDE_INT uwir0 = tree_to_uhwi (range[0]);
location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
if (at_least_one)
warning_at (loc, opt,
- "%K%qD: writing at least %wu byte into a region "
+ "%K%qD writing at least %wu byte into a region "
"of size %wu overflows the destination",
exp, get_callee_fndecl (exp), uwir0,
tree_to_uhwi (objsize));
else if (range[0] == range[1])
warning_at (loc, opt,
(uwir0 == 1
- ? G_("%K%qD: writing %wu byte into a region "
+ ? G_("%K%qD writing %wu byte into a region "
"of size %wu overflows the destination")
: G_("%K%qD writing %wu bytes into a region "
"of size %wu overflows the destination")),
@@ -3175,7 +3179,7 @@ check_sizes (int opt, tree exp, tree size, tree maxlen, tree str, tree objsize)
tree_to_uhwi (objsize));
else
warning_at (loc, opt,
- "%K%qD: writing between %wu and %wu bytes "
+ "%K%qD writing between %wu and %wu bytes "
"into a region of size %wu overflows "
"the destination",
exp, get_callee_fndecl (exp), uwir0,
@@ -3196,6 +3200,7 @@ check_sizes (int opt, tree exp, tree size, tree maxlen, tree str, tree objsize)
if (range[0] && objsize && tree_fits_uhwi_p (objsize))
{
location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
if (tree_int_cst_lt (maxobjsize, range[0]))
{
@@ -3304,6 +3309,24 @@ expand_builtin_memcpy (tree exp, rtx target)
return expand_builtin_memcpy_args (dest, src, len, target, exp);
}
+/* Check a call EXP to the memmove built-in for validity.
+ Return NULL_RTX on both success and failure. */
+
+static rtx
+expand_builtin_memmove (tree exp, rtx)
+{
+ if (!validate_arglist (exp,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return NULL_RTX;
+
+ tree dest = CALL_EXPR_ARG (exp, 0);
+ tree len = CALL_EXPR_ARG (exp, 2);
+
+ check_memop_sizes (exp, dest, len);
+
+ return NULL_RTX;
+}
+
/* Expand an instrumented call EXP to the memcpy builtin.
Return NULL_RTX if we failed, the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
@@ -3614,6 +3637,13 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
dst = CALL_EXPR_ARG (exp, 0);
src = CALL_EXPR_ARG (exp, 1);
+ if (warn_stringop_overflow)
+ {
+ tree destsize = compute_dest_size (dst, warn_stringop_overflow - 1);
+ check_sizes (OPT_Wstringop_overflow_,
+ exp, /*size=*/NULL_TREE, /*maxlen=*/NULL_TREE, src, destsize);
+ }
+
/* If return value is ignored, transform stpcpy into strcpy. */
if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
{
@@ -3674,6 +3704,47 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
}
}
+/* Check a call EXP to the stpncpy built-in for validity.
+ Return NULL_RTX on both success and failure. */
+
+static rtx
+expand_builtin_stpncpy (tree exp, rtx)
+{
+ if (!validate_arglist (exp,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
+ || !warn_stringop_overflow)
+ return NULL_RTX;
+
+ tree dest = CALL_EXPR_ARG (exp, 0);
+ tree src = CALL_EXPR_ARG (exp, 1);
+
+ /* The number of bytes to write (not the maximum). */
+ tree len = CALL_EXPR_ARG (exp, 2);
+ /* The length of the source sequence. */
+ tree slen = c_strlen (src, 1);
+
+ /* Try to determine the range of lengths that the source expression
+ refers to. */
+ tree lenrange[2];
+ if (slen)
+ lenrange[0] = lenrange[1] = slen;
+ else
+ {
+ get_range_strlen (src, lenrange);
+ slen = lenrange[0];
+ }
+
+ tree destsize = compute_dest_size (dest,
+ warn_stringop_overflow - 1);
+
+ /* The number of bytes to write is LEN but check_sizes will also
+ check SLEN if LEN's value isn't known. */
+ check_sizes (OPT_Wstringop_overflow_,
+ exp, len, /*maxlen=*/NULL_TREE, slen, destsize);
+
+ return NULL_RTX;
+}
+
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
bytes from constant string DATA + OFFSET and return it as target
constant. */
@@ -3729,9 +3800,13 @@ check_strncat_sizes (tree exp, tree objsize)
if (tree_fits_uhwi_p (maxlen) && tree_fits_uhwi_p (objsize)
&& tree_int_cst_equal (objsize, maxlen))
{
- warning_at (EXPR_LOCATION (exp), OPT_Wstringop_overflow_,
- "specified bound %wu "
+ location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
+
+ warning_at (loc, OPT_Wstringop_overflow_,
+ "%K%qD: specified bound %wu "
"equals the size of the destination",
+ exp, get_callee_fndecl (exp),
tree_to_uhwi (maxlen));
return false;
@@ -3793,9 +3868,13 @@ expand_builtin_strncat (tree exp, rtx)
if (tree_fits_uhwi_p (maxlen) && tree_fits_uhwi_p (destsize)
&& tree_int_cst_equal (destsize, maxlen))
{
- warning_at (EXPR_LOCATION (exp), OPT_Wstringop_overflow_,
- "specified bound %wu "
+ location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
+
+ warning_at (loc, OPT_Wstringop_overflow_,
+ "%K%qD: specified bound %wu "
"equals the size of the destination",
+ exp, get_callee_fndecl (exp),
tree_to_uhwi (maxlen));
return NULL_RTX;
@@ -6712,12 +6791,24 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return target;
break;
+ case BUILT_IN_STPNCPY:
+ target = expand_builtin_stpncpy (exp, target);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_MEMCPY:
target = expand_builtin_memcpy (exp, target);
if (target)
return target;
break;
+ case BUILT_IN_MEMMOVE:
+ target = expand_builtin_memmove (exp, target);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_MEMPCPY:
target = expand_builtin_mempcpy (exp, target, mode);
if (target)