Commit daa94de2 by Martin Sebor Committed by Martin Sebor

PR middle-end/91977 - missing -Wstringop-overflow on memcpy into a pointer plus offset

gcc/ChangeLog:

	PR middle-end/91977
	* tree-ssa-strlen.c (count_nonzero_bytes): Handle assignments with
	MEM_REF right operand.  Avoid failing for MEM_REF assignments from
	uninitialized objects.

gcc/testsuite/ChangeLog:

	PR middle-end/91977
	* gcc.dg/Wstringop-overflow-18.c: New test.

From-SVN: r276603
parent 28a5fa54
2019-10-04 Martin Sebor <msebor@redhat.com> 2019-10-04 Martin Sebor <msebor@redhat.com>
PR middle-end/91977
* tree-ssa-strlen.c (count_nonzero_bytes): Handle assignments with
MEM_REF right operand. Avoid failing for MEM_REF assignments from
uninitialized objects.
2019-10-04 Martin Sebor <msebor@redhat.com>
* builtins.c (compute_objsize): Add an argument. * builtins.c (compute_objsize): Add an argument.
* tree-object-size.c (addr_object_size): Same. * tree-object-size.c (addr_object_size): Same.
(compute_builtin_object_size): Same. (compute_builtin_object_size): Same.
......
2019-10-04 Martin Sebor <msebor@redhat.com> 2019-10-04 Martin Sebor <msebor@redhat.com>
PR middle-end/91977
* gcc.dg/Wstringop-overflow-18.c: New test.
2019-10-04 Martin Sebor <msebor@redhat.com>
* gcc.dg/Wstringop-overflow-17.c: New test. * gcc.dg/Wstringop-overflow-17.c: New test.
2019-10-04 Steven G. Kargl <kargl@gcc.gnu.org> 2019-10-04 Steven G. Kargl <kargl@gcc.gnu.org>
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -Warray-bounds" } */ /* { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow" } */
typedef struct typedef struct
{ {
......
...@@ -3801,40 +3801,44 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset, ...@@ -3801,40 +3801,44 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
if (TREE_CODE (type) == INTEGER_TYPE if (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_MODE (type) == TYPE_MODE (char_type_node) && TYPE_MODE (type) == TYPE_MODE (char_type_node)
&& TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node)) && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node)
&& tree_expr_nonzero_p (exp))
{ {
/* Determine if the character EXP is known to be non-zero /* If the character EXP is known to be non-zero (even if its
(even if its exact value is not known) and if so, recurse exact value is not known) recurse once to set the range
once to set the range, etc. */ for an arbitrary constant. */
if (tree_expr_nonzero_p (exp)) exp = build_int_cst (type, 1);
return count_nonzero_bytes (build_int_cst (type, 1), return count_nonzero_bytes (exp, offset, 1, lenrange,
offset, nbytes, lenrange, nulterm, allnul, allnonnul, snlim);
nulterm, allnul, allnonnul, snlim);
/* Don't know whether EXP is or isn't nonzero. */
return false;
} }
gimple *stmt = SSA_NAME_DEF_STMT (exp); gimple *stmt = SSA_NAME_DEF_STMT (exp);
if (gimple_code (stmt) != GIMPLE_PHI) if (gimple_assign_single_p (stmt))
return false;
/* Avoid processing an SSA_NAME that has already been visited
or if an SSA_NAME limit has been reached. Indicate success
if the former and failure if the latter. */
if (int res = snlim.next_ssa_name (exp))
return res > 0;
/* Determine the minimum and maximum from the PHI arguments. */
unsigned int n = gimple_phi_num_args (stmt);
for (unsigned i = 0; i != n; i++)
{ {
tree def = gimple_phi_arg_def (stmt, i); exp = gimple_assign_rhs1 (stmt);
if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm, if (TREE_CODE (exp) != MEM_REF)
allnul, allnonnul, snlim))
return false; return false;
} }
else if (gimple_code (stmt) == GIMPLE_PHI)
{
/* Avoid processing an SSA_NAME that has already been visited
or if an SSA_NAME limit has been reached. Indicate success
if the former and failure if the latter. */
if (int res = snlim.next_ssa_name (exp))
return res > 0;
/* Determine the minimum and maximum from the PHI arguments. */
unsigned int n = gimple_phi_num_args (stmt);
for (unsigned i = 0; i != n; i++)
{
tree def = gimple_phi_arg_def (stmt, i);
if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm,
allnul, allnonnul, snlim))
return false;
}
return true; return true;
}
} }
if (TREE_CODE (exp) == MEM_REF) if (TREE_CODE (exp) == MEM_REF)
...@@ -3897,14 +3901,25 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset, ...@@ -3897,14 +3901,25 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
prep = reinterpret_cast <char *>(buf); prep = reinterpret_cast <char *>(buf);
/* Try to extract the representation of the constant object /* Try to extract the representation of the constant object
or expression starting from the offset. */ or expression starting from the offset. */
nbytes = native_encode_expr (exp, buf, sizeof buf, offset); unsigned repsize = native_encode_expr (exp, buf, sizeof buf, offset);
if (!nbytes) if (repsize < nbytes)
return false; {
/* This should only happen when REPSIZE is zero because EXP
doesn't denote an object with a known initializer, except
perhaps when the reference reads past its end. */
lenrange[0] = 0;
prep = NULL;
}
else
nbytes = repsize;
} }
if (!nbytes)
return false;
/* Compute the number of leading nonzero bytes in the representation /* Compute the number of leading nonzero bytes in the representation
and update the minimum and maximum. */ and update the minimum and maximum. */
unsigned n = strnlen (prep, nbytes); unsigned n = prep ? strnlen (prep, nbytes) : nbytes;
if (n < lenrange[0]) if (n < lenrange[0])
lenrange[0] = n; lenrange[0] = n;
......
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