aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-11-10 16:35:26 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-11-10 09:35:26 -0700
commit025d57f037ad13eb479818b677ef4be4d97b639c (patch)
tree28c279950fb42d8f67b86b9a2193b3acc6a669f2 /gcc/builtins.c
parente89ce41dbab07a9acafd900a3ab57eeb5d499276 (diff)
downloadgcc-025d57f037ad13eb479818b677ef4be4d97b639c.zip
gcc-025d57f037ad13eb479818b677ef4be4d97b639c.tar.gz
gcc-025d57f037ad13eb479818b677ef4be4d97b639c.tar.bz2
PR c/81117 - Improve buffer overflow checking in strncpy
gcc/ChangeLog: PR c/81117 * builtins.c (compute_objsize): Handle arrays that compute_builtin_object_size likes to fail for. Make extern. * builtins.h (compute_objsize): Declare. (check_strncpy_sizes): New function. (expand_builtin_strncpy): Call check_strncpy_sizes. * gimple-fold.c (gimple_fold_builtin_strncpy): Implement -Wstringop-truncation. (gimple_fold_builtin_strncat): Same. * gimple.c (gimple_build_call_from_tree): Set call location. * tree-ssa-strlen.c (strlen_to_stridx): New global variable. (maybe_diag_bound_equal_length, is_strlen_related_p): New functions. (handle_builtin_stxncpy, handle_builtin_strncat): Same. (handle_builtin_strlen): Use strlen_to_stridx. (strlen_optimize_stmt): Handle flavors of strncat, strncpy, and stpncpy. Use strlen_to_stridx. (pass_strlen::execute): Release strlen_to_stridx. * doc/invoke.texi (-Wsizeof-pointer-memaccess): Document enhancement. (-Wstringop-truncation): Document new option. gcc/ada/ChangeLog: PR c/81117 * ada/adadecode.c (__gnat_decode): Use memcpy instead of strncpy. * ada/argv.c (__gnat_fill_arg, __gnat_fill_env): Same. gcc/c-family/ChangeLog: PR c/81117 * c-common.c (catenate_strings): Use memcpy instead of strncpy. * c-warn.c (sizeof_pointer_memaccess_warning): Handle arrays. * c.opt (-Wstringop-truncation): New option. gcc/fortran/ChangeLog: PR c/81117 * gcc/fortran/decl.c (build_sym): Use strcpy instead of strncpy. gcc/objc/ChangeLog: PR c/81117 * objc-encoding.c (encode_type): Use memcpy instead of strncpy. gcc/testsuite/ChangeLog: PR c/81117 * c-c++-common/Wsizeof-pointer-memaccess3.c: New test. * c-c++-common/Wstringop-overflow.c: Same. * c-c++-common/Wstringop-truncation.c: Same. * c-c++-common/Wsizeof-pointer-memaccess2.c: Adjust. * c-c++-common/attr-nonstring-2.c: New test. * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Adjust. * g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same. * gcc.dg/torture/pr63554.c: Same. * gcc.dg/Walloca-1.c: Disable macro tracking. From-SVN: r254630
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index a677705..650de0d 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3260,18 +3260,60 @@ check_sizes (int opt, tree exp, tree size, tree maxlen, tree src, tree objsize)
}
/* Helper to compute the size of the object referenced by the DEST
- expression which must of of pointer type, using Object Size type
+ expression which must have pointer type, using Object Size type
OSTYPE (only the least significant 2 bits are used). Return
the size of the object if successful or NULL when the size cannot
be determined. */
-static inline tree
+tree
compute_objsize (tree dest, int ostype)
{
unsigned HOST_WIDE_INT size;
- if (compute_builtin_object_size (dest, ostype & 3, &size))
+
+ /* Only the two least significant bits are meaningful. */
+ ostype &= 3;
+
+ if (compute_builtin_object_size (dest, ostype, &size))
return build_int_cst (sizetype, size);
+ /* Unless computing the largest size (for memcpy and other raw memory
+ functions), try to determine the size of the object from its type. */
+ if (!ostype)
+ return NULL_TREE;
+
+ if (TREE_CODE (dest) == SSA_NAME)
+ {
+ gimple *stmt = SSA_NAME_DEF_STMT (dest);
+ if (!is_gimple_assign (stmt))
+ return NULL_TREE;
+
+ tree_code code = gimple_assign_rhs_code (stmt);
+ if (code != ADDR_EXPR && code != POINTER_PLUS_EXPR)
+ return NULL_TREE;
+
+ dest = gimple_assign_rhs1 (stmt);
+ }
+
+ if (TREE_CODE (dest) != ADDR_EXPR)
+ return NULL_TREE;
+
+ tree type = TREE_TYPE (dest);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TREE_TYPE (type);
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && !array_at_struct_end_p (dest))
+ {
+ /* Return the constant size unless it's zero (that's a zero-length
+ array likely at the end of a struct). */
+ tree size = TYPE_SIZE_UNIT (type);
+ if (size && TREE_CODE (size) == INTEGER_CST
+ && !integer_zerop (size))
+ return size;
+ }
+
return NULL_TREE;
}
@@ -3923,6 +3965,22 @@ expand_builtin_strncat (tree exp, rtx)
return NULL_RTX;
}
+/* Helper to check the sizes of sequences and the destination of calls
+ to __builtin_strncpy (DST, SRC, CNT) and __builtin___strncpy_chk.
+ Returns true on success (no overflow warning), false otherwise. */
+
+static bool
+check_strncpy_sizes (tree exp, tree dst, tree src, tree cnt)
+{
+ tree dstsize = compute_objsize (dst, warn_stringop_overflow - 1);
+
+ if (!check_sizes (OPT_Wstringop_overflow_,
+ exp, cnt, /*maxlen=*/NULL_TREE, src, dstsize))
+ return false;
+
+ return true;
+}
+
/* Expand expression EXP, which is a call to the strncpy builtin. Return
NULL_RTX if we failed the caller should emit a normal call. */
@@ -3941,16 +3999,7 @@ expand_builtin_strncpy (tree exp, rtx target)
/* The length of the source sequence. */
tree slen = c_strlen (src, 1);
- if (warn_stringop_overflow)
- {
- tree destsize = compute_objsize (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, src, destsize);
- }
+ check_strncpy_sizes (exp, dest, src, len);
/* We must be passed a constant len and src parameter. */
if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))