diff options
author | Martin Sebor <msebor@redhat.com> | 2016-12-08 00:01:33 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2016-12-07 17:01:33 -0700 |
commit | ee92e7bafb52d267f52e4c48edada5f279bcf591 (patch) | |
tree | 1468c5482ab4b2c6c5a92894f2e96f47a742b995 /gcc/gimple-ssa-sprintf.c | |
parent | fc3f36f9a1642338da8c0428ea5dc140402556c9 (diff) | |
download | gcc-ee92e7bafb52d267f52e4c48edada5f279bcf591.zip gcc-ee92e7bafb52d267f52e4c48edada5f279bcf591.tar.gz gcc-ee92e7bafb52d267f52e4c48edada5f279bcf591.tar.bz2 |
PR c/53562 - Add -Werror= support for -D_FORTIFY_SOURCE / __builtin___memcpy_chk
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.
From-SVN: r243419
Diffstat (limited to 'gcc/gimple-ssa-sprintf.c')
-rw-r--r-- | gcc/gimple-ssa-sprintf.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index e86c4dc..8de9a1e 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); } } |