https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49905

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to David Binderman from comment #9)
> I tried a build of the gcc fortran compiler and I found this warning:
> 
> ../../../src/trunk/libgfortran/intrinsics/date_and_time.c:173:33: warning:
> ‘%+03d’ directive output truncated while writing ‘9’ bytes into a region of
> size ‘6’ [-Wformat-length=]
> 
> Source code is
> 
>     snprintf (zone, ZONE_LEN + 1, "%+03d%02d",
>           values[3] / 60, abs (values[3] % 60));
> 
> and
> 
> #define ZONE_LEN 5
> 
>   char zone[ZONE_LEN + 1];
> 
> While it is clear that the region size of 6 is fine, I can't see where the
> value 
> of 9 bytes is coming from.

First of all, I'd say the warning is badly worded, because it should make it
clear that what it guessed is the maximum length, unless it is equal to minimum
it might not really happen.  While it can use VRP, VRP is about what the
compiler can prove, while there can be other range restrictions just not
visible to the compiler.  I think the warning code should compute both minimum
and maximum, and have different wording for the cases where minimum == maximum
and there is overflow, or for when even minimum overflows, or when maximum
overflows (and the last one should be probably different warning level, because
the program could be just fine, have some mechanism hidden not visible to the
compiler that guarantees the values will never be out of certain ranges.

For abs (values[3] % 60) the compiler is able to prove the VR is [0, 59] and
thus %02d is guaranteed to be exact 2 characters.  For values[3] / 60, I think
the compiler can't see such a guarantee, there is just subtraction of fields
computed by two functions that are really black boxes for GCC analysis.
Thus, I'd expect that GCC for %+03d should compute minimum length of 3 and
maximum length of strlen ("+35791394") - 0x7fffffff / 60, or strlen
("-35791394") - (int) 0x80000000 / 60, i.e. 9.  Thus it is IMHO 9 + 2 + 1.

The code obviously relies on it to be timezone offsets, so expects values[3] /
60 must be in between -14 and +14 or so and then ZONE_LEN 5 is just fine.

Reply via email to