diff options
author | Martin Sebor <msebor@redhat.com> | 2017-11-10 16:35:26 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-11-10 09:35:26 -0700 |
commit | 025d57f037ad13eb479818b677ef4be4d97b639c (patch) | |
tree | 28c279950fb42d8f67b86b9a2193b3acc6a669f2 /gcc/builtins.c | |
parent | e89ce41dbab07a9acafd900a3ab57eeb5d499276 (diff) | |
download | gcc-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.c | 75 |
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)) |