PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length
PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length PR middle-end/77708 - -Wformat-length %s warns for snprintf gcc/ChangeLog: PR middle-end/77708 * doc/invoke.texi (Warning Options): Document -Wformat-truncation. * gimple-ssa-sprintf.c (call_info::reval_used, call_info::warnopt): New member functions. (format_directive): Used them. (add_bytes): Same. (pass_sprintf_length::handle_gimple_call): Same. * graphite-sese-to-poly.c (tree_int_to_gmp): Increase buffer size to avoid truncation for any argument. (extract_affine_mul): Same. * tree.c (get_file_function_name): Same. gcc/c-family/ChangeLog: PR middle-end/77708 * c.opt (-Wformat-truncation): New option. gcc/fortran/ChangeLog: PR tree-optimization/78913 PR middle-end/77708 * trans-common.c (build_equiv_decl): Increase buffer size to avoid truncation for any argument. * trans-types.c (gfc_build_logical_type): Same. gcc/testsuite/ChangeLog: PR middle-end/77708 * gcc.dg/tree-ssa/builtin-snprintf-warn-1.c: New test. * gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: New test. * gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: XFAIL test cases failing due to bug 78969. * gcc.dg/format/pr78569.c: Adjust. From-SVN: r244210
This commit is contained in:
parent
1243c42d64
commit
efcc8d387f
@ -1,3 +1,17 @@
|
|||||||
|
2017-01-08 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR middle-end/77708
|
||||||
|
* doc/invoke.texi (Warning Options): Document -Wformat-truncation.
|
||||||
|
* gimple-ssa-sprintf.c (call_info::reval_used, call_info::warnopt):
|
||||||
|
New member functions.
|
||||||
|
(format_directive): Used them.
|
||||||
|
(add_bytes): Same.
|
||||||
|
(pass_sprintf_length::handle_gimple_call): Same.
|
||||||
|
* graphite-sese-to-poly.c (tree_int_to_gmp): Increase buffer size
|
||||||
|
to avoid truncation for any argument.
|
||||||
|
(extract_affine_mul): Same.
|
||||||
|
* tree.c (get_file_function_name): Same.
|
||||||
|
|
||||||
2017-01-01 Jan Hubicka <hubicka@ucw.cz>
|
2017-01-01 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
PR middle-end/77484
|
PR middle-end/77484
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2017-01-08 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR middle-end/77708
|
||||||
|
* c.opt (-Wformat-truncation): New option.
|
||||||
|
|
||||||
2017-01-06 Alexandre Oliva <aoliva@redhat.com>
|
2017-01-06 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
* c-pretty-print.c (pp_c_tree_decl_identifier): Convert 16-bit
|
* c-pretty-print.c (pp_c_tree_decl_identifier): Convert 16-bit
|
||||||
|
@ -537,6 +537,11 @@ Wformat-signedness
|
|||||||
C ObjC C++ ObjC++ Var(warn_format_signedness) Warning
|
C ObjC C++ ObjC++ Var(warn_format_signedness) Warning
|
||||||
Warn about sign differences with format functions.
|
Warn about sign differences with format functions.
|
||||||
|
|
||||||
|
Wformat-truncation
|
||||||
|
C ObjC C++ ObjC++ Warning Alias(Wformat-truncation=, 1, 0)
|
||||||
|
Warn about calls to snprintf and similar functions that truncate output.
|
||||||
|
Same as -Wformat-truncation=1.
|
||||||
|
|
||||||
Wformat-y2k
|
Wformat-y2k
|
||||||
C ObjC C++ ObjC++ Var(warn_format_y2k) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 2, 0)
|
C ObjC C++ ObjC++ Var(warn_format_y2k) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 2, 0)
|
||||||
Warn about strftime formats yielding 2-digit years.
|
Warn about strftime formats yielding 2-digit years.
|
||||||
@ -554,6 +559,10 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_length) Warning
|
|||||||
Warn about function calls with format strings that write past the end
|
Warn about function calls with format strings that write past the end
|
||||||
of the destination region.
|
of the destination region.
|
||||||
|
|
||||||
|
Wformat-truncation=
|
||||||
|
C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
|
||||||
|
Warn about calls to snprintf and similar functions that truncate output.
|
||||||
|
|
||||||
Wignored-qualifiers
|
Wignored-qualifiers
|
||||||
C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra)
|
C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra)
|
||||||
Warn whenever type qualifiers are ignored.
|
Warn whenever type qualifiers are ignored.
|
||||||
|
@ -276,7 +276,8 @@ Objective-C and Objective-C++ Dialects}.
|
|||||||
-Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol
|
-Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol
|
||||||
-Wno-format-contains-nul -Wno-format-extra-args -Wformat-length=@var{n} @gol
|
-Wno-format-contains-nul -Wno-format-extra-args -Wformat-length=@var{n} @gol
|
||||||
-Wformat-nonliteral @gol
|
-Wformat-nonliteral @gol
|
||||||
-Wformat-security -Wformat-signedness -Wformat-y2k -Wframe-address @gol
|
-Wformat-security -Wformat-signedness -Wformat-truncation=@var{n} @gol
|
||||||
|
-Wformat-y2k -Wframe-address @gol
|
||||||
-Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol
|
-Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol
|
||||||
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
|
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
|
||||||
-Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol
|
-Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol
|
||||||
@ -3959,10 +3960,9 @@ Unix Specification says that such unused arguments are allowed.
|
|||||||
@opindex Wformat-length
|
@opindex Wformat-length
|
||||||
@opindex Wno-format-length
|
@opindex Wno-format-length
|
||||||
Warn about calls to formatted input/output functions such as @code{sprintf}
|
Warn about calls to formatted input/output functions such as @code{sprintf}
|
||||||
that might overflow the destination buffer, or about bounded functions such
|
and @code{vsprintf} that might overflow the destination buffer. When the
|
||||||
as @code{snprintf} that might result in output truncation. When the exact
|
exact number of bytes written by a format directive cannot be determined
|
||||||
number of bytes written by a format directive cannot be determined at
|
at compile-time it is estimated based on heuristics that depend on the
|
||||||
compile-time it is estimated based on heuristics that depend on the
|
|
||||||
@var{level} argument and on optimization. While enabling optimization
|
@var{level} argument and on optimization. While enabling optimization
|
||||||
will in most cases improve the accuracy of the warning, it may also
|
will in most cases improve the accuracy of the warning, it may also
|
||||||
result in false positives.
|
result in false positives.
|
||||||
@ -3974,15 +3974,14 @@ result in false positives.
|
|||||||
@opindex Wno-format-length
|
@opindex Wno-format-length
|
||||||
Level @var{1} of @option{-Wformat-length} enabled by @option{-Wformat}
|
Level @var{1} of @option{-Wformat-length} enabled by @option{-Wformat}
|
||||||
employs a conservative approach that warns only about calls that most
|
employs a conservative approach that warns only about calls that most
|
||||||
likely overflow the buffer or result in output truncation. At this
|
likely overflow the buffer. At this level, numeric arguments to format
|
||||||
level, numeric arguments to format directives with unknown values are
|
directives with unknown values are assumed to have the value of one, and
|
||||||
assumed to have the value of one, and strings of unknown length to be
|
strings of unknown length to be empty. Numeric arguments that are known
|
||||||
empty. Numeric arguments that are known to be bounded to a subrange
|
to be bounded to a subrange of their type, or string arguments whose output
|
||||||
of their type, or string arguments whose output is bounded either by
|
is bounded either by their directive's precision or by a finite set of
|
||||||
their directive's precision or by a finite set of string literals, are
|
string literals, are assumed to take on the value within the range that
|
||||||
assumed to take on the value within the range that results in the most
|
results in the most bytes on output. For example, the call to @code{sprintf}
|
||||||
bytes on output. For example, the call to @code{sprintf} below is
|
below is diagnosed because even with both @var{a} and @var{b} equal to zero,
|
||||||
diagnosed because even with both @var{a} and @var{b} equal to zero,
|
|
||||||
the terminating NUL character (@code{'\0'}) appended by the function
|
the terminating NUL character (@code{'\0'}) appended by the function
|
||||||
to the destination buffer will be written past its end. Increasing
|
to the destination buffer will be written past its end. Increasing
|
||||||
the size of the buffer by a single byte is sufficient to avoid the
|
the size of the buffer by a single byte is sufficient to avoid the
|
||||||
@ -3998,14 +3997,13 @@ void f (int a, int b)
|
|||||||
|
|
||||||
@item -Wformat-length=2
|
@item -Wformat-length=2
|
||||||
Level @var{2} warns also about calls that might overflow the destination
|
Level @var{2} warns also about calls that might overflow the destination
|
||||||
buffer or result in truncation given an argument of sufficient length
|
buffer given an argument of sufficient length or magnitude. At level
|
||||||
or magnitude. At level @var{2}, unknown numeric arguments are assumed
|
@var{2}, unknown numeric arguments are assumed to have the minimum
|
||||||
to have the minimum representable value for signed types with a precision
|
representable value for signed types with a precision greater than 1, and
|
||||||
greater than 1, and the maximum representable value otherwise. Unknown
|
the maximum representable value otherwise. Unknown string arguments whose
|
||||||
string arguments whose length cannot be assumed to be bounded either by
|
length cannot be assumed to be bounded either by the directive's precision,
|
||||||
the directive's precision, or by a finite set of string literals they
|
or by a finite set of string literals they may evaluate to, or the character
|
||||||
may evaluate to, or the character array they may point to, are assumed
|
array they may point to, are assumed to be 1 character long.
|
||||||
to be 1 character long.
|
|
||||||
|
|
||||||
At level @var{2}, the call in the example above is again diagnosed, but
|
At level @var{2}, the call in the example above is again diagnosed, but
|
||||||
this time because with @var{a} equal to a 32-bit @code{INT_MIN} the first
|
this time because with @var{a} equal to a 32-bit @code{INT_MIN} the first
|
||||||
@ -4075,6 +4073,35 @@ included in @option{-Wformat-nonliteral}.)
|
|||||||
If @option{-Wformat} is specified, also warn if the format string
|
If @option{-Wformat} is specified, also warn if the format string
|
||||||
requires an unsigned argument and the argument is signed and vice versa.
|
requires an unsigned argument and the argument is signed and vice versa.
|
||||||
|
|
||||||
|
@item -Wformat-truncation
|
||||||
|
@itemx -Wformat-truncation=@var{level}
|
||||||
|
@opindex Wformat-truncation
|
||||||
|
@opindex Wno-format-truncation
|
||||||
|
Warn about calls to formatted input/output functions such as @code{snprintf}
|
||||||
|
and @code{vsnprintf} that might result in output truncation. When the exact
|
||||||
|
number of bytes written by a format directive cannot be determined at
|
||||||
|
compile-time it is estimated based on heuristics that depend on
|
||||||
|
the @var{level} argument and on optimization. While enabling optimization
|
||||||
|
will in most cases improve the accuracy of the warning, it may also result
|
||||||
|
in false positives. Except as noted otherwise, the option uses the same
|
||||||
|
logic @option{-Wformat-length}.
|
||||||
|
|
||||||
|
@table @gcctabopt
|
||||||
|
@item -Wformat-truncation
|
||||||
|
@item -Wformat-truncation=1
|
||||||
|
@opindex Wformat-truncation
|
||||||
|
@opindex Wno-format-length
|
||||||
|
Level @var{1} of @option{-Wformat-truncation} enabled by @option{-Wformat}
|
||||||
|
employs a conservative approach that warns only about calls to bounded
|
||||||
|
functions whose return value is unused and that will most likely result
|
||||||
|
in output truncatation.
|
||||||
|
|
||||||
|
@item -Wformat-truncation=2
|
||||||
|
Level @var{2} warns also about calls to bounded functions whose return
|
||||||
|
value is used and that might result in truncation given an argument of
|
||||||
|
sufficient length or magnitude.
|
||||||
|
@end table
|
||||||
|
|
||||||
@item -Wformat-y2k
|
@item -Wformat-y2k
|
||||||
@opindex Wformat-y2k
|
@opindex Wformat-y2k
|
||||||
@opindex Wno-format-y2k
|
@opindex Wno-format-y2k
|
||||||
@ -8429,8 +8456,8 @@ if (snprintf (buf, "%08x", i) >= sizeof buf)
|
|||||||
|
|
||||||
The @option{-fprintf-return-value} option relies on other optimizations
|
The @option{-fprintf-return-value} option relies on other optimizations
|
||||||
and yields best results with @option{-O2}. It works in tandem with the
|
and yields best results with @option{-O2}. It works in tandem with the
|
||||||
@option{-Wformat-length} option. The @option{-fprintf-return-value}
|
@option{-Wformat-length} and @option{-Wformat-truncation} options.
|
||||||
option is enabled by default.
|
The @option{-fprintf-return-value} option is enabled by default.
|
||||||
|
|
||||||
@item -fno-peephole
|
@item -fno-peephole
|
||||||
@itemx -fno-peephole2
|
@itemx -fno-peephole2
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
2017-01-08 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/78913
|
||||||
|
PR middle-end/77708
|
||||||
|
* trans-common.c (build_equiv_decl): Increase buffer size to avoid
|
||||||
|
truncation for any argument.
|
||||||
|
* trans-types.c (gfc_build_logical_type): Same.
|
||||||
|
|
||||||
2017-01-07 Andre Vehreschild <vehre@gcc.gnu.org>
|
2017-01-07 Andre Vehreschild <vehre@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/78781
|
PR fortran/78781
|
||||||
|
@ -342,7 +342,7 @@ static tree
|
|||||||
build_equiv_decl (tree union_type, bool is_init, bool is_saved)
|
build_equiv_decl (tree union_type, bool is_init, bool is_saved)
|
||||||
{
|
{
|
||||||
tree decl;
|
tree decl;
|
||||||
char name[15];
|
char name[18];
|
||||||
static int serial = 0;
|
static int serial = 0;
|
||||||
|
|
||||||
if (is_init)
|
if (is_init)
|
||||||
|
@ -861,7 +861,7 @@ gfc_build_logical_type (gfc_logical_info *info)
|
|||||||
void
|
void
|
||||||
gfc_init_types (void)
|
gfc_init_types (void)
|
||||||
{
|
{
|
||||||
char name_buf[18];
|
char name_buf[26];
|
||||||
int index;
|
int index;
|
||||||
tree type;
|
tree type;
|
||||||
unsigned n;
|
unsigned n;
|
||||||
|
@ -718,6 +718,18 @@ struct pass_sprintf_length::call_info
|
|||||||
writing any. NOWRITE is cleared in response to the %n directive
|
writing any. NOWRITE is cleared in response to the %n directive
|
||||||
which has side-effects similar to writing output. */
|
which has side-effects similar to writing output. */
|
||||||
bool nowrite;
|
bool nowrite;
|
||||||
|
|
||||||
|
/* Return true if the called function's return value is used. */
|
||||||
|
bool retval_used () const
|
||||||
|
{
|
||||||
|
return gimple_get_lhs (callstmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the warning option corresponding to the called function. */
|
||||||
|
int warnopt () const
|
||||||
|
{
|
||||||
|
return bounded ? OPT_Wformat_truncation_ : OPT_Wformat_length_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return the result of formatting the '%%' directive. */
|
/* Return the result of formatting the '%%' directive. */
|
||||||
@ -1950,8 +1962,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
|
|
||||||
if (fmtres.nullp)
|
if (fmtres.nullp)
|
||||||
{
|
{
|
||||||
fmtwarn (dirloc, pargrange, NULL,
|
fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
|
||||||
OPT_Wformat_length_,
|
|
||||||
"%<%.*s%> directive argument is null",
|
"%<%.*s%> directive argument is null",
|
||||||
(int)cvtlen, cvtbeg);
|
(int)cvtlen, cvtbeg);
|
||||||
|
|
||||||
@ -1986,8 +1997,8 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
"%wu bytes into a region of size %wu")
|
"%wu bytes into a region of size %wu")
|
||||||
: G_("%<%.*s%> directive writing %wu bytes "
|
: G_("%<%.*s%> directive writing %wu bytes "
|
||||||
"into a region of size %wu"));
|
"into a region of size %wu"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
|
||||||
OPT_Wformat_length_, fmtstr,
|
fmtstr,
|
||||||
(int)cvtlen, cvtbeg, fmtres.range.min,
|
(int)cvtlen, cvtbeg, fmtres.range.min,
|
||||||
navail);
|
navail);
|
||||||
}
|
}
|
||||||
@ -2001,7 +2012,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("%<%.*s%> directive writing between %wu and "
|
: G_("%<%.*s%> directive writing between %wu and "
|
||||||
"%wu bytes into a region of size %wu"));
|
"%wu bytes into a region of size %wu"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, fmtres.range.max, navail);
|
fmtres.range.min, fmtres.range.max, navail);
|
||||||
}
|
}
|
||||||
@ -2014,16 +2025,20 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("%<%.*s%> directive writing %wu or more bytes "
|
: G_("%<%.*s%> directive writing %wu or more bytes "
|
||||||
"into a region of size %wu"));
|
"into a region of size %wu"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, navail);
|
fmtres.range.min, navail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (navail < fmtres.range.max
|
else if (navail < fmtres.range.max
|
||||||
&& (((spec.specifier == 's'
|
&& (spec.specifier != 's'
|
||||||
&& fmtres.range.max < HOST_WIDE_INT_MAX)
|
|| fmtres.range.max < HOST_WIDE_INT_MAX)
|
||||||
/* && (spec.precision || spec.star_precision) */)
|
&& ((info.bounded
|
||||||
|| 1 < warn_format_length))
|
&& (!info.retval_used ()
|
||||||
|
|| warn_format_trunc > 1))
|
||||||
|
|| (!info.bounded
|
||||||
|
&& (spec.specifier == 's'
|
||||||
|
|| 1 < warn_format_length))))
|
||||||
{
|
{
|
||||||
/* The maximum directive output is longer than there is
|
/* The maximum directive output is longer than there is
|
||||||
room in the destination and the output length is either
|
room in the destination and the output length is either
|
||||||
@ -2038,7 +2053,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("%<%.*s%> directive writing %wu or more bytes "
|
: G_("%<%.*s%> directive writing %wu or more bytes "
|
||||||
"into a region of size %wu"));
|
"into a region of size %wu"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, navail);
|
fmtres.range.min, navail);
|
||||||
}
|
}
|
||||||
@ -2052,7 +2067,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("%<%.*s%> directive writing between %wu and %wu "
|
: G_("%<%.*s%> directive writing between %wu and %wu "
|
||||||
"bytes into a region of size %wu"));
|
"bytes into a region of size %wu"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, fmtres.range.max,
|
fmtres.range.min, fmtres.range.max,
|
||||||
navail);
|
navail);
|
||||||
@ -2086,7 +2101,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
"into a region of size %wu")));
|
"into a region of size %wu")));
|
||||||
|
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg, fmtres.range.min,
|
(int)cvtlen, cvtbeg, fmtres.range.min,
|
||||||
navail);
|
navail);
|
||||||
}
|
}
|
||||||
@ -2111,7 +2126,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
|
|
||||||
if (fmtres.range.min == fmtres.range.max)
|
if (fmtres.range.min == fmtres.range.max)
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_,
|
info.warnopt (),
|
||||||
"%<%.*s%> directive output of %wu bytes exceeds "
|
"%<%.*s%> directive output of %wu bytes exceeds "
|
||||||
"minimum required size of 4095",
|
"minimum required size of 4095",
|
||||||
(int)cvtlen, cvtbeg, fmtres.range.min);
|
(int)cvtlen, cvtbeg, fmtres.range.min);
|
||||||
@ -2125,7 +2140,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
"bytes exceeds minimum required size of 4095"));
|
"bytes exceeds minimum required size of 4095"));
|
||||||
|
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, fmtres.range.max);
|
fmtres.range.min, fmtres.range.max);
|
||||||
}
|
}
|
||||||
@ -2143,8 +2158,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
to exceed INT_MAX bytes. */
|
to exceed INT_MAX bytes. */
|
||||||
|
|
||||||
if (fmtres.range.min == fmtres.range.max)
|
if (fmtres.range.min == fmtres.range.max)
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
|
||||||
OPT_Wformat_length_,
|
|
||||||
"%<%.*s%> directive output of %wu bytes causes "
|
"%<%.*s%> directive output of %wu bytes causes "
|
||||||
"result to exceed %<INT_MAX%>",
|
"result to exceed %<INT_MAX%>",
|
||||||
(int)cvtlen, cvtbeg, fmtres.range.min);
|
(int)cvtlen, cvtbeg, fmtres.range.min);
|
||||||
@ -2157,7 +2171,7 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||||||
: G_ ("%<%.*s%> directive output between %wu and %wu "
|
: G_ ("%<%.*s%> directive output between %wu and %wu "
|
||||||
"bytes may cause result to exceed %<INT_MAX%>"));
|
"bytes may cause result to exceed %<INT_MAX%>"));
|
||||||
warned = fmtwarn (dirloc, pargrange, NULL,
|
warned = fmtwarn (dirloc, pargrange, NULL,
|
||||||
OPT_Wformat_length_, fmtstr,
|
info.warnopt (), fmtstr,
|
||||||
(int)cvtlen, cvtbeg,
|
(int)cvtlen, cvtbeg,
|
||||||
fmtres.range.min, fmtres.range.max);
|
fmtres.range.min, fmtres.range.max);
|
||||||
}
|
}
|
||||||
@ -2265,7 +2279,11 @@ add_bytes (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("writing a terminating nul past the end "
|
: G_("writing a terminating nul past the end "
|
||||||
"of the destination")));
|
"of the destination")));
|
||||||
|
|
||||||
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_, text);
|
if (!info.bounded
|
||||||
|
|| !boundrange
|
||||||
|
|| !info.retval_used ()
|
||||||
|
|| warn_format_trunc > 1)
|
||||||
|
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2283,8 +2301,12 @@ add_bytes (const pass_sprintf_length::call_info &info,
|
|||||||
: G_("writing format character %#qc at offset %wu past "
|
: G_("writing format character %#qc at offset %wu past "
|
||||||
"the end of the destination")));
|
"the end of the destination")));
|
||||||
|
|
||||||
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_,
|
if (!info.bounded
|
||||||
text, info.fmtstr[off], off);
|
|| !boundrange
|
||||||
|
|| !info.retval_used ()
|
||||||
|
|| warn_format_trunc > 1)
|
||||||
|
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (),
|
||||||
|
text, info.fmtstr[off], off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2351,8 +2373,7 @@ add_bytes (const pass_sprintf_length::call_info &info,
|
|||||||
off + len - !!len);
|
off + len - !!len);
|
||||||
|
|
||||||
if (res->number_chars_min == res->number_chars_max)
|
if (res->number_chars_min == res->number_chars_max)
|
||||||
res->warned = fmtwarn (loc, NULL, NULL,
|
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (),
|
||||||
OPT_Wformat_length_,
|
|
||||||
"output of %wu bytes causes "
|
"output of %wu bytes causes "
|
||||||
"result to exceed %<INT_MAX%>",
|
"result to exceed %<INT_MAX%>",
|
||||||
res->number_chars_min - !end);
|
res->number_chars_min - !end);
|
||||||
@ -2364,8 +2385,7 @@ add_bytes (const pass_sprintf_length::call_info &info,
|
|||||||
"result to exceed %<INT_MAX%>")
|
"result to exceed %<INT_MAX%>")
|
||||||
: G_ ("output between %wu and %wu bytes may cause "
|
: G_ ("output between %wu and %wu bytes may cause "
|
||||||
"result to exceed %<INT_MAX%>"));
|
"result to exceed %<INT_MAX%>"));
|
||||||
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_,
|
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text,
|
||||||
text,
|
|
||||||
res->number_chars_min - !end,
|
res->number_chars_min - !end,
|
||||||
res->number_chars_max - !end);
|
res->number_chars_max - !end);
|
||||||
}
|
}
|
||||||
@ -2970,14 +2990,13 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
|||||||
checking built-ins. */
|
checking built-ins. */
|
||||||
if ((idx_objsize == HOST_WIDE_INT_M1U
|
if ((idx_objsize == HOST_WIDE_INT_M1U
|
||||||
|| !warn_stringop_overflow))
|
|| !warn_stringop_overflow))
|
||||||
warning_at (gimple_location (info.callstmt),
|
warning_at (gimple_location (info.callstmt), info.warnopt (),
|
||||||
OPT_Wformat_length_,
|
|
||||||
"specified bound %wu exceeds maximum object size "
|
"specified bound %wu exceeds maximum object size "
|
||||||
"%wu",
|
"%wu",
|
||||||
dstsize, target_size_max () / 2);
|
dstsize, target_size_max () / 2);
|
||||||
}
|
}
|
||||||
else if (dstsize > target_int_max ())
|
else if (dstsize > target_int_max ())
|
||||||
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
|
warning_at (gimple_location (info.callstmt), info.warnopt (),
|
||||||
"specified bound %wu exceeds %<INT_MAX %>",
|
"specified bound %wu exceeds %<INT_MAX %>",
|
||||||
dstsize);
|
dstsize);
|
||||||
}
|
}
|
||||||
@ -3028,7 +3047,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
|||||||
is not constant. */
|
is not constant. */
|
||||||
location_t loc = gimple_location (info.callstmt);
|
location_t loc = gimple_location (info.callstmt);
|
||||||
warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
|
warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
|
||||||
OPT_Wformat_length_, "null destination pointer");
|
info.warnopt (), "null destination pointer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3044,7 +3063,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
|||||||
&& (idx_objsize == HOST_WIDE_INT_M1U
|
&& (idx_objsize == HOST_WIDE_INT_M1U
|
||||||
|| !warn_stringop_overflow))
|
|| !warn_stringop_overflow))
|
||||||
{
|
{
|
||||||
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
|
warning_at (gimple_location (info.callstmt), info.warnopt (),
|
||||||
"specified bound %wu exceeds the size %wu "
|
"specified bound %wu exceeds the size %wu "
|
||||||
"of the destination object", dstsize, objsize);
|
"of the destination object", dstsize, objsize);
|
||||||
}
|
}
|
||||||
@ -3057,7 +3076,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
|||||||
is not constant. */
|
is not constant. */
|
||||||
location_t loc = gimple_location (info.callstmt);
|
location_t loc = gimple_location (info.callstmt);
|
||||||
warning_at (EXPR_LOC_OR_LOC (info.format, loc),
|
warning_at (EXPR_LOC_OR_LOC (info.format, loc),
|
||||||
OPT_Wformat_length_, "null format string");
|
info.warnopt (), "null format string");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ tree_int_to_gmp (tree t, mpz_t res)
|
|||||||
static isl_id *
|
static isl_id *
|
||||||
isl_id_for_pbb (scop_p s, poly_bb_p pbb)
|
isl_id_for_pbb (scop_p s, poly_bb_p pbb)
|
||||||
{
|
{
|
||||||
char name[10];
|
char name[14];
|
||||||
snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
|
snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
|
||||||
return isl_id_alloc (s->isl_context, name, pbb);
|
return isl_id_alloc (s->isl_context, name, pbb);
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
|
|||||||
static isl_id *
|
static isl_id *
|
||||||
isl_id_for_ssa_name (scop_p s, tree e)
|
isl_id_for_ssa_name (scop_p s, tree e)
|
||||||
{
|
{
|
||||||
char name1[10];
|
char name1[14];
|
||||||
snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
|
snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
|
||||||
return isl_id_alloc (s->isl_context, name1, e);
|
return isl_id_alloc (s->isl_context, name1, e);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2017-01-08 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR middle-end/77708
|
||||||
|
* gcc.dg/tree-ssa/builtin-snprintf-warn-1.c: New test.
|
||||||
|
* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: New test.
|
||||||
|
* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: XFAIL test cases failing
|
||||||
|
due to bug 78969.
|
||||||
|
* gcc.dg/format/pr78569.c: Adjust.
|
||||||
|
|
||||||
2017-01-07 David Malcolm <dmalcolm@redhat.com>
|
2017-01-07 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
PR c++/72803
|
PR c++/72803
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-Wformat-length" } */
|
/* { dg-options "-Wformat-truncation" } */
|
||||||
|
|
||||||
/* A run of blank lines, so that we would fail the assertion in input.c:1388:
|
/* A run of blank lines, so that we would fail the assertion in input.c:1388:
|
||||||
gcc_assert (line_width >= (start.column - 1 + literal_length)); */
|
gcc_assert (line_width >= (start.column - 1 + literal_length)); */
|
||||||
|
73
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-1.c
Normal file
73
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-1.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -Wformat -Wformat-truncation=1 -ftrack-macro-expansion=0" } */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char a0[0];
|
||||||
|
char a1[1];
|
||||||
|
char a2[2];
|
||||||
|
char a3[3];
|
||||||
|
char a4[4];
|
||||||
|
char ax[];
|
||||||
|
} Arrays;
|
||||||
|
|
||||||
|
char buffer[1024];
|
||||||
|
#define buffer(size) (buffer + sizeof buffer - size)
|
||||||
|
|
||||||
|
int value_range (int min, int max)
|
||||||
|
{
|
||||||
|
extern int value (void);
|
||||||
|
int val = value ();
|
||||||
|
return val < min || max < val ? min : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R(min, max) value_range (min, max)
|
||||||
|
|
||||||
|
/* Verify that calls to snprintf whose return value is unused are
|
||||||
|
diagnosed if certain or possible truncation is detected. */
|
||||||
|
|
||||||
|
#define T(size, ...) \
|
||||||
|
__builtin_snprintf (buffer (size), size, __VA_ARGS__)
|
||||||
|
|
||||||
|
void test_int_retval_unused (void)
|
||||||
|
{
|
||||||
|
T (2, "%i", 123); /* { dg-warning "output truncated" } */
|
||||||
|
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
|
||||||
|
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_retval_unused (const Arrays *ar)
|
||||||
|
{
|
||||||
|
T (1, "%-s", ar->a0);
|
||||||
|
T (1, "%-s", ar->a1);
|
||||||
|
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Verify that calls to snprintf whose return value is used are
|
||||||
|
diagnosed only if certain truncation is detected but not when
|
||||||
|
truncation is only possible but not certain. */
|
||||||
|
|
||||||
|
volatile int retval;
|
||||||
|
|
||||||
|
#undef T
|
||||||
|
#define T(size, ...) \
|
||||||
|
retval = __builtin_snprintf (buffer (size), size, __VA_ARGS__)
|
||||||
|
|
||||||
|
void test_int_retval_used (void)
|
||||||
|
{
|
||||||
|
T (2, "%i", 123); /* { dg-warning "output truncated" } */
|
||||||
|
T (2, "%i", R (1, 99));
|
||||||
|
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
|
||||||
|
T (3, "%i%i", R (1, 99), R (1, 99));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_retval_used (const Arrays *ar)
|
||||||
|
{
|
||||||
|
T (1, "%-s", ar->a0);
|
||||||
|
T (1, "%-s", ar->a1);
|
||||||
|
T (1, "%-s", ar->a2);
|
||||||
|
T (1, "%-s", ar->a4);
|
||||||
|
T (1, "%-s", "123"); /* { dg-warning "output truncated" } */
|
||||||
|
}
|
70
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-2.c
Normal file
70
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-2.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -Wformat -Wformat-truncation=2 -ftrack-macro-expansion=0" } */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char a0[0];
|
||||||
|
char a1[1];
|
||||||
|
char a2[2];
|
||||||
|
char a3[3];
|
||||||
|
char a4[4];
|
||||||
|
char ax[];
|
||||||
|
} Arrays;
|
||||||
|
|
||||||
|
char buffer[1024];
|
||||||
|
#define buffer(size) (buffer + sizeof buffer - size)
|
||||||
|
|
||||||
|
int value_range (int min, int max)
|
||||||
|
{
|
||||||
|
extern int value (void);
|
||||||
|
int val = value ();
|
||||||
|
return val < min || max < val ? min : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R(min, max) value_range (min, max)
|
||||||
|
|
||||||
|
/* Verify that calls to snprintf whose return value is unused are
|
||||||
|
diagnosed if certain or possible truncation is detected. */
|
||||||
|
|
||||||
|
#define T(size, ...) \
|
||||||
|
__builtin_snprintf (buffer (size), size, __VA_ARGS__)
|
||||||
|
|
||||||
|
void test_int_retval_unused (void)
|
||||||
|
{
|
||||||
|
T (2, "%i", 123); /* { dg-warning "output truncated" } */
|
||||||
|
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
|
||||||
|
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_retval_unused (const Arrays *ar)
|
||||||
|
{
|
||||||
|
T (1, "%-s", ar->a0);
|
||||||
|
T (1, "%-s", ar->a1);
|
||||||
|
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Verify that (at -Wformat-trunc=2) calls to snprintf whose return value
|
||||||
|
is used are diagnosed the same way as those whose value is unused. */
|
||||||
|
|
||||||
|
volatile int retval;
|
||||||
|
|
||||||
|
#undef T
|
||||||
|
#define T(size, ...) \
|
||||||
|
retval = __builtin_snprintf (buffer (size), size, __VA_ARGS__)
|
||||||
|
|
||||||
|
void test_int_retval_used (void)
|
||||||
|
{
|
||||||
|
T (2, "%i", 123); /* { dg-warning "output truncated" } */
|
||||||
|
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
|
||||||
|
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_retval_used (const Arrays *ar)
|
||||||
|
{
|
||||||
|
T (1, "%-s", ar->a0);
|
||||||
|
T (1, "%-s", ar->a1);
|
||||||
|
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
|
||||||
|
}
|
@ -51,7 +51,8 @@ void fuint (unsigned j, char *p)
|
|||||||
{
|
{
|
||||||
if (j > 999)
|
if (j > 999)
|
||||||
return;
|
return;
|
||||||
snprintf (p, 4, "%3u", j);
|
|
||||||
|
snprintf (p, 4, "%3u", j); /* { dg-bogus "may be truncated" "unsigned int" { xfail *-*-* } } */
|
||||||
}
|
}
|
||||||
|
|
||||||
void fint (int j, char *p)
|
void fint (int j, char *p)
|
||||||
@ -61,8 +62,7 @@ void fint (int j, char *p)
|
|||||||
if (k > 999)
|
if (k > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Range info isn't available here. */
|
snprintf (p, 4, "%3u", k); /* { dg-bogus "may be truncated" "signed int" { xfail *-*-* } } */
|
||||||
snprintf (p, 4, "%3u", k);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fulong (unsigned long j, char *p)
|
void fulong (unsigned long j, char *p)
|
||||||
@ -70,8 +70,7 @@ void fulong (unsigned long j, char *p)
|
|||||||
if (j > 999)
|
if (j > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Range info isn't available here. */
|
snprintf (p, 4, "%3lu", j); /* { dg-bogus "may be truncated" "unsigned long" { xfail *-*-* } } */
|
||||||
snprintf (p, 4, "%3lu", j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flong (long j, char *p)
|
void flong (long j, char *p)
|
||||||
@ -81,8 +80,7 @@ void flong (long j, char *p)
|
|||||||
if (k > 999)
|
if (k > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Range info isn't available here. */
|
snprintf (p, 4, "%3lu", k); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
|
||||||
snprintf (p, 4, "%3lu", k);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullong (unsigned long long j, char *p)
|
void fullong (unsigned long long j, char *p)
|
||||||
@ -90,18 +88,17 @@ void fullong (unsigned long long j, char *p)
|
|||||||
if (j > 999)
|
if (j > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Range info isn't available here. */
|
snprintf (p, 4, "%3llu", j); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
|
||||||
snprintf (p, 4, "%3llu", j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fllong (long j, char *p)
|
void fllong (long long j, char *p)
|
||||||
{
|
{
|
||||||
const unsigned long long k = (unsigned long long) j;
|
const unsigned long long k = (unsigned long long) j;
|
||||||
|
|
||||||
if (k > 999)
|
if (k > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
snprintf (p, 4, "%3llu", k);
|
snprintf (p, 4, "%3llu", k); /* { dg-bogus "may be truncated" "unsigned long long" { xfail *-*-* } } */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
|
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
|
||||||
|
@ -9746,10 +9746,10 @@ get_file_function_name (const char *type)
|
|||||||
file = LOCATION_FILE (input_location);
|
file = LOCATION_FILE (input_location);
|
||||||
|
|
||||||
len = strlen (file);
|
len = strlen (file);
|
||||||
q = (char *) alloca (9 + 17 + len + 1);
|
q = (char *) alloca (9 + 19 + len + 1);
|
||||||
memcpy (q, file, len + 1);
|
memcpy (q, file, len + 1);
|
||||||
|
|
||||||
snprintf (q + len, 9 + 17 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
|
snprintf (q + len, 9 + 19 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
|
||||||
crc32_string (0, name), get_random_seed (false));
|
crc32_string (0, name), get_random_seed (false));
|
||||||
|
|
||||||
p = q;
|
p = q;
|
||||||
|
Loading…
Reference in New Issue
Block a user