* [PATCH] correct handling of non-constant width and precision (pr 78521)
@ 2016-11-28 3:34 Martin Sebor
2016-11-28 20:26 ` Jeff Law
` (2 more replies)
0 siblings, 3 replies; 20+ messages in thread
From: Martin Sebor @ 2016-11-28 3:34 UTC (permalink / raw)
To: Gcc Patch List
[-- Attachment #1: Type: text/plain, Size: 1213 bytes --]
PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
thing (i.e., the -Wformat-length and -fprintf-return-value options
behave incorrectly) when a conversion specification includes a width
or precision with a non-constant value. The code treats such cases
as if they were not provided which is incorrect and results in
the wrong bytes counts in warning messages and in the wrong ranges
being generated for such calls (or in the case sprintf(0, 0, ...)
for some such calls being eliminated).
The attached patch corrects the handling of these cases, plus a couple
of other edge cases in the same area: it adjusts the parser to accept
precision in the form of just a period with no asterisk or decimal
digits after it (this sets the precision to zero), and corrects the
handling of zero precision and zero argument in integer directives
to produce no bytes on output.
Finally, the patch also tightens up the constraint on the upper bound
of bounded functions like snprintf to be INT_MAX. The functions cannot
produce output in excess of INT_MAX + 1 bytes and some implementations
(e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
This is the subject of PR 78520.
Thanks
Martin
[-- Attachment #2: gcc-78521.diff --]
[-- Type: text/x-patch, Size: 51442 bytes --]
PR middle-end/78521 - [7 Regression] incorrect byte count in -Wformat-length warning with non-constant width or precision
PR middle-end/78520 - missing warning for snprintf with size greater than INT_MAX
gcc/ChangeLog:
PR middle-end/78521
PR middle-end/78520
* gimple-ssa-sprintf.c (target_max_value): Remove.
(target_int_max, target_size_max): Use TYPE_MAX_VALUE.
(get_width_and_precision): New function.
(format_integer, format_floating, get_string_length, format_string):
Correct handling of width and precision with unknown value.
(format_directive): Add warning.
(pass_sprintf_length::compute_format_length): Allow for precision
to consist of a sole period with no asterisk or digits after it.
gcc/testsuite/ChangeLog:
PR middle-end/78521
PR middle-end/78520
* gcc.dg/tree-ssa/builtin-sprintf-5.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-6.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Add test cases.
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index dc2b66d..9f07503 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -235,23 +235,12 @@ target_int_min ()
return int_min;
}
-/* Return the largest value for TYPE on the target. */
-
-static unsigned HOST_WIDE_INT
-target_max_value (tree type)
-{
- const unsigned HOST_WIDE_INT max_value
- = HOST_WIDE_INT_M1U >> (HOST_BITS_PER_WIDE_INT
- - TYPE_PRECISION (type) + 1);
- return max_value;
-}
-
/* Return the value of INT_MAX for the target. */
static inline unsigned HOST_WIDE_INT
target_int_max ()
{
- return target_max_value (integer_type_node);
+ return tree_to_uhwi (TYPE_MAX_VALUE (integer_type_node));
}
/* Return the value of SIZE_MAX for the target. */
@@ -259,7 +248,7 @@ target_int_max ()
static inline unsigned HOST_WIDE_INT
target_size_max ()
{
- return target_max_value (size_type_node);
+ return tree_to_uhwi (TYPE_MAX_VALUE (size_type_node));
}
/* Return the constant initial value of DECL if available or DECL
@@ -843,6 +832,43 @@ format_pointer (const conversion_spec &spec, tree arg)
return res;
}
+/* Set *PWIDTH and *PPREC according to the width and precision specified
+ in SPEC. Each is set to HOST_WIDE_INT_MIN when the corresponding
+ field is specified but unknown, to zero for width and -1, respectively
+ when it's not specified, or to a non-negative value corresponding to
+ the known value. */
+static void
+get_width_and_precision (const conversion_spec &spec,
+ HOST_WIDE_INT *pwidth, HOST_WIDE_INT *pprec)
+{
+ HOST_WIDE_INT width = spec.have_width ? spec.width : 0;
+ HOST_WIDE_INT prec = spec.have_precision ? spec.precision : -1;
+
+ if (spec.star_width)
+ {
+ if (TREE_CODE (spec.star_width) == INTEGER_CST)
+ width = abs (tree_to_shwi (spec.star_width));
+ else
+ width = HOST_WIDE_INT_MIN;
+ }
+
+ if (spec.star_precision)
+ {
+ if (TREE_CODE (spec.star_precision) == INTEGER_CST)
+ {
+ prec = tree_to_shwi (spec.star_precision);
+ if (prec < 0)
+ prec = 0;
+ }
+ else
+ prec = HOST_WIDE_INT_MIN;
+ }
+
+ *pwidth = width;
+ *pprec = prec;
+}
+
+
/* Return a range representing the minimum and maximum number of bytes
that the conversion specification SPEC will write on output for the
integer argument ARG when non-null. ARG may be null (for vararg
@@ -860,18 +886,10 @@ format_integer (const conversion_spec &spec, tree arg)
if (!intmax_type_node)
build_intmax_type_nodes (&intmax_type_node, &uintmax_type_node);
- /* Set WIDTH and PRECISION to either the values in the format
- specification or to zero. */
- int width = spec.have_width ? spec.width : 0;
- int prec = spec.have_precision ? spec.precision : 0;
-
- if (spec.star_width)
- width = (TREE_CODE (spec.star_width) == INTEGER_CST
- ? tree_to_shwi (spec.star_width) : 0);
-
- if (spec.star_precision)
- prec = (TREE_CODE (spec.star_precision) == INTEGER_CST
- ? tree_to_shwi (spec.star_precision) : 0);
+ /* Set WIDTH and PRECISION based on the specification. */
+ HOST_WIDE_INT width;
+ HOST_WIDE_INT prec;
+ get_width_and_precision (spec, &width, &prec);
bool sign = spec.specifier == 'd' || spec.specifier == 'i';
@@ -940,15 +958,8 @@ format_integer (const conversion_spec &spec, tree arg)
}
else if (TREE_CODE (arg) == INTEGER_CST)
{
- /* The minimum and maximum number of bytes produced by
- the directive. */
- fmtresult res;
-
/* When a constant argument has been provided use its value
rather than type to determine the length of the output. */
- res.bounded = true;
- res.constant = true;
- res.knownrange = true;
/* Base to format the number in. */
int base;
@@ -981,25 +992,56 @@ format_integer (const conversion_spec &spec, tree arg)
gcc_unreachable ();
}
- /* Convert the argument to the type of the directive. */
- arg = fold_convert (dirtype, arg);
+ int len;
+
+ if ((prec == HOST_WIDE_INT_MIN || prec == 0) && integer_zerop (arg))
+ {
+ /* As a special case, a precision of zero with an argument
+ of zero results in zero bytes regardless of flags (with
+ width having the normal effect). This must extend to
+ the case of a specified precision with an unknown value
+ because it can be zero. */
+ len = 0;
+ }
+ else
+ {
+ /* Convert the argument to the type of the directive. */
+ arg = fold_convert (dirtype, arg);
- maybesign |= spec.get_flag ('+');
+ maybesign |= spec.get_flag ('+');
- /* True when a conversion is preceded by a prefix indicating the base
- of the argument (octal or hexadecimal). */
- bool maybebase = spec.get_flag ('#');
- int len = tree_digits (arg, base, maybesign, maybebase);
+ /* True when a conversion is preceded by a prefix indicating the base
+ of the argument (octal or hexadecimal). */
+ bool maybebase = spec.get_flag ('#');
+ len = tree_digits (arg, base, maybesign, maybebase);
- if (len < prec)
- len = prec;
+ if (len < prec)
+ len = prec;
+ }
if (len < width)
len = width;
- res.range.max = len;
- res.range.min = res.range.max;
- res.bounded = true;
+ /* The minimum and maximum number of bytes produced by the directive. */
+ fmtresult res;
+
+ res.range.min = len;
+
+ /* The upper bound of the number of bytes is unlimited when either
+ width or precision is specified but its value is unknown, and
+ the same as the lower bound otherwise. */
+ if (width == HOST_WIDE_INT_MIN || prec == HOST_WIDE_INT_MIN)
+ {
+ res.range.max = HOST_WIDE_INT_MAX;
+ }
+ else
+ {
+ res.range.max = len;
+ res.bounded = true;
+ res.constant = true;
+ res.knownrange = true;
+ res.bounded = true;
+ }
return res;
}
@@ -1110,8 +1152,10 @@ format_integer (const conversion_spec &spec, tree arg)
or one whose value range cannot be determined, create a T_MIN
constant if the argument's type is signed and T_MAX otherwise,
and use those to compute the range of bytes that the directive
- can output. */
- argmin = build_int_cst (argtype, 1);
+ can output. When precision is specified but unknown, use zero
+ as the minimum since it results in no bytes on output (unless
+ width is specified to be greater than 0). */
+ argmin = build_int_cst (argtype, prec != HOST_WIDE_INT_MIN);
int typeprec = TYPE_PRECISION (dirtype);
int argprec = TYPE_PRECISION (argtype);
@@ -1261,11 +1305,13 @@ format_floating (const conversion_spec &spec, int width, int prec)
{
/* The minimum output is "0x.p+0". */
res.range.min = 6 + (prec > 0 ? prec : 0);
- res.range.max = format_floating_max (type, 'a', prec);
+ res.range.max = (width == INT_MIN
+ ? HOST_WIDE_INT_MAX
+ : format_floating_max (type, 'a', prec));
/* The output of "%a" is fully specified only when precision
- is explicitly specified. */
- res.bounded = -1 < prec;
+ is explicitly specified and width isn't unknown. */
+ res.bounded = INT_MIN != width && -1 < prec;
break;
}
@@ -1278,13 +1324,16 @@ format_floating (const conversion_spec &spec, int width, int prec)
res.range.min = (sign
+ 1 /* unit */ + (prec < 0 ? 7 : prec ? prec + 1 : 0)
+ 2 /* e+ */ + 2);
- /* The maximum output is the minimum plus sign (unless already
- included), plus the difference between the minimum exponent
- of 2 and the maximum exponent for the type. */
- res.range.max = res.range.min + !sign + logexpdigs - 2;
-
- /* "%e" is fully specified and the range of bytes is bounded. */
- res.bounded = true;
+ /* Unless width is uknown the maximum output is the minimum plus
+ sign (unless already included), plus the difference between
+ the minimum exponent of 2 and the maximum exponent for the type. */
+ res.range.max = (width == INT_MIN
+ ? HOST_WIDE_INT_M1U
+ : res.range.min + !sign + logexpdigs - 2);
+
+ /* "%e" is fully specified and the range of bytes is bounded
+ unless width is unknown. */
+ res.bounded = INT_MIN != width;
break;
}
@@ -1300,10 +1349,11 @@ format_floating (const conversion_spec &spec, int width, int prec)
format_floating_max (double_type_node, 'f'),
format_floating_max (long_double_type_node, 'f')
};
- res.range.max = f_max [ldbl];
+ res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : f_max [ldbl];
- /* "%f" is fully specified and the range of bytes is bounded. */
- res.bounded = true;
+ /* "%f" is fully specified and the range of bytes is bounded
+ unless width is unknown. */
+ res.bounded = INT_MIN != width;
break;
}
case 'G':
@@ -1317,10 +1367,11 @@ format_floating (const conversion_spec &spec, int width, int prec)
format_floating_max (double_type_node, 'g'),
format_floating_max (long_double_type_node, 'g')
};
- res.range.max = g_max [ldbl];
+ res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : g_max [ldbl];
- /* "%g" is fully specified and the range of bytes is bounded. */
- res.bounded = true;
+ /* "%g" is fully specified and the range of bytes is bounded
+ unless width is unknown. */
+ res.bounded = INT_MIN != width;
break;
}
@@ -1346,6 +1397,9 @@ format_floating (const conversion_spec &spec, int width, int prec)
static fmtresult
format_floating (const conversion_spec &spec, tree arg)
{
+ /* Set WIDTH to -1 when it's not specified, to INT_MIN when it is
+ specified by the asterisk to an unknown value, and otherwise to
+ a non-negative value corresponding to the specified width. */
int width = -1;
int prec = -1;
@@ -1358,12 +1412,13 @@ format_floating (const conversion_spec &spec, tree arg)
else if (spec.star_width)
{
if (TREE_CODE (spec.star_width) == INTEGER_CST)
- width = tree_to_shwi (spec.star_width);
- else
{
- res.range.min = res.range.max = HOST_WIDE_INT_M1U;
- return res;
+ width = tree_to_shwi (spec.star_width);
+ if (width < 0)
+ width = -width;
}
+ else
+ width = INT_MIN;
}
if (spec.have_precision)
@@ -1374,6 +1429,7 @@ format_floating (const conversion_spec &spec, tree arg)
prec = tree_to_shwi (spec.star_precision);
else
{
+ /* FIXME: Handle non-constant precision. */
res.range.min = res.range.max = HOST_WIDE_INT_M1U;
return res;
}
@@ -1413,9 +1469,9 @@ format_floating (const conversion_spec &spec, tree arg)
*pfmt++ = *pf;
/* Append width when specified and precision. */
- if (width != -1)
+ if (-1 < width)
pfmt += sprintf (pfmt, "%i", width);
- if (prec != -1)
+ if (-1 < prec)
pfmt += sprintf (pfmt, ".%i", prec);
/* Append the MPFR 'R' floating type specifier (no length modifier
@@ -1442,16 +1498,24 @@ format_floating (const conversion_spec &spec, tree arg)
*minmax[i] = mpfr_snprintf (NULL, 0, fmtstr, mpfrval);
}
+ /* The range of output is known even if the result isn't bounded. */
+ if (width == INT_MIN)
+ {
+ res.knownrange = false;
+ res.range.max = HOST_WIDE_INT_MAX;
+ }
+ else
+ res.knownrange = true;
+
/* The output of all directives except "%a" is fully specified
and so the result is bounded unless it exceeds INT_MAX.
For "%a" the output is fully specified only when precision
is explicitly specified. */
- res.bounded = ((TOUPPER (spec.specifier) != 'A'
- || (0 <= prec && (unsigned) prec < target_int_max ()))
+ res.bounded = (res.knownrange
+ && (TOUPPER (spec.specifier) != 'A'
+ || (0 <= prec && (unsigned) prec < target_int_max ()))
&& res.range.min < target_int_max ());
- /* The range of output is known even if the result isn't bounded. */
- res.knownrange = true;
return res;
}
@@ -1521,20 +1585,10 @@ get_string_length (tree str)
static fmtresult
format_string (const conversion_spec &spec, tree arg)
{
- unsigned width = spec.have_width && spec.width > 0 ? spec.width : 0;
- int prec = spec.have_precision ? spec.precision : -1;
-
- if (spec.star_width)
- {
- width = (TREE_CODE (spec.star_width) == INTEGER_CST
- ? tree_to_shwi (spec.star_width) : 0);
- if (width > INT_MAX)
- width = 0;
- }
-
- if (spec.star_precision)
- prec = (TREE_CODE (spec.star_precision) == INTEGER_CST
- ? tree_to_shwi (spec.star_precision) : -1);
+ /* Set WIDTH and PRECISION based on the specification. */
+ HOST_WIDE_INT width;
+ HOST_WIDE_INT prec;
+ get_width_and_precision (spec, &width, &prec);
fmtresult res;
@@ -1594,11 +1648,12 @@ format_string (const conversion_spec &spec, tree arg)
res.range = slen.range;
/* The output of "%s" and "%ls" directives with a constant
- string is in a known range. For "%s" it is the length
- of the string. For "%ls" it is in the range [length,
- length * MB_LEN_MAX]. (The final range can be further
- constrained by width and precision but it's always known.) */
- res.knownrange = true;
+ string is in a known range unless width of an unknown value
+ is specified. For "%s" it is the length of the string. For
+ "%ls" it is in the range [length, length * MB_LEN_MAX].
+ (The final range can be further constrained by width and
+ precision but it's always known.) */
+ res.knownrange = -1 < width;
if (spec.modifier == FMT_LEN_l)
{
@@ -1626,19 +1681,32 @@ format_string (const conversion_spec &spec, tree arg)
if (0 <= prec)
res.range.max = prec;
}
- else
+ else if (0 <= width)
{
- /* The output od a "%s" directive with a constant argument
- is bounded, constant, and obviously in a known range. */
+ /* The output of a "%s" directive with a constant argument
+ and constant or no width is bounded. It is constant if
+ precision is either not specified or it is specified and
+ its value is known. */
res.bounded = true;
- res.constant = true;
+ res.constant = prec != HOST_WIDE_INT_MIN;
+ }
+ else if (width == HOST_WIDE_INT_MIN)
+ {
+ /* Specified but unknown width makes the output unbounded. */
+ res.range.max = HOST_WIDE_INT_MAX;
}
- if (0 <= prec && (unsigned)prec < res.range.min)
+ if (0 <= prec && (unsigned HOST_WIDE_INT)prec < res.range.min)
{
res.range.min = prec;
res.range.max = prec;
}
+ else if (prec == HOST_WIDE_INT_MIN)
+ {
+ /* When precision is specified but not known the lower
+ bound is assumed to be as low as zero. */
+ res.range.min = 0;
+ }
}
else
{
@@ -1652,10 +1720,10 @@ format_string (const conversion_spec &spec, tree arg)
{
if (slen.range.min >= target_int_max ())
slen.range.min = 0;
- else if ((unsigned)prec < slen.range.min)
+ else if ((unsigned HOST_WIDE_INT)prec < slen.range.min)
slen.range.min = prec;
- if ((unsigned)prec < slen.range.max
+ if ((unsigned HOST_WIDE_INT)prec < slen.range.max
|| slen.range.max >= target_int_max ())
slen.range.max = prec;
}
@@ -1678,20 +1746,23 @@ format_string (const conversion_spec &spec, tree arg)
}
/* Adjust the lengths for field width. */
- if (res.range.min < width)
- res.range.min = width;
+ if (0 < width)
+ {
+ if (res.range.min < (unsigned HOST_WIDE_INT)width)
+ res.range.min = width;
- if (res.range.max < width)
- res.range.max = width;
+ if (res.range.max < (unsigned HOST_WIDE_INT)width)
+ res.range.max = width;
- /* Adjust BOUNDED if width happens to make them equal. */
- if (res.range.min == res.range.max && res.range.min < target_int_max ()
- && bounded)
- res.bounded = true;
+ /* Adjust BOUNDED if width happens to make them equal. */
+ if (res.range.min == res.range.max && res.range.min < target_int_max ()
+ && bounded)
+ res.bounded = true;
+ }
/* When precision is specified the range of characters on output
is known to be bounded by it. */
- if (-1 < prec)
+ if (-1 < width && -1 < prec)
res.knownrange = true;
return res;
@@ -1807,7 +1878,7 @@ format_directive (const pass_sprintf_length::call_info &info,
(int)cvtlen, cvtbeg, fmtres.range.min,
navail);
}
- else
+ else if (fmtres.range.max < HOST_WIDE_INT_MAX)
{
const char* fmtstr
= (info.bounded
@@ -1821,6 +1892,19 @@ format_directive (const pass_sprintf_length::call_info &info,
(int)cvtlen, cvtbeg,
fmtres.range.min, fmtres.range.max, navail);
}
+ else
+ {
+ const char* fmtstr
+ = (info.bounded
+ ? G_("%<%.*s%> directive output truncated writing "
+ "%wu or more bytes into a region of size %wu")
+ : G_("%<%.*s%> directive writing %wu or more bytes "
+ "into a region of size %wu"));
+ warned = fmtwarn (dirloc, pargrange, NULL,
+ OPT_Wformat_length_, fmtstr,
+ (int)cvtlen, cvtbeg,
+ fmtres.range.min, navail);
+ }
}
else if (navail < fmtres.range.max
&& (((spec.specifier == 's'
@@ -2277,13 +2361,22 @@ pass_sprintf_length::compute_format_length (const call_info &info,
if (dollar || !spec.star_width)
{
- if (spec.have_width && spec.width == 0)
+ if (spec.have_width)
{
- /* The '0' that has been interpreted as a width above is
- actually a flag. Reset HAVE_WIDTH, set the '0' flag,
- and continue processing other flags. */
- spec.have_width = false;
- spec.set_flag ('0');
+ if (spec.width == 0)
+ {
+ /* The '0' that has been interpreted as a width above is
+ actually a flag. Reset HAVE_WIDTH, set the '0' flag,
+ and continue processing other flags. */
+ spec.have_width = false;
+ spec.set_flag ('0');
+ }
+ else if (!dollar)
+ {
+ /* (Non-zero) width has been seen. The next character
+ is either a period or a digit. */
+ goto start_precision;
+ }
}
/* When either '$' has been seen, or width has not been seen,
the next field is the optional flags followed by an optional
@@ -2328,6 +2421,7 @@ pass_sprintf_length::compute_format_length (const call_info &info,
}
}
+ start_precision:
if ('.' == *pf)
{
++pf;
@@ -2345,7 +2439,12 @@ pass_sprintf_length::compute_format_length (const call_info &info,
++pf;
}
else
- return;
+ {
+ /* The decimal precision or the asterisk are optional.
+ When neither is specified it's taken to be zero. */
+ spec.precision = 0;
+ spec.have_precision = true;
+ }
}
switch (*pf)
@@ -2705,9 +2804,9 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
if (idx_dstsize == HOST_WIDE_INT_M1U)
{
- // For non-bounded functions like sprintf, to determine
- // the size of the destination from the object or pointer
- // passed to it as the first argument.
+ /* For non-bounded functions like sprintf, determine the size
+ of the destination from the object or pointer passed to it
+ as the first argument. */
dstsize = get_destination_size (gimple_call_arg (info.callstmt, 0));
}
else if (tree size = gimple_call_arg (info.callstmt, idx_dstsize))
@@ -2719,10 +2818,18 @@ 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. */
+ less than that.
+ 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 too large",
+ "specified destination size %wu is too large",
+ dstsize);
+ else if (dstsize > target_int_max ())
+ warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
+ "specified destination size %wu exceeds %<INT_MAX %>",
dstsize);
}
else if (TREE_CODE (size) == SSA_NAME)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-5.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-5.c
index d568f9c..cdaeeac 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-5.c
@@ -44,6 +44,26 @@ void test_arg_int (int i, int n)
for (i = -n; i != n; ++i)
T (8, "%08x", i);
+
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (0, "%.0d", ival (0));
+ T (0, "%.0i", ival (0));
+ T (0, "%.0o", ival (0));
+ T (0, "%.0u", ival (0));
+ T (0, "%.0x", ival (0));
+
+ T (0, "%.*d", 0, ival (0));
+ T (0, "%.*i", 0, ival (0));
+ T (0, "%.*o", 0, ival (0));
+ T (0, "%.*u", 0, ival (0));
+ T (0, "%.*x", 0, ival (0));
+
+ T (1, "%1.0d", ival (0));
+ T (1, "%1.0i", ival (0));
+ T (1, "%1.0o", ival (0));
+ T (1, "%1.0u", ival (0));
+ T (1, "%1.0x", ival (0));
}
void test_arg_string (const char *s)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-6.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-6.c
new file mode 100644
index 0000000..375fc09
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-6.c
@@ -0,0 +1,73 @@
+/* PR middle-end/78476 - snprintf(0, 0, ...) with known arguments not
+ optimized away
+ A negative test complementing builtin-sprintf-5.c to verify that calls
+ to the function that do not return a constant are not optimized away.
+ { dg-compile }
+ { dg-options "-O2 -fdump-tree-optimized" }
+ { dg-require-effective-target int32plus } */
+
+#define CONCAT(a, b) a ## b
+#define CAT(a, b) CONCAT (a, b)
+
+#define T(...) \
+ do { \
+ int CAT (n, __LINE__) = __builtin_snprintf (0, 0, __VA_ARGS__); \
+ sink (CAT (n, __LINE__)); \
+ } while (0)
+
+void sink (int);
+
+static int
+int_range (int min, int max)
+{
+ extern int int_value (void);
+ int val = int_value ();
+ if (val < min || max < val)
+ val = min;
+ return val;
+}
+
+#define R(min, max) int_range (min, max)
+
+void test_arg_int (int width, int prec, int i, int n)
+{
+ T ("%i", i);
+ T ("%1i", i);
+ T ("%2i", i);
+ T ("%3i", i);
+ T ("%4i", i);
+
+ T ("%*i", width, 0);
+ T ("%*i", width, 1);
+ T ("%*i", width, i);
+
+ T ("%.*i", prec, 0);
+ T ("%.*i", prec, 1);
+ T ("%.*i", prec, i);
+ T ("%.*i", 0, i);
+
+ T ("%i", R (1, 10));
+
+ for (i = -n; i != n; ++i)
+ T ("%*x", n, i);
+}
+
+void test_arg_string (int width, int prec, const char *s)
+{
+ T ("%-s", s);
+ T ("%1s", s);
+ T ("%.1s", s);
+ T ("%*s", width, s);
+ T ("%.*s", prec, s);
+ T ("%1.*s", prec, s);
+ T ("%*.1s", width, s);
+ T ("%*.*s", width, prec, s);
+ T ("%*s", width, "123");
+ T ("%.*s", prec, "123");
+ T ("%1.*s", prec, "123");
+ T ("%*.1s", width, "123");
+ T ("%*.*s", width, prec, "123");
+}
+
+
+/* { dg-final { scan-tree-dump-times "snprintf" 27 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
index a24889b..4aafc9f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
@@ -233,6 +233,8 @@ void test_sprintf_chk_s_const (void)
T ( 1, "%*s", 1, s0); /* { dg-warning "nul past the end" } */
T (-1, "%*s", 1, s0); /* No warning for unknown destination size. */
+ T (1, "%.s", "");
+ T (1, "%.s", "123");
T (1, "%.0s", "123");
T (1, "%.0s", s3);
T (1, "%.*s", 0, "123");
@@ -450,6 +452,24 @@ void test_sprintf_chk_hh_const (void)
T (4, "%hhi %hhi", 10, 1); /* { dg-warning "nul past the end" } */
T (4, "%hhi %hhi", 11, 12); /* { dg-warning "into a region" } */
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (1, "%.0hhd", 0);
+ T (1, "%+.0hhd", 0);
+ T (1, "%-.0hhd", 0);
+ T (1, "% .0hhd", 0);
+ T (1, "%0.0hhd", 0); /* { dg-warning ".0. flag ignored with precision" } */
+ T (1, "%00.0hhd", 0); /* { dg-warning "repeated .0. flag in format" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%-0.0hhd", 0); /* { dg-warning ".0. flag ignored with .-. flag" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%.0hhi", 0);
+ T (1, "%.0hho", 0);
+ T (1, "%#.0hho", 0);
+ T (1, "%.0hhx", 0);
+ T (1, "%.0hhX", 0);
+ T (1, "%#.0hhX", 0);
+
T (5, "%0*hhd %0*hhi", 0, 7, 0, 9);
T (5, "%0*hhd %0*hhi", 1, 7, 1, 9);
T (5, "%0*hhd %0*hhi", 1, 7, 2, 9);
@@ -546,14 +566,32 @@ void test_sprintf_chk_h_const (void)
T (4, "%#hx", 0x100); /* { dg-warning "into a region" } */
T (4, "%#hx", -1); /* { dg-warning "into a region" } */
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (1, "%.0hd", 0);
+ T (1, "%+.0hd", 0);
+ T (1, "%-.0hd", 0);
+ T (1, "% .0hd", 0);
+ T (1, "%0.0hd", 0); /* { dg-warning ".0. flag ignored with precision" } */
+ T (1, "%00.0hd", 0); /* { dg-warning "repeated .0. flag in format" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%-0.0hd", 0); /* { dg-warning ".0. flag ignored with .-. flag" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%.0hi", 0);
+ T (1, "%.0ho", 0);
+ T (1, "%#.0ho", 0);
+ T (1, "%.0hx", 0);
+ T (1, "%.0hX", 0);
+ T (1, "%#.0hX", 0);
+
#undef MAX
#define MAX 65535
- T (1, "%hhu", 0); /* { dg-warning "nul past the end" } */
- T (1, "%hhu", 1); /* { dg-warning "nul past the end" } */
- T (1, "%hhu", -1); /* { dg-warning "into a region" } */
- T (1, "%hhu", MAX); /* { dg-warning "into a region" } */
- T (1, "%hhu", MAX + 1); /* { dg-warning "nul past the end" } */
+ T (1, "%hu", 0); /* { dg-warning "nul past the end" } */
+ T (1, "%hu", 1); /* { dg-warning "nul past the end" } */
+ T (1, "%hu", -1); /* { dg-warning "into a region" } */
+ T (1, "%hu", MAX); /* { dg-warning "into a region" } */
+ T (1, "%hu", MAX + 1); /* { dg-warning "nul past the end" } */
}
/* Exercise the "%d", "%i", "%o", "%u", and "%x" directives with
@@ -611,6 +649,24 @@ void test_sprintf_chk_integer_const (void)
T ( 8, "%8u", 1); /* { dg-warning "nul past the end" } */
T ( 9, "%8u", 1);
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (1, "%.0d", 0);
+ T (1, "%+.0d", 0);
+ T (1, "%-.0d", 0);
+ T (1, "% .0d", 0);
+ T (1, "%0.0d", 0); /* { dg-warning ".0. flag ignored with precision" } */
+ T (1, "%00.0d", 0); /* { dg-warning "repeated .0. flag in format" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%-0.0d", 0); /* { dg-warning ".0. flag ignored with .-. flag" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%.0i", 0);
+ T (1, "%.0o", 0);
+ T (1, "%#.0o", 0);
+ T (1, "%.0x", 0);
+ T (1, "%.0X", 0);
+ T (1, "%#.0X", 0);
+
T ( 7, "%1$i%2$i%3$i", 1, 23, 456);
T ( 8, "%1$i%2$i%3$i%1$i", 1, 23, 456);
T ( 8, "%1$i%2$i%3$i%2$i", 1, 23, 456); /* { dg-warning "nul past the end" } */
@@ -691,6 +747,24 @@ void test_sprintf_chk_j_const (void)
T ( 8, "%8ju", I (1)); /* { dg-warning "nul past the end" } */
T ( 9, "%8ju", I (1));
+
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (1, "%.0jd", I (0));
+ T (1, "%+.0jd", I (0));
+ T (1, "%-.0jd", I (0));
+ T (1, "% .0jd", I (0));
+ T (1, "%0.0jd", I (0)); /* { dg-warning ".0. flag ignored with precision" } */
+ T (1, "%00.0jd", I (0)); /* { dg-warning "repeated .0. flag in format" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%-0.0jd", I (0)); /* { dg-warning ".0. flag ignored with .-. flag" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%.0ji", I (0));
+ T (1, "%.0jo", I (0));
+ T (1, "%#.0jo", I (0));
+ T (1, "%.0jx", I (0));
+ T (1, "%.0jX", I (0));
+ T (1, "%#.0jX", I (0));
}
/* Exercise the "%ld", "%li", "%lo", "%lu", and "%lx" directives
@@ -747,6 +821,24 @@ void test_sprintf_chk_l_const (void)
T ( 8, "%8lu", 1L); /* { dg-warning "nul past the end" } */
T ( 9, "%8lu", 1L);
+
+ /* As a special case, a precision of zero with an argument of zero
+ results in zero bytes (unless modified by width). */
+ T (1, "%.0ld", 0L);
+ T (1, "%+.0ld", 0L);
+ T (1, "%-.0ld", 0L);
+ T (1, "% .0ld", 0L);
+ T (1, "%0.0ld", 0L); /* { dg-warning ".0. flag ignored with precision" } */
+ T (1, "%00.0ld", 0L); /* { dg-warning "repeated .0. flag in format" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%-0.0ld", 0L); /* { dg-warning ".0. flag ignored with .-. flag" } */
+ /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
+ T (1, "%.0li", 0L);
+ T (1, "%.0lo", 0L);
+ T (1, "%#.0lo", 0L);
+ T (1, "%.0lx", 0L);
+ T (1, "%.0lX", 0L);
+ T (1, "%#.0lX", 0L);
}
/* Exercise the "%lld", "%lli", "%llo", "%llu", and "%llx" directives
@@ -858,37 +950,56 @@ void test_sprintf_chk_z_const (void)
void test_sprintf_chk_a_const (void)
{
- T (-1, "%a", 0.0);
- T (-1, "%la", 0.0);
+ T (-1, "%a", 0.0);
+ T (-1, "%la", 0.0);
+ T (-1, "%.a", 0.0);
+ T (-1, "%.la", 0.0);
+ T (-1, "%123.a", 0.0);
+ T (-1, "%234.la", 0.0);
+ T (-1, "%.345a", 0.0);
+ T (-1, "%456.567la", 0.0);
/* The least number of bytes on output is 6 for "0x0p+0". When precision
is missing the number of digits after the decimal point isn't fully
specified by C (it seems like a defect). */
- T (0, "%a", 0.0); /* { dg-warning "into a region" } */
- T (0, "%la", 0.0); /* { dg-warning "into a region" } */
- T (1, "%a", 0.0); /* { dg-warning "into a region" } */
- T (2, "%a", 0.0); /* { dg-warning "into a region" } */
- T (3, "%a", 0.0); /* { dg-warning "into a region" } */
- T (4, "%a", 0.0); /* { dg-warning "into a region" } */
- T (5, "%a", 0.0); /* { dg-warning "into a region" } */
- T (6, "%a", 0.0); /* { dg-warning "writing a terminating nul" } */
+ T (0, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (0, "%la", 0.0); /* { dg-warning "into a region" } */
+ T (1, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (2, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (3, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (4, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (5, "%a", 0.0); /* { dg-warning "into a region" } */
+ T (6, "%a", 0.0); /* { dg-warning "writing a terminating nul" } */
T (7, "%a", 0.0);
- T (0, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (0, "%.0la", 0.0); /* { dg-warning "into a region" } */
- T (1, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (2, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (3, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (4, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (5, "%.0a", 0.0); /* { dg-warning "into a region" } */
- T (6, "%.0a", 0.0); /* { dg-warning "writing a terminating nul" } */
+ T (0, "%.a", 0.0); /* { dg-warning "into a region" } */
+ T (0, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (0, "%.0la", 0.0); /* { dg-warning "into a region" } */
+ T (1, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (2, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (3, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (4, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (5, "%.0a", 0.0); /* { dg-warning "into a region" } */
+ T (6, "%.0a", 0.0); /* { dg-warning "writing a terminating nul" } */
+
+ T (7, "%6.a", 0.0);
+ T (7, "%7.a", 0.0); /* { dg-warning "writing a terminating nul" } */
+ T (7, "%7.1a", 0.0); /* { dg-warning "writing 8 bytes into a region of size 7" } */
+
+ T (7, "%.a", 0.0);
T (7, "%.0a", 0.0);
}
void test_sprintf_chk_e_const (void)
{
- T (-1, "%E", 0.0);
- T (-1, "%lE", 0.0);
+ T (-1, "%E", 0.0);
+ T (-1, "%lE", 0.0);
+ T (-1, "%.E", 0.0);
+ T (-1, "%.lE", 0.0);
+ T (-1, "%123.E", 0.0);
+ T (-1, "%234.lE", 0.0);
+ T (-1, "%.345E", 0.0);
+ T (-1, "%.456lE", 0.0);
T ( 0, "%E", 0.0); /* { dg-warning "into a region" } */
T ( 0, "%e", 0.0); /* { dg-warning "into a region" } */
@@ -910,8 +1021,10 @@ void test_sprintf_chk_e_const (void)
T (16, "%.8e", -1.9e+104); /* { dg-warning "nul past the end" } */
T (17, "%.8e", -2.0e+105); /* -2.00000000e+105 */
+ T ( 5, "%.e", 0.0); /* { dg-warning "nul past the end" } */
T ( 5, "%.0e", 0.0); /* { dg-warning "nul past the end" } */
T ( 5, "%.0e", 1.0); /* { dg-warning "nul past the end" } */
+ T ( 6, "%.e", 1.0);
T ( 6, "%.0e", 1.0);
/* The actual output of the following directives depends on the rounding
@@ -938,7 +1051,7 @@ void test_sprintf_chk_e_const (void)
the value one, and unknown strings are assumed to have a zero
length. */
-void test_sprintf_chk_s_nonconst (int i, const char *s)
+void test_sprintf_chk_s_nonconst (int w, int p, const char *s)
{
T (-1, "%s", s);
T ( 0, "%s", s); /* { dg-warning "nul past the end" } */
@@ -946,6 +1059,19 @@ void test_sprintf_chk_s_nonconst (int i, const char *s)
T ( 1, "%.0s", s);
T ( 1, "%.1s", s); /* { dg-warning "nul past the end" } */
+ /* The string argument is constant but the width and/or precision
+ is not. */
+ T ( 1, "%*s", w, "");
+ T ( 1, "%*s", w, "1"); /* { dg-warning "nul past the end" } */
+ T ( 1, "%.*s", w, "");
+ T ( 1, "%.*s", w, "1"); /* { dg-warning "may write a terminating nul" } */
+ T ( 1, "%.*s", w, "123"); /* { dg-warning "writing between 0 and 3 bytes into a region of size 1" } */
+
+ T ( 1, "%*s", w, "123"); /* { dg-warning "writing 3 or more bytes into a region of size 1" } */
+ T ( 2, "%*s", w, "123"); /* { dg-warning "writing 3 or more bytes into a region of size 2" } */
+ T ( 3, "%*s", w, "123"); /* { dg-warning "writing a terminating nul past the end" } */
+ T ( 4, "%*s", w, "123");
+
/* The following will definitely write past the end of the buffer,
but since at level 1 the length of an unknown string argument
is assumed to be zero, it will write the terminating nul past
@@ -957,7 +1083,7 @@ void test_sprintf_chk_s_nonconst (int i, const char *s)
/* Exercise the hh length modifier with all integer specifiers and
a non-constant argument. */
-void test_sprintf_chk_hh_nonconst (int a)
+void test_sprintf_chk_hh_nonconst (int w, int p, int a)
{
T (-1, "%hhd", a);
@@ -999,11 +1125,48 @@ void test_sprintf_chk_hh_nonconst (int a)
T (2, "%#hho", a); /* { dg-warning "nul past the end" } */
T (2, "%#hhx", a); /* { dg-warning ".%#hhx. directive writing between 3 and . bytes into a region of size 2" } */
+ T (3, "%0hhd", a);
+ T (3, "%1hhd", a);
T (3, "%2hhd", a);
T (3, "%2hhi", a);
T (3, "%2hho", a);
T (3, "%2hhu", a);
T (3, "%2hhx", a);
+ T (3, "%2.hhx", a);
+
+ T (3, "%3hhd", a); /* { dg-warning "nul past the end" } */
+ T (3, "%3hhi", a); /* { dg-warning "nul past the end" } */
+ T (3, "%3hho", a); /* { dg-warning "nul past the end" } */
+ T (3, "%3hhu", a); /* { dg-warning "nul past the end" } */
+ T (3, "%3hhx", a); /* { dg-warning "nul past the end" } */
+ T (3, "%3.hhx", a); /* { dg-warning "nul past the end" } */
+
+ T (4, "%5hhd", a); /* { dg-warning "into a region" } */
+ T (4, "%6hhi", a); /* { dg-warning "into a region" } */
+ T (4, "%7hho", a); /* { dg-warning "into a region" } */
+ T (4, "%8hhu", a); /* { dg-warning "into a region" } */
+ T (4, "%9hhx", a); /* { dg-warning "into a region" } */
+
+ T (3, "%.hhd", a);
+ T (3, "%.0hhd", a);
+ T (3, "%.1hhd", a);
+ T (3, "%.2hhd", a);
+ T (3, "%.2hhi", a);
+ T (3, "%.2hho", a);
+ T (3, "%.2hhu", a);
+ T (3, "%.2hhx", a);
+
+ T (3, "%.3hhd", a); /* { dg-warning "nul past the end" } */
+ T (3, "%.3hhi", a); /* { dg-warning "nul past the end" } */
+ T (3, "%.3hho", a); /* { dg-warning "nul past the end" } */
+ T (3, "%.3hhu", a); /* { dg-warning "nul past the end" } */
+ T (3, "%.3hhx", a); /* { dg-warning "nul past the end" } */
+
+ T (4, "%.5hhd", a); /* { dg-warning "into a region" } */
+ T (4, "%.6hhi", a); /* { dg-warning "into a region" } */
+ T (4, "%.7hho", a); /* { dg-warning "into a region" } */
+ T (4, "%.8hhu", a); /* { dg-warning "into a region" } */
+ T (4, "%.9hhx", a); /* { dg-warning "into a region" } */
/* Exercise cases where the type of the actual argument (whose value
and range are unknown) constrain the size of the output and so
@@ -1012,6 +1175,55 @@ void test_sprintf_chk_hh_nonconst (int a)
T (2, "%hhd", (UChar)a);
T (2, "%hhi", (UChar)a);
T (2, "%-hhi", (UChar)a);
+
+ /* Exercise cases where the argument is known but width isn't. */
+ T (0, "%*hhi", w, 0); /* { dg-warning "into a region" } */
+ T (1, "%*hhi", w, 0); /* { dg-warning "nul past the end" } */
+ T (2, "%*hhi", w, 0);
+ T (2, "%*hhi", w, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%*hhi", w, 123); /* { dg-warning "into a region" } */
+
+ /* The argument is known but precision isn't. When the argument
+ is zero only the first call can be diagnosed since a zero
+ precision would result in no bytes on output. */
+ T (0, "%.*hhi", p, 0); /* { dg-warning "nul past the end" } */
+ T (1, "%.*hhi", p, 0);
+ T (2, "%.*hhi", p, 0);
+ T (2, "%.*hhi", p, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%.*hhi", p, 123); /* { dg-warning "into a region" } */
+
+ /* The argument is known but neither width nor precision is. */
+ T (0, "%*.*hhi", w, p, 0); /* { dg-warning "nul past the end" } */
+ T (1, "%*.*hhi", w, p, 0);
+ T (2, "%*.*hhi", w, p, 0);
+ T (2, "%*.*hhi", w, p, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%*.*hhi", w, p, 123); /* { dg-warning "into a region" } */
+
+ /* The argument and width are known but precision isn't. */
+ T (0, "%1.*hhi", p, 0); /* { dg-warning "into a region" } */
+ T (0, "%-1.*hhi", p, 0); /* { dg-warning "into a region" } */
+ T (1, "%1.*hhi", p, 0); /* { dg-warning "nul past the end" } */
+ T (2, "%1.*hhi", p, 0);
+ T (2, "%2.*hhi", p, 0); /* { dg-warning "nul past the end" } */
+ T (2, "%1.*hhi", p, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%2.*hhi", p, 12); /* { dg-warning "nul past the end" } */
+
+ T (2, "%1.*hhi", p, 123); /* { dg-warning "into a region" } */
+ T (2, "%2.*hhi", p, 123); /* { dg-warning "into a region" } */
+ T (2, "%3.*hhi", p, 123); /* { dg-warning "into a region" } */
+
+ /* The argument and precision are known but width isn't. */
+ T (0, "%*.1hhi", w, 0); /* { dg-warning "into a region" } */
+ T (1, "%*.1hhi", w, 0); /* { dg-warning "nul past the end" } */
+ T (2, "%*.1hhi", w, 0);
+ T (2, "%*.2hhi", w, 0); /* { dg-warning "nul past the end" } */
+ T (2, "%*.1hhi", w, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%*.2hhi", w, 12); /* { dg-warning "nul past the end" } */
+ T (2, "%*.3hhi", w, 12); /* { dg-warning "into a region" } */
+
+ T (2, "%*.1hhi", w, 123); /* { dg-warning "into a region" } */
+ T (2, "%*.2hhi", w, 123); /* { dg-warning "into a region" } */
+ T (2, "%*.3hhi", w, 123); /* { dg-warning "into a region" } */
}
/* Exercise the h length modifier with all integer specifiers and
@@ -1063,7 +1275,7 @@ void test_sprintf_chk_h_nonconst (int a)
/* Exercise all integer specifiers with no modifier and a non-constant
argument. */
-void test_sprintf_chk_int_nonconst (int a)
+void test_sprintf_chk_int_nonconst (int w, int p, int a)
{
T (-1, "%d", a);
@@ -1104,12 +1316,22 @@ void test_sprintf_chk_int_nonconst (int a)
T (3, "%2o", a);
T (3, "%2u", a);
T (3, "%2x", a);
+
+ T (1, "%.*d", p, a);
}
-void test_sprintf_chk_e_nonconst (double d)
+void test_sprintf_chk_e_nonconst (int w, int p, double d)
{
- T (-1, "%E", d);
- T (-1, "%lE", d);
+ T (-1, "%E", d);
+ T (-1, "%lE", d);
+ T (-1, "%.E", d);
+ T (-1, "%.lE", d);
+ T (-1, "%*E", w, d);
+ T (-1, "%*lE", w, d);
+ T (-1, "%.*E", p, d);
+ T (-1, "%.*lE", p, d);
+ T (-1, "%*.*E", w, p, d);
+ T (-1, "%*.*lE", w, p, d);
T ( 0, "%E", d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
T ( 0, "%e", d); /* { dg-warning "into a region" } */
@@ -1123,9 +1345,9 @@ void test_sprintf_chk_e_nonconst (double d)
T (14, "%E", d);
T (14, "%e", d);
- T (0, "%+E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
- T (0, "%-e", d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
- T (0, "% E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
+ T ( 0, "%+E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
+ T ( 0, "%-e", d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
+ T ( 0, "% E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
/* The range of output of "%.0e" is between 5 and 7 bytes (not counting
the terminating NUL. */
@@ -1136,6 +1358,9 @@ void test_sprintf_chk_e_nonconst (double d)
the terminating NUL. */
T ( 7, "%.1e", d); /* { dg-warning "writing a terminating nul past the end" } */
T ( 8, "%.1e", d);
+
+ T ( 0, "%*e", 0, d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
+ T ( 0, "%*e", w, d); /* { dg-warning "writing 12 or more bytes into a region of size 0" } */
}
void test_sprintf_chk_f_nonconst (double d)
@@ -1204,7 +1429,6 @@ void test_vsprintf_chk_c (__builtin_va_list va)
/* Here in the best case each argument will format as single character,
causing the terminating NUL to be written past the end. */
T (3, "%lc%c%c");
-
}
void test_vsprintf_chk_int (__builtin_va_list va)
@@ -1254,9 +1478,11 @@ void test_vsprintf_chk_int (__builtin_va_list va)
#define T(size, fmt, ...) \
__builtin_snprintf (buffer (size), objsize (size), fmt, __VA_ARGS__)
-void test_snprintf_c_const (void)
+void test_snprintf_c_const (char *d)
{
- T (-1, "%c", 0); /* { dg-warning "specified destination size \[0-9\]+ too large" } */
+ T (-1, "%c", 0); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
+
+ __builtin_snprintf (d, INT_MAX, "%c", 0);
/* Verify the full text of the diagnostic for just the distinct messages
and use abbreviations in subsequent test cases. */
@@ -1306,7 +1532,7 @@ void test_snprintf_chk_c_const (void)
the function by __builtin_object_size) is diagnosed. */
__builtin___snprintf_chk (buffer, 3, 0, 2, " "); /* { dg-warning "always overflow|specified size 3 exceeds the size 2 of the destination" } */
- T (-1, "%c", 0); /* { dg-warning "specified destination size \[^ \]* too large" } */
+ T (-1, "%c", 0); /* { dg-warning "specified destination size \[^ \]* is too large" } */
T (0, "%c", 0);
T (0, "%c%c", 0, 0);
@@ -1417,7 +1643,7 @@ void test_vsprintf_int (__builtin_va_list va)
void test_vsnprintf_s (__builtin_va_list va)
{
- T (-1, "%s"); /* { dg-warning "specified destination size \[^ \]* too large" } */
+ T (-1, "%s"); /* { dg-warning "specified destination size \[^ \]* is too large" } */
T (0, "%s");
T (1, "%s");
@@ -1442,7 +1668,7 @@ void test_vsnprintf_chk_s (__builtin_va_list va)
the function by __builtin_object_size) is diagnosed. */
__builtin___vsnprintf_chk (buffer, 123, 0, 122, "%-s", va); /* { dg-warning "always overflow|specified size 123 exceeds the size 122 of the destination object" } */
- __builtin___vsnprintf_chk (buffer, __SIZE_MAX__, 0, 2, "%-s", va); /* { dg-warning "always overflow|destination size .\[0-9\]+. too large" } */
+ __builtin___vsnprintf_chk (buffer, __SIZE_MAX__, 0, 2, "%-s", va); /* { dg-warning "always overflow|destination size .\[0-9\]+. is too large" } */
T (0, "%s");
T (1, "%s");
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
index 8d97fa8..f4550ba 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
@@ -1,6 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-std=c99 -O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
+typedef __SIZE_TYPE__ size_t;
+
#ifndef LINE
# define LINE 0
#endif
@@ -232,3 +234,48 @@ void test_sprintf_chk_range_sshort (signed short *a, signed short *b)
T ( 4, "%i", Ra (998, 999));
T ( 4, "%i", Ra (999, 1000)); /* { dg-warning "may write a terminating nul past the end of the destination" } */
}
+
+/* Verify that destination size in excess of INT_MAX (and, separately,
+ in excess of the largest object) is diagnosed. The former because
+ the functions are defined only for output of at most INT_MAX and
+ specifying a large upper bound defeats the bounds checking (and,
+ on some implementations such as Solaris, causes the function to
+ fail. The latter because due to the limit of ptrdiff_t no object
+ can be larger than PTRDIFF_MAX bytes. */
+
+void test_too_large (char *d, int x, __builtin_va_list va)
+{
+ const size_t imax = __INT_MAX__;
+ const size_t imax_p1 = imax + 1;
+
+ __builtin_snprintf (d, imax, "%c", x);
+ __builtin_snprintf (d, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
+ /* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
+
+ __builtin_vsnprintf (d, imax, "%c", va);
+ __builtin_vsnprintf (d, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
+ /* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
+
+ __builtin___snprintf_chk (d, imax, 0, imax, "%c", x);
+ __builtin___snprintf_chk (d, imax_p1, 0, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
+ /* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
+
+ __builtin___vsnprintf_chk (d, imax, 0, imax, "%c", va);
+ __builtin___vsnprintf_chk (d, imax_p1, 0, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
+ /* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
+
+ const size_t ptrmax = __PTRDIFF_MAX__;
+ const size_t ptrmax_m1 = ptrmax - 1;
+
+ __builtin_snprintf (d, ptrmax_m1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
+ __builtin_snprintf (d, ptrmax, " %c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
+
+ __builtin_vsnprintf (d, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
+ __builtin_vsnprintf (d, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
+
+ __builtin___snprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
+ __builtin___snprintf_chk (d, ptrmax, 0, ptrmax, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
+
+ __builtin___vsnprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
+ __builtin___vsnprintf_chk (d, ptrmax, 0, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
+}
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-28 3:34 [PATCH] correct handling of non-constant width and precision (pr 78521) Martin Sebor
@ 2016-11-28 20:26 ` Jeff Law
2016-11-29 0:42 ` Joseph Myers
2016-12-02 8:31 ` Rainer Orth
2 siblings, 0 replies; 20+ messages in thread
From: Jeff Law @ 2016-11-28 20:26 UTC (permalink / raw)
To: Martin Sebor, Gcc Patch List
On 11/27/2016 08:34 PM, Martin Sebor wrote:
> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
> thing (i.e., the -Wformat-length and -fprintf-return-value options
> behave incorrectly) when a conversion specification includes a width
> or precision with a non-constant value. The code treats such cases
> as if they were not provided which is incorrect and results in
> the wrong bytes counts in warning messages and in the wrong ranges
> being generated for such calls (or in the case sprintf(0, 0, ...)
> for some such calls being eliminated).
>
> The attached patch corrects the handling of these cases, plus a couple
> of other edge cases in the same area: it adjusts the parser to accept
> precision in the form of just a period with no asterisk or decimal
> digits after it (this sets the precision to zero), and corrects the
> handling of zero precision and zero argument in integer directives
> to produce no bytes on output.
>
> Finally, the patch also tightens up the constraint on the upper bound
> of bounded functions like snprintf to be INT_MAX. The functions cannot
> produce output in excess of INT_MAX + 1 bytes and some implementations
> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
> This is the subject of PR 78520.
>
> Thanks
> Martin
>
> gcc-78521.diff
>
>
> PR middle-end/78521 - [7 Regression] incorrect byte count in -Wformat-length warning with non-constant width or precision
> PR middle-end/78520 - missing warning for snprintf with size greater than INT_MAX
> gcc/ChangeLog:
>
> PR middle-end/78521
> PR middle-end/78520
> * gimple-ssa-sprintf.c (target_max_value): Remove.
> (target_int_max, target_size_max): Use TYPE_MAX_VALUE.
> (get_width_and_precision): New function.
> (format_integer, format_floating, get_string_length, format_string):
> Correct handling of width and precision with unknown value.
> (format_directive): Add warning.
> (pass_sprintf_length::compute_format_length): Allow for precision
> to consist of a sole period with no asterisk or digits after it.
>
> gcc/testsuite/ChangeLog:
>
> PR middle-end/78521
> PR middle-end/78520
> * gcc.dg/tree-ssa/builtin-sprintf-5.c: Add test cases.
> * gcc.dg/tree-ssa/builtin-sprintf-6.c: New test.
> * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Add test cases.
> * gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Add test cases.
Fairly dense reading. Probably inherent due to the problem space.
OK for the trunk.
Thanks,
jeff
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-28 3:34 [PATCH] correct handling of non-constant width and precision (pr 78521) Martin Sebor
2016-11-28 20:26 ` Jeff Law
@ 2016-11-29 0:42 ` Joseph Myers
2016-11-29 16:57 ` Martin Sebor
2016-12-02 8:31 ` Rainer Orth
2 siblings, 1 reply; 20+ messages in thread
From: Joseph Myers @ 2016-11-29 0:42 UTC (permalink / raw)
To: Martin Sebor; +Cc: Gcc Patch List
On Sun, 27 Nov 2016, Martin Sebor wrote:
> Finally, the patch also tightens up the constraint on the upper bound
> of bounded functions like snprintf to be INT_MAX. The functions cannot
> produce output in excess of INT_MAX + 1 bytes and some implementations
> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
> This is the subject of PR 78520.
Note that failing with large bounds is questionable (there is an apparent
conflict between ISO C, where passing a large bound seems valid, and
POSIX, where large bounds require errors; see
<http://austingroupbugs.net/view.php?id=761>; I'm not sure if any liaison
issue for this ever got passed to WG14).
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-29 0:42 ` Joseph Myers
@ 2016-11-29 16:57 ` Martin Sebor
2016-11-29 20:14 ` Martin Sebor
0 siblings, 1 reply; 20+ messages in thread
From: Martin Sebor @ 2016-11-29 16:57 UTC (permalink / raw)
To: Joseph Myers; +Cc: Gcc Patch List
On 11/28/2016 05:42 PM, Joseph Myers wrote:
> On Sun, 27 Nov 2016, Martin Sebor wrote:
>
>> Finally, the patch also tightens up the constraint on the upper bound
>> of bounded functions like snprintf to be INT_MAX. The functions cannot
>> produce output in excess of INT_MAX + 1 bytes and some implementations
>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>> This is the subject of PR 78520.
>
> Note that failing with large bounds is questionable (there is an apparent
> conflict between ISO C, where passing a large bound seems valid, and
> POSIX, where large bounds require errors; see
> <http://austingroupbugs.net/view.php?id=761>; I'm not sure if any liaison
> issue for this ever got passed to WG14).
Thanks! That's useful background. Let me check with Nick to see
is he (as the POSIX/WG14 liaison) plans to submit it. I can also
write it up for the next WG14 meeting if we or the Austin Group
feel like WG14 should clarify or change things.
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-29 16:57 ` Martin Sebor
@ 2016-11-29 20:14 ` Martin Sebor
0 siblings, 0 replies; 20+ messages in thread
From: Martin Sebor @ 2016-11-29 20:14 UTC (permalink / raw)
To: Joseph Myers; +Cc: Gcc Patch List
On 11/29/2016 09:56 AM, Martin Sebor wrote:
> On 11/28/2016 05:42 PM, Joseph Myers wrote:
>> On Sun, 27 Nov 2016, Martin Sebor wrote:
>>
>>> Finally, the patch also tightens up the constraint on the upper bound
>>> of bounded functions like snprintf to be INT_MAX. The functions cannot
>>> produce output in excess of INT_MAX + 1 bytes and some implementations
>>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>>> This is the subject of PR 78520.
>>
>> Note that failing with large bounds is questionable (there is an apparent
>> conflict between ISO C, where passing a large bound seems valid, and
>> POSIX, where large bounds require errors; see
>> <http://austingroupbugs.net/view.php?id=761>; I'm not sure if any liaison
>> issue for this ever got passed to WG14).
>
> Thanks! That's useful background. Let me check with Nick to see
> is he (as the POSIX/WG14 liaison) plans to submit it. I can also
> write it up for the next WG14 meeting if we or the Austin Group
> feel like WG14 should clarify or change things.
I've been looking at the original BSD sources where snprintf came
from (AFAICT). The first implementation I could find is in Net/2
from 1988. It returns EOF when the size after conversion to int
is less than 1. The same code is still in 4.4BSD.
Early UNIX implementations also have the limitation that the buffer
size maintained by struct FILE is an int. Since snprintf on these
early implementations usually uses vfprintf to do the work (with
the count being set to the snprinf bound), it can't store more than
INT_MAX bytes without overflowing the counter.
http://minnie.tuhs.org/cgi-bin/utree.pl?file=Net2/usr/src/lib/libc/stdio/snprintf.c
It looks to me like the POSIX spec is faithful to the historical
implementations and C should consider either tightening up its
constraints or make the behavior implementation-defined to allow
for more modern implementations that don't have this restriction.
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-28 3:34 [PATCH] correct handling of non-constant width and precision (pr 78521) Martin Sebor
2016-11-28 20:26 ` Jeff Law
2016-11-29 0:42 ` Joseph Myers
@ 2016-12-02 8:31 ` Rainer Orth
2016-12-02 15:52 ` Martin Sebor
2 siblings, 1 reply; 20+ messages in thread
From: Rainer Orth @ 2016-12-02 8:31 UTC (permalink / raw)
To: Martin Sebor; +Cc: Gcc Patch List
[-- Attachment #1: Type: text/plain, Size: 2651 bytes --]
Hi Martin,
> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
> thing (i.e., the -Wformat-length and -fprintf-return-value options
> behave incorrectly) when a conversion specification includes a width
> or precision with a non-constant value. The code treats such cases
> as if they were not provided which is incorrect and results in
> the wrong bytes counts in warning messages and in the wrong ranges
> being generated for such calls (or in the case sprintf(0, 0, ...)
> for some such calls being eliminated).
>
> The attached patch corrects the handling of these cases, plus a couple
> of other edge cases in the same area: it adjusts the parser to accept
> precision in the form of just a period with no asterisk or decimal
> digits after it (this sets the precision to zero), and corrects the
> handling of zero precision and zero argument in integer directives
> to produce no bytes on output.
>
> Finally, the patch also tightens up the constraint on the upper bound
> of bounded functions like snprintf to be INT_MAX. The functions cannot
> produce output in excess of INT_MAX + 1 bytes and some implementations
> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
> This is the subject of PR 78520.
this patch broke Solaris bootstrap:
/vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c: In function 'void {anonymous}::get_width_and_precision(const {anonymous}::conversion_spec&, long long int*, long long int*)':
/vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: error: call of overloaded 'abs(long long int)' is ambiguous
width = abs (tree_to_shwi (spec.star_width));
^
/vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: note: candidates are:
In file included from /usr/include/stdlib.h:12:0,
from /vol/gcc/src/hg/trunk/local/gcc/system.h:258,
from /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:49:
/usr/include/iso/stdlib_iso.h:205:16: note: long int std::abs(long int)
inline long abs(long _l) { return labs(_l); }
^
/usr/include/iso/stdlib_iso.h:160:12: note: int std::abs(int)
extern int abs(int);
^
The following patch fixed this for me, but I've no idea if it's right.
It bootstrapped successfully on sparc-sun-solaris2.12,
i386-pc-solaris2.12, and x86_64-pc-linux-gnu.
Rainer
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
2016-12-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gimple-ssa-sprintf.c (get_width_and_precision): Use std::abs.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: abs.patch --]
[-- Type: text/x-patch, Size: 423 bytes --]
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -774,7 +774,7 @@ get_width_and_precision (const conversio
if (spec.star_width)
{
if (TREE_CODE (spec.star_width) == INTEGER_CST)
- width = abs (tree_to_shwi (spec.star_width));
+ width = std::abs (tree_to_shwi (spec.star_width));
else
width = HOST_WIDE_INT_MIN;
}
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-02 8:31 ` Rainer Orth
@ 2016-12-02 15:52 ` Martin Sebor
2016-12-05 15:50 ` Martin Sebor
0 siblings, 1 reply; 20+ messages in thread
From: Martin Sebor @ 2016-12-02 15:52 UTC (permalink / raw)
To: Rainer Orth; +Cc: Gcc Patch List
On 12/02/2016 01:31 AM, Rainer Orth wrote:
> Hi Martin,
>
>> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
>> thing (i.e., the -Wformat-length and -fprintf-return-value options
>> behave incorrectly) when a conversion specification includes a width
>> or precision with a non-constant value. The code treats such cases
>> as if they were not provided which is incorrect and results in
>> the wrong bytes counts in warning messages and in the wrong ranges
>> being generated for such calls (or in the case sprintf(0, 0, ...)
>> for some such calls being eliminated).
>>
>> The attached patch corrects the handling of these cases, plus a couple
>> of other edge cases in the same area: it adjusts the parser to accept
>> precision in the form of just a period with no asterisk or decimal
>> digits after it (this sets the precision to zero), and corrects the
>> handling of zero precision and zero argument in integer directives
>> to produce no bytes on output.
>>
>> Finally, the patch also tightens up the constraint on the upper bound
>> of bounded functions like snprintf to be INT_MAX. The functions cannot
>> produce output in excess of INT_MAX + 1 bytes and some implementations
>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>> This is the subject of PR 78520.
>
> this patch broke Solaris bootstrap:
>
> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c: In function 'void {anonymous}::get_width_and_precision(const {anonymous}::conversion_spec&, long long int*, long long int*)':
> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: error: call of overloaded 'abs(long long int)' is ambiguous
> width = abs (tree_to_shwi (spec.star_width));
> ^
> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: note: candidates are:
> In file included from /usr/include/stdlib.h:12:0,
> from /vol/gcc/src/hg/trunk/local/gcc/system.h:258,
> from /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:49:
> /usr/include/iso/stdlib_iso.h:205:16: note: long int std::abs(long int)
> inline long abs(long _l) { return labs(_l); }
> ^
> /usr/include/iso/stdlib_iso.h:160:12: note: int std::abs(int)
> extern int abs(int);
> ^
>
> The following patch fixed this for me, but I've no idea if it's right.
> It bootstrapped successfully on sparc-sun-solaris2.12,
> i386-pc-solaris2.12, and x86_64-pc-linux-gnu.
Thanks for the heads up! I just looked at that code yesterday while
analyzing bug 78608, wondering if it was safe. Now I know it isn't.
I think it might be best to simply hand code the expression instead
of taking a chance on abs. Let me take care of it today along with 78608.
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-02 15:52 ` Martin Sebor
@ 2016-12-05 15:50 ` Martin Sebor
2016-12-05 15:54 ` Jakub Jelinek
2016-12-05 18:25 ` Jeff Law
0 siblings, 2 replies; 20+ messages in thread
From: Martin Sebor @ 2016-12-05 15:50 UTC (permalink / raw)
To: Rainer Orth; +Cc: Gcc Patch List
On 12/02/2016 08:52 AM, Martin Sebor wrote:
> On 12/02/2016 01:31 AM, Rainer Orth wrote:
>> Hi Martin,
>>
>>> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
>>> thing (i.e., the -Wformat-length and -fprintf-return-value options
>>> behave incorrectly) when a conversion specification includes a width
>>> or precision with a non-constant value. The code treats such cases
>>> as if they were not provided which is incorrect and results in
>>> the wrong bytes counts in warning messages and in the wrong ranges
>>> being generated for such calls (or in the case sprintf(0, 0, ...)
>>> for some such calls being eliminated).
>>>
>>> The attached patch corrects the handling of these cases, plus a couple
>>> of other edge cases in the same area: it adjusts the parser to accept
>>> precision in the form of just a period with no asterisk or decimal
>>> digits after it (this sets the precision to zero), and corrects the
>>> handling of zero precision and zero argument in integer directives
>>> to produce no bytes on output.
>>>
>>> Finally, the patch also tightens up the constraint on the upper bound
>>> of bounded functions like snprintf to be INT_MAX. The functions cannot
>>> produce output in excess of INT_MAX + 1 bytes and some implementations
>>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>>> This is the subject of PR 78520.
>>
>> this patch broke Solaris bootstrap:
>>
>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c: In function
>> 'void {anonymous}::get_width_and_precision(const
>> {anonymous}::conversion_spec&, long long int*, long long int*)':
>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: error:
>> call of overloaded 'abs(long long int)' is ambiguous
>> width = abs (tree_to_shwi (spec.star_width));
>> ^
>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: note:
>> candidates are:
>> In file included from /usr/include/stdlib.h:12:0,
>> from /vol/gcc/src/hg/trunk/local/gcc/system.h:258,
>> from
>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:49:
>> /usr/include/iso/stdlib_iso.h:205:16: note: long int std::abs(long int)
>> inline long abs(long _l) { return labs(_l); }
>> ^
>> /usr/include/iso/stdlib_iso.h:160:12: note: int std::abs(int)
>> extern int abs(int);
>> ^
>>
>> The following patch fixed this for me, but I've no idea if it's right.
>> It bootstrapped successfully on sparc-sun-solaris2.12,
>> i386-pc-solaris2.12, and x86_64-pc-linux-gnu.
>
> Thanks for the heads up! I just looked at that code yesterday while
> analyzing bug 78608, wondering if it was safe. Now I know it isn't.
> I think it might be best to simply hand code the expression instead
> of taking a chance on abs. Let me take care of it today along with 78608.
I posted a bigger patch to fix this and other related problems on
Friday (https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00262.html).
In hindsight, I should have probably committed the fix for this
on its own. Please let me know if this is blocking you and I'll
commit this fix by itself today so you don't have to wait for
the bigger patch to get reviewed and approved.
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 15:50 ` Martin Sebor
@ 2016-12-05 15:54 ` Jakub Jelinek
2016-12-05 18:25 ` Jeff Law
1 sibling, 0 replies; 20+ messages in thread
From: Jakub Jelinek @ 2016-12-05 15:54 UTC (permalink / raw)
To: Martin Sebor; +Cc: Rainer Orth, Gcc Patch List
On Mon, Dec 05, 2016 at 08:50:08AM -0700, Martin Sebor wrote:
> I posted a bigger patch to fix this and other related problems on
> Friday (https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00262.html).
> In hindsight, I should have probably committed the fix for this
> on its own. Please let me know if this is blocking you and I'll
> commit this fix by itself today so you don't have to wait for
> the bigger patch to get reviewed and approved.
You could just change the abs use to absu_hwi or abs_hwi if you need
something quickly working (depending on whether HOST_WIDE_INT_MIN can
appear or not).
Jakub
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 15:50 ` Martin Sebor
2016-12-05 15:54 ` Jakub Jelinek
@ 2016-12-05 18:25 ` Jeff Law
2016-12-05 18:30 ` Marek Polacek
` (2 more replies)
1 sibling, 3 replies; 20+ messages in thread
From: Jeff Law @ 2016-12-05 18:25 UTC (permalink / raw)
To: Martin Sebor, Rainer Orth; +Cc: Gcc Patch List
On 12/05/2016 08:50 AM, Martin Sebor wrote:
> On 12/02/2016 08:52 AM, Martin Sebor wrote:
>> On 12/02/2016 01:31 AM, Rainer Orth wrote:
>>> Hi Martin,
>>>
>>>> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
>>>> thing (i.e., the -Wformat-length and -fprintf-return-value options
>>>> behave incorrectly) when a conversion specification includes a width
>>>> or precision with a non-constant value. The code treats such cases
>>>> as if they were not provided which is incorrect and results in
>>>> the wrong bytes counts in warning messages and in the wrong ranges
>>>> being generated for such calls (or in the case sprintf(0, 0, ...)
>>>> for some such calls being eliminated).
>>>>
>>>> The attached patch corrects the handling of these cases, plus a couple
>>>> of other edge cases in the same area: it adjusts the parser to accept
>>>> precision in the form of just a period with no asterisk or decimal
>>>> digits after it (this sets the precision to zero), and corrects the
>>>> handling of zero precision and zero argument in integer directives
>>>> to produce no bytes on output.
>>>>
>>>> Finally, the patch also tightens up the constraint on the upper bound
>>>> of bounded functions like snprintf to be INT_MAX. The functions cannot
>>>> produce output in excess of INT_MAX + 1 bytes and some implementations
>>>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>>>> This is the subject of PR 78520.
>>>
>>> this patch broke Solaris bootstrap:
>>>
>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c: In function
>>> 'void {anonymous}::get_width_and_precision(const
>>> {anonymous}::conversion_spec&, long long int*, long long int*)':
>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: error:
>>> call of overloaded 'abs(long long int)' is ambiguous
>>> width = abs (tree_to_shwi (spec.star_width));
>>> ^
>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: note:
>>> candidates are:
>>> In file included from /usr/include/stdlib.h:12:0,
>>> from /vol/gcc/src/hg/trunk/local/gcc/system.h:258,
>>> from
>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:49:
>>> /usr/include/iso/stdlib_iso.h:205:16: note: long int std::abs(long int)
>>> inline long abs(long _l) { return labs(_l); }
>>> ^
>>> /usr/include/iso/stdlib_iso.h:160:12: note: int std::abs(int)
>>> extern int abs(int);
>>> ^
>>>
>>> The following patch fixed this for me, but I've no idea if it's right.
>>> It bootstrapped successfully on sparc-sun-solaris2.12,
>>> i386-pc-solaris2.12, and x86_64-pc-linux-gnu.
>>
>> Thanks for the heads up! I just looked at that code yesterday while
>> analyzing bug 78608, wondering if it was safe. Now I know it isn't.
>> I think it might be best to simply hand code the expression instead
>> of taking a chance on abs. Let me take care of it today along with
>> 78608.
>
> I posted a bigger patch to fix this and other related problems on
> Friday (https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00262.html).
> In hindsight, I should have probably committed the fix for this
> on its own. Please let me know if this is blocking you and I'll
> commit this fix by itself today so you don't have to wait for
> the bigger patch to get reviewed and approved.
What's the concern with using std::abs?
We're already using std::min std::max, std::swap and others.
jeff
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:25 ` Jeff Law
@ 2016-12-05 18:30 ` Marek Polacek
2016-12-05 18:37 ` Jeff Law
2016-12-05 18:36 ` Jakub Jelinek
2016-12-05 18:53 ` Martin Sebor
2 siblings, 1 reply; 20+ messages in thread
From: Marek Polacek @ 2016-12-05 18:30 UTC (permalink / raw)
To: Jeff Law; +Cc: Martin Sebor, Rainer Orth, Gcc Patch List
On Mon, Dec 05, 2016 at 11:25:02AM -0700, Jeff Law wrote:
> We're already using std::min std::max, std::swap and others.
Note we're not using std::min nor std::max. I gave this a shot a while ago,
but it didn't pan out:
https://gcc.gnu.org/ml/gcc-patches/2015-07/msg00886.html
Marek
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:25 ` Jeff Law
2016-12-05 18:30 ` Marek Polacek
@ 2016-12-05 18:36 ` Jakub Jelinek
2016-12-05 18:53 ` Martin Sebor
2 siblings, 0 replies; 20+ messages in thread
From: Jakub Jelinek @ 2016-12-05 18:36 UTC (permalink / raw)
To: Jeff Law; +Cc: Martin Sebor, Rainer Orth, Gcc Patch List
On Mon, Dec 05, 2016 at 11:25:02AM -0700, Jeff Law wrote:
> >>
> >>Thanks for the heads up! I just looked at that code yesterday while
> >>analyzing bug 78608, wondering if it was safe. Now I know it isn't.
> >>I think it might be best to simply hand code the expression instead
> >>of taking a chance on abs. Let me take care of it today along with
> >>78608.
> >
> >I posted a bigger patch to fix this and other related problems on
> >Friday (https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00262.html).
> >In hindsight, I should have probably committed the fix for this
> >on its own. Please let me know if this is blocking you and I'll
> >commit this fix by itself today so you don't have to wait for
> >the bigger patch to get reviewed and approved.
> What's the concern with using std::abs?
We already have abs_hwi and absu_hwi where you choose the semantics you
want. std::abs might not even have the right overload for HWI.
Jakub
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:30 ` Marek Polacek
@ 2016-12-05 18:37 ` Jeff Law
2016-12-05 18:39 ` Jakub Jelinek
0 siblings, 1 reply; 20+ messages in thread
From: Jeff Law @ 2016-12-05 18:37 UTC (permalink / raw)
To: Marek Polacek; +Cc: Martin Sebor, Rainer Orth, Gcc Patch List
On 12/05/2016 11:30 AM, Marek Polacek wrote:
> On Mon, Dec 05, 2016 at 11:25:02AM -0700, Jeff Law wrote:
>> We're already using std::min std::max, std::swap and others.
>
> Note we're not using std::min nor std::max. I gave this a shot a while ago,
> but it didn't pan out:
> https://gcc.gnu.org/ml/gcc-patches/2015-07/msg00886.html
>
> Marek
>
tree-ssa-phiprop.c uses std::min and std::max
Jeff
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:37 ` Jeff Law
@ 2016-12-05 18:39 ` Jakub Jelinek
0 siblings, 0 replies; 20+ messages in thread
From: Jakub Jelinek @ 2016-12-05 18:39 UTC (permalink / raw)
To: Jeff Law; +Cc: Marek Polacek, Martin Sebor, Rainer Orth, Gcc Patch List
On Mon, Dec 05, 2016 at 11:37:23AM -0700, Jeff Law wrote:
> On 12/05/2016 11:30 AM, Marek Polacek wrote:
> >On Mon, Dec 05, 2016 at 11:25:02AM -0700, Jeff Law wrote:
> >>We're already using std::min std::max, std::swap and others.
> >
> >Note we're not using std::min nor std::max. I gave this a shot a while ago,
> >but it didn't pan out:
> >https://gcc.gnu.org/ml/gcc-patches/2015-07/msg00886.html
> >
> > Marek
> >
> tree-ssa-phiprop.c uses std::min and std::max
If you mean the
std::max(std::min(a0, c), std::min(std::max(a1, c), b))
line, that is in a comment.
Jakub
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:25 ` Jeff Law
2016-12-05 18:30 ` Marek Polacek
2016-12-05 18:36 ` Jakub Jelinek
@ 2016-12-05 18:53 ` Martin Sebor
2016-12-06 23:30 ` Jeff Law
2 siblings, 1 reply; 20+ messages in thread
From: Martin Sebor @ 2016-12-05 18:53 UTC (permalink / raw)
To: Jeff Law, Rainer Orth; +Cc: Gcc Patch List
On 12/05/2016 11:25 AM, Jeff Law wrote:
> On 12/05/2016 08:50 AM, Martin Sebor wrote:
>> On 12/02/2016 08:52 AM, Martin Sebor wrote:
>>> On 12/02/2016 01:31 AM, Rainer Orth wrote:
>>>> Hi Martin,
>>>>
>>>>> PR 78521 notes that the gimple-ssa-sprintf pass doesn't do the right
>>>>> thing (i.e., the -Wformat-length and -fprintf-return-value options
>>>>> behave incorrectly) when a conversion specification includes a width
>>>>> or precision with a non-constant value. The code treats such cases
>>>>> as if they were not provided which is incorrect and results in
>>>>> the wrong bytes counts in warning messages and in the wrong ranges
>>>>> being generated for such calls (or in the case sprintf(0, 0, ...)
>>>>> for some such calls being eliminated).
>>>>>
>>>>> The attached patch corrects the handling of these cases, plus a couple
>>>>> of other edge cases in the same area: it adjusts the parser to accept
>>>>> precision in the form of just a period with no asterisk or decimal
>>>>> digits after it (this sets the precision to zero), and corrects the
>>>>> handling of zero precision and zero argument in integer directives
>>>>> to produce no bytes on output.
>>>>>
>>>>> Finally, the patch also tightens up the constraint on the upper bound
>>>>> of bounded functions like snprintf to be INT_MAX. The functions
>>>>> cannot
>>>>> produce output in excess of INT_MAX + 1 bytes and some implementations
>>>>> (e.g., Solaris) fail with EINVAL when the bound is INT_MAX or more.
>>>>> This is the subject of PR 78520.
>>>>
>>>> this patch broke Solaris bootstrap:
>>>>
>>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c: In function
>>>> 'void {anonymous}::get_width_and_precision(const
>>>> {anonymous}::conversion_spec&, long long int*, long long int*)':
>>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: error:
>>>> call of overloaded 'abs(long long int)' is ambiguous
>>>> width = abs (tree_to_shwi (spec.star_width));
>>>> ^
>>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:777:45: note:
>>>> candidates are:
>>>> In file included from /usr/include/stdlib.h:12:0,
>>>> from /vol/gcc/src/hg/trunk/local/gcc/system.h:258,
>>>> from
>>>> /vol/gcc/src/hg/trunk/local/gcc/gimple-ssa-sprintf.c:49:
>>>> /usr/include/iso/stdlib_iso.h:205:16: note: long int std::abs(long int)
>>>> inline long abs(long _l) { return labs(_l); }
>>>> ^
>>>> /usr/include/iso/stdlib_iso.h:160:12: note: int std::abs(int)
>>>> extern int abs(int);
>>>> ^
>>>>
>>>> The following patch fixed this for me, but I've no idea if it's right.
>>>> It bootstrapped successfully on sparc-sun-solaris2.12,
>>>> i386-pc-solaris2.12, and x86_64-pc-linux-gnu.
>>>
>>> Thanks for the heads up! I just looked at that code yesterday while
>>> analyzing bug 78608, wondering if it was safe. Now I know it isn't.
>>> I think it might be best to simply hand code the expression instead
>>> of taking a chance on abs. Let me take care of it today along with
>>> 78608.
>>
>> I posted a bigger patch to fix this and other related problems on
>> Friday (https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00262.html).
>> In hindsight, I should have probably committed the fix for this
>> on its own. Please let me know if this is blocking you and I'll
>> commit this fix by itself today so you don't have to wait for
>> the bigger patch to get reviewed and approved.
> What's the concern with using std::abs?
My concern, when I wrote the reply n Friday, was that not all C++98
implementations may get std::abs right, declare it in the right header,
avoid defining the abs macro, or put it in namespace std. (IIRC,
the standard itself wasn't quite right.)
I also need to avoid calling abs with a TYPE_MIN argument because
that's undefined and flagged by ubsan (as per the bug in the subject,
though it was not a result of calling abs but rather that of negating
it).
Besides avoiding the undefined behavior in the compiler I also need
diagnose it (in the program). The test case for it goes like this:
int n = sprintf (0, 0, "%*i", INT_MIN, 0);
where the INT_MIN is interpreted as the left justification flag
followed by a positive width of -(unsigned long)INT_MIN. The
problem is that the function (declared to return int0 is being
asked to return INT_MAX + 1 which is undefined (in the program).
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-12-05 18:53 ` Martin Sebor
@ 2016-12-06 23:30 ` Jeff Law
0 siblings, 0 replies; 20+ messages in thread
From: Jeff Law @ 2016-12-06 23:30 UTC (permalink / raw)
To: Martin Sebor, Rainer Orth; +Cc: Gcc Patch List
On 12/05/2016 11:52 AM, Martin Sebor wrote:
>> What's the concern with using std::abs?
>
> My concern, when I wrote the reply n Friday, was that not all C++98
> implementations may get std::abs right, declare it in the right header,
> avoid defining the abs macro, or put it in namespace std. (IIRC,
> the standard itself wasn't quite right.)
>
> I also need to avoid calling abs with a TYPE_MIN argument because
> that's undefined and flagged by ubsan (as per the bug in the subject,
> though it was not a result of calling abs but rather that of negating
> it).
I'm less concerned about the older C++ implementations as I am about the
TYPE_MIN overflow. Thanks for clarifying.
>
> Besides avoiding the undefined behavior in the compiler I also need
> diagnose it (in the program). The test case for it goes like this:
>
> int n = sprintf (0, 0, "%*i", INT_MIN, 0);
>
> where the INT_MIN is interpreted as the left justification flag
> followed by a positive width of -(unsigned long)INT_MIN. The
> problem is that the function (declared to return int0 is being
> asked to return INT_MAX + 1 which is undefined (in the program).
Understood. Thanks again.
jeff
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-29 8:05 ` Christophe Lyon
@ 2016-11-29 21:58 ` Martin Sebor
0 siblings, 0 replies; 20+ messages in thread
From: Martin Sebor @ 2016-11-29 21:58 UTC (permalink / raw)
To: Christophe Lyon; +Cc: David Edelsohn, GCC Patches
On 11/29/2016 01:04 AM, Christophe Lyon wrote:
> On 29 November 2016 at 03:59, Martin Sebor <msebor@gmail.com> wrote:
>> On 11/28/2016 06:35 PM, David Edelsohn wrote:
>>>
>>> Martin,
>>>
>>> I am seeing a number of new failures with the testcases on AIX.
>>>
>>> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test for excess errors)
>>>
>>> Excess errors:
>>>
>>> /nasfarm/edelsohn/src/src/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c:1485:3:
>>> warning: specified destination size 2147483647 is too large
>>> [-Wformat-length=]
>>>
>>>
>>> Also, a number of errors like
>>>
>>> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test for
>>> warnings, line 256)
>>> PASS: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c (test for warnings, line
>>> 256)
>>
>>
>> Thanks. The DejaGnu directives in the tests likely needs adjusting.
>> Let me look into it tomorrow.
>>
>> Martin
>
>
> Probably. I'm seeing errors on arm*:
> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
> for warnings, line 256)
> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
> for warnings, line 260)
> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
> for warnings, line 264)
I committed r242977 to resolve the failures. My AIX 7.1 ILP32
cross-build and test run is clean but let me know if some persist
elsewhere.
Thanks
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-29 2:59 ` Martin Sebor
@ 2016-11-29 8:05 ` Christophe Lyon
2016-11-29 21:58 ` Martin Sebor
0 siblings, 1 reply; 20+ messages in thread
From: Christophe Lyon @ 2016-11-29 8:05 UTC (permalink / raw)
To: Martin Sebor; +Cc: David Edelsohn, GCC Patches
On 29 November 2016 at 03:59, Martin Sebor <msebor@gmail.com> wrote:
> On 11/28/2016 06:35 PM, David Edelsohn wrote:
>>
>> Martin,
>>
>> I am seeing a number of new failures with the testcases on AIX.
>>
>> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test for excess errors)
>>
>> Excess errors:
>>
>> /nasfarm/edelsohn/src/src/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c:1485:3:
>> warning: specified destination size 2147483647 is too large
>> [-Wformat-length=]
>>
>>
>> Also, a number of errors like
>>
>> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test for
>> warnings, line 256)
>> PASS: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c (test for warnings, line
>> 256)
>
>
> Thanks. The DejaGnu directives in the tests likely needs adjusting.
> Let me look into it tomorrow.
>
> Martin
Probably. I'm seeing errors on arm*:
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
for warnings, line 256)
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
for warnings, line 260)
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test
for warnings, line 264)
Christophe
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
2016-11-29 1:35 David Edelsohn
@ 2016-11-29 2:59 ` Martin Sebor
2016-11-29 8:05 ` Christophe Lyon
0 siblings, 1 reply; 20+ messages in thread
From: Martin Sebor @ 2016-11-29 2:59 UTC (permalink / raw)
To: David Edelsohn; +Cc: GCC Patches
On 11/28/2016 06:35 PM, David Edelsohn wrote:
> Martin,
>
> I am seeing a number of new failures with the testcases on AIX.
>
> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test for excess errors)
>
> Excess errors:
> /nasfarm/edelsohn/src/src/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c:1485:3:
> warning: specified destination size 2147483647 is too large
> [-Wformat-length=]
>
>
> Also, a number of errors like
>
> FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test for
> warnings, line 256)
> PASS: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c (test for warnings, line 256)
Thanks. The DejaGnu directives in the tests likely needs adjusting.
Let me look into it tomorrow.
Martin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] correct handling of non-constant width and precision (pr 78521)
@ 2016-11-29 1:35 David Edelsohn
2016-11-29 2:59 ` Martin Sebor
0 siblings, 1 reply; 20+ messages in thread
From: David Edelsohn @ 2016-11-29 1:35 UTC (permalink / raw)
To: Martin Sebor; +Cc: GCC Patches
Martin,
I am seeing a number of new failures with the testcases on AIX.
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test for excess errors)
Excess errors:
/nasfarm/edelsohn/src/src/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c:1485:3:
warning: specified destination size 2147483647 is too large
[-Wformat-length=]
Also, a number of errors like
FAIL: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c target lp64 (test for
warnings, line 256)
PASS: gcc.dg/tree-ssa/builtin-sprintf-warn-3.c (test for warnings, line 256)
Thanks, David
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2016-12-06 23:30 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-28 3:34 [PATCH] correct handling of non-constant width and precision (pr 78521) Martin Sebor
2016-11-28 20:26 ` Jeff Law
2016-11-29 0:42 ` Joseph Myers
2016-11-29 16:57 ` Martin Sebor
2016-11-29 20:14 ` Martin Sebor
2016-12-02 8:31 ` Rainer Orth
2016-12-02 15:52 ` Martin Sebor
2016-12-05 15:50 ` Martin Sebor
2016-12-05 15:54 ` Jakub Jelinek
2016-12-05 18:25 ` Jeff Law
2016-12-05 18:30 ` Marek Polacek
2016-12-05 18:37 ` Jeff Law
2016-12-05 18:39 ` Jakub Jelinek
2016-12-05 18:36 ` Jakub Jelinek
2016-12-05 18:53 ` Martin Sebor
2016-12-06 23:30 ` Jeff Law
2016-11-29 1:35 David Edelsohn
2016-11-29 2:59 ` Martin Sebor
2016-11-29 8:05 ` Christophe Lyon
2016-11-29 21:58 ` Martin Sebor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).