summaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-sprintf.c
diff options
context:
space:
mode:
authormsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-08 00:01:33 +0000
committermsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-08 00:01:33 +0000
commit5aef89381fb540bc0ef1f3e0004629416ab0e106 (patch)
tree1468c5482ab4b2c6c5a92894f2e96f47a742b995 /gcc/gimple-ssa-sprintf.c
parentbd1e4dd017d46a7da221f583c3dc4c0e0af3e542 (diff)
downloadgcc-5aef89381fb540bc0ef1f3e0004629416ab0e106.tar.gz
PR c/53562 - Add -Werror= support for -D_FORTIFY_SOURCE / __builtin___memcpy_chk
PR middle-end/77784 - duplicate warning for snprintf when n > object size PR middle-end/78149 - missing warning on strncpy buffer overflow due to an excessive bound PR middle-end/78138 - missing warnings on buffer overflow with non-constant source length gcc/c-family/ChangeLog: PR c/53562 PR middle-end/77784 PR middle-end/78149 PR middle-end/78138 * c.opt (-Wstringop-overflow): New option. gcc/ChangeLog: PR middle-end/77784 PR middle-end/78149 PR middle-end/78138 * builtins.c (expand_builtin_strcat, expand_builtin_strncat): New functions. (compute_dest_size, get_size_range, check_sizes, check_strncat_sizes) (check_memop_sizes): Same. (expand_builtin_memcpy): Call check memop_sizes. (expand_builtin_mempcpy): Same. (expand_builtin_memset): Same, (expand_builtin_bzero): Same. (expand_builtin_memory_chk): Call check_sizes. (expand_builtin_strcpy): Same. (expand_builtin_strncpy): Same. (maybe_emit_sprintf_chk_warning): Same. (expand_builtin): Handle strcat and strncat. (fini_object_sizes): Reset pointers. (compute_object_size): New function. * gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call): Avoid issuing warnings also issued during built-in expansion. * doc/invoke.texi (Warning Options): Document -Wstringop-overflow. gcc/testsuite/ChangeLog: PR middle-end/77784 PR middle-end/78149 PR middle-end/78138 * c-c++-common/Wsizeof-pointer-memaccess2.c: Adjust expected diagnostic. * g++.dg/ext/builtin-object-size3.C (bar): Same. * g++.dg/ext/strncpy-chk1.C: Same. * g++.dg/opt/memcpy1.C: Same. * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Same. * gcc.c-torture/compile/pr55569.c: Disable -Wstringop-overflow. * gcc.dg/Wobjsize-1.c: Adjust expected diagnostic. * gcc.dg/attr-alloc_size.c: Same. * gcc.dg/builtin-stringop-chk-1.c: Adjust expected diagnostic. * gcc.dg/builtin-stringop-chk-2.c: Same. * gcc.dg/builtin-stringop-chk-4.c: New test. * gcc.dg/builtin-strncat-chk-1.c: Adjust expected diagnostic. * gcc.dg/memcpy-2.c: Same. * gcc.dg/pr40340-1.c: Same. * gcc.dg/pr40340-2.c (main): Same. * gcc.dg/pr40340-5.c (main): Same. * gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Same. * gcc.dg/torture/pr71132.c: Disable -Wstringop-overflow. * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust text of expected warning. * gfortran.dg/char_length_3.f90: Prune expected warnings. * gfortran.dg/pr38868.f: Add expected warnings. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@243419 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimple-ssa-sprintf.c')
-rw-r--r--gcc/gimple-ssa-sprintf.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index e86c4dc71e1..8de9a1e31d2 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -774,7 +774,23 @@ get_width_and_precision (const conversion_spec &spec,
if (spec.star_width)
{
if (TREE_CODE (spec.star_width) == INTEGER_CST)
- width = abs (tree_to_shwi (spec.star_width));
+ {
+ width = tree_to_shwi (spec.star_width);
+ if (width < 0)
+ {
+ if (width == HOST_WIDE_INT_MIN)
+ {
+ /* Avoid undefined behavior due to negating a minimum.
+ This case will be diagnosed since it will result in
+ more than INT_MAX bytes on output, either by the
+ directive itself (when INT_MAX < HOST_WIDE_INT_MAX)
+ or by the format function itself. */
+ width = HOST_WIDE_INT_MAX;
+ }
+ else
+ width = -width;
+ }
+ }
else
width = HOST_WIDE_INT_MIN;
}
@@ -1261,9 +1277,9 @@ format_floating (const conversion_spec &spec, int width, int prec)
res.range.min = 2 + (prec < 0 ? 6 : prec);
/* Compute the maximum just once. */
- static const int f_max[] = {
- format_floating_max (double_type_node, 'f'),
- format_floating_max (long_double_type_node, 'f')
+ const int f_max[] = {
+ format_floating_max (double_type_node, 'f', prec),
+ format_floating_max (long_double_type_node, 'f', prec)
};
res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : f_max [ldbl];
@@ -1279,9 +1295,9 @@ format_floating (const conversion_spec &spec, int width, int prec)
res.range.min = 2 + (prec < 0 ? 6 : prec);
/* Compute the maximum just once. */
- static const int g_max[] = {
- format_floating_max (double_type_node, 'g'),
- format_floating_max (long_double_type_node, 'g')
+ const int g_max[] = {
+ format_floating_max (double_type_node, 'g', prec),
+ format_floating_max (long_double_type_node, 'g', prec)
};
res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : g_max [ldbl];
@@ -2743,19 +2759,27 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
{
dstsize = tree_to_uhwi (size);
/* No object can be larger than SIZE_MAX bytes (half the address
- space) on the target. This imposes a limit that's one byte
- less than that.
+ space) on the target.
The functions are defined only for output of at most INT_MAX
bytes. Specifying a bound in excess of that limit effectively
defeats the bounds checking (and on some implementations such
as Solaris cause the function to fail with EINVAL). */
- if (dstsize >= target_size_max () / 2)
- warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
- "specified destination size %wu is too large",
- dstsize);
+ if (dstsize > target_size_max () / 2)
+ {
+ /* Avoid warning if -Wstringop-overflow is specified since
+ it also warns for the same thing though only for the
+ checking built-ins. */
+ if ((idx_objsize == HOST_WIDE_INT_M1U
+ || !warn_stringop_overflow))
+ warning_at (gimple_location (info.callstmt),
+ OPT_Wformat_length_,
+ "specified bound %wu exceeds maximum object size "
+ "%wu",
+ dstsize, target_size_max () / 2);
+ }
else if (dstsize > target_int_max ())
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
- "specified destination size %wu exceeds %<INT_MAX %>",
+ "specified bound %wu exceeds %<INT_MAX %>",
dstsize);
}
else if (TREE_CODE (size) == SSA_NAME)
@@ -2800,10 +2824,15 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
info.objsize = dstsize < objsize ? dstsize : objsize;
if (info.bounded
- && dstsize < target_size_max () / 2 && objsize < dstsize)
+ && dstsize < target_size_max () / 2 && objsize < dstsize
+ /* Avoid warning if -Wstringop-overflow is specified since
+ it also warns for the same thing though only for the
+ checking built-ins. */
+ && (idx_objsize == HOST_WIDE_INT_M1U
+ || !warn_stringop_overflow))
{
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
- "specified size %wu exceeds the size %wu "
+ "specified bound %wu exceeds the size %wu "
"of the destination object", dstsize, objsize);
}
}