public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug other/103736] New: snprintf bogus format-truncation, disregarding modulo on argument
@ 2021-12-15 14:39 patrickdepinguin at gmail dot com
2021-12-15 17:12 ` [Bug other/103736] " msebor at gcc dot gnu.org
0 siblings, 1 reply; 2+ messages in thread
From: patrickdepinguin at gmail dot com @ 2021-12-15 14:39 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103736
Bug ID: 103736
Summary: snprintf bogus format-truncation, disregarding modulo
on argument
Product: gcc
Version: 11.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: other
Assignee: unassigned at gcc dot gnu.org
Reporter: patrickdepinguin at gmail dot com
Target Milestone: ---
gcc 11.2.0 and gcc 9.4.0 give a bogus format-truncation warning on following
test case compiled with -Wall and -O2:
#include <stdint.h>
#include <stdio.h>
void func(void) {
extern int8_t timezoneval;
char timezone[1+2+1];
if(timezoneval < 0)
{
snprintf(timezone, sizeof(timezone),"-%02d",-(timezoneval % 100));
}
else
{
snprintf(timezone, sizeof(timezone),"+%02d", timezoneval % 100);
}
}
Warning:
/tmp/test.cpp: In function 'void func()':
/tmp/test.cpp:15:52: warning: 'snprintf' output may be truncated before the
last format character [-Wformat-truncation=]
15 | snprintf(timezone, sizeof(timezone),"+%02d", timezoneval %
100);
| ^
/tmp/test.cpp:15:18: note: 'snprintf' output between 4 and 5 bytes into a
destination of size 4
15 | snprintf(timezone, sizeof(timezone),"+%02d", timezoneval %
100);
|
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since timezoneval is used modulo 100, it will not take up more than two digits
(note that if timezoneval is negative, its value is negated first, so the
string representation will be positive). Together with the literal sign
character, and the null-termination, max. total size is 4 bytes. Yet, gcc
considers that 5 bytes may be needed.
When the parentheses in the first snprintf are omitted, causing the modulo
operator to operate on the negated timezoneval, the warning disappears. Funnily
enough, the warning is about the _second_, unmodified, snprintf:
#include <stdint.h>
#include <stdio.h>
void func(void) {
extern int8_t timezoneval;
char timezone[1+2+1];
if(timezoneval < 0)
{
snprintf(timezone, sizeof(timezone),"-%02d",-timezoneval % 100);
}
else
{
snprintf(timezone, sizeof(timezone),"+%02d", timezoneval % 100);
}
}
I found some possibly related older bugs, but was unsure if it's the same and
known to still apply on gcc 11. Feel free to mark this one as duplicated to the
relevant one.
Bug #78969 - bogus snprintf truncation warning due to missing range info
Bug #77721 - -Wformat-truncation not uses arg range for converted vars
Bug #94021 - -Wformat-truncation false positive due to excessive integer range
^ permalink raw reply [flat|nested] 2+ messages in thread
* [Bug other/103736] snprintf bogus format-truncation, disregarding modulo on argument
2021-12-15 14:39 [Bug other/103736] New: snprintf bogus format-truncation, disregarding modulo on argument patrickdepinguin at gmail dot com
@ 2021-12-15 17:12 ` msebor at gcc dot gnu.org
0 siblings, 0 replies; 2+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-12-15 17:12 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103736
Martin Sebor <msebor at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |msebor at gcc dot gnu.org
--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning is based on the annotated IL below. The duplicate modulo
computation is optimized to take place just once (in PRE), before the
negativity test, the range of the result in the else branch is greater than the
code permits.
void func ()
{
char timezone[4];
signed char timezoneval.0_1;
int _4;
int _12;
signed char _13;
<bb 2> [local count: 1073741824]:
timezoneval.0_1 = timezoneval;
_13 = timezoneval.0_1 % 100;
_12 = (int) _13; >>> _12's range is [-99, 99]
if (timezoneval.0_1 < 0)
goto <bb 3>; [41.00%]
else
goto <bb 4>; [59.00%]
<bb 3> [local count: 440234144]:
_4 = -_12; _4's range is [0, 99]
snprintf (&timezone, 4, "-%02d", _4); so no warning here
goto <bb 5>; [100.00%]
<bb 4> [local count: 633507681]:
snprintf (&timezone, 4, "+%02d", _12); << -Wformat-truncation
<bb 5> [local count: 1073741824]:
timezone ={v} {CLOBBER};
return;
}
The warning can be avoided by using a local temporary copy of the extern
variable, like so
int x = timezoneval;
if(x < 0)
{
snprintf(timezone, sizeof(timezone),"-%02d",-(x % 100));
}
else
{
snprintf(timezone, sizeof(timezone),"+%02d", x % 100);
}
or simply:
int x = timezoneval % 100;
if(x < 0)
{
snprintf(timezone, sizeof(timezone),"-%02d",-x);
}
else
{
snprintf(timezone, sizeof(timezone),"+%02d", x);
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-12-15 17:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-15 14:39 [Bug other/103736] New: snprintf bogus format-truncation, disregarding modulo on argument patrickdepinguin at gmail dot com
2021-12-15 17:12 ` [Bug other/103736] " msebor at gcc dot gnu.org
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).