[Bug c/95755] New: GCC 10.1.0 reports bogus sizes in -Werror=format-truncation= error
jonathan.leffler at gmail dot com
gcc-bugzilla@gcc.gnu.org
Fri Jun 19 00:07:31 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95755
Bug ID: 95755
Summary: GCC 10.1.0 reports bogus sizes in
-Werror=format-truncation= error
Product: gcc
Version: 10.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: jonathan.leffler at gmail dot com
Target Milestone: ---
Created attachment 48754
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48754&action=edit
Preprocessed source (also in body of bug report)
GCC 10.1.0 on an RHEL 7 machine gives an incorrect warning about truncated
output via snprintf, claiming a size that is much bigger than is justified.
Compilation error induced by -Werror shows:
gcc-10.1.0-bug-v2.c: In function ‘mz_format’:
gcc-10.1.0-bug-v2.c:60:48: error: ‘%s’ directive output may be truncated
writing up to 4551 bytes into a region of size 513 [-Werror=format-truncation=]
60 | snprintf(rcb->mz_url, sizeof(rcb->mz_url), "%s/name/%s/abc1234",
| ^~~~~~~~~~~~~~~~~~~~
gcc-10.1.0-bug-v2.c:60:5: note: ‘snprintf’ output between 15 and 8837 bytes
into a destination of size 513
60 | snprintf(rcb->mz_url, sizeof(rcb->mz_url), "%s/name/%s/abc1234",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 | rcred->variant.variant02.az_field11,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
62 | rcred->variant.variant02.common01);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
The mz_url member is 513 bytes (that's correct); the format string has 15 bytes
apart from the two %s directives (including the null byte); the field
az_field11 is 129 bytes; the field common01 is 161 bytes; the maximum total
length should be much less than 513 bytes (15 + 128 + 160 = 303), therefore,
and not 8837 bytes, and should not suffer truncation and hence the warning
(error) is bogus.
Version and options:
Using built-in specs.
COLLECT_GCC=gcc
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-10.1.0/configure --prefix=/usr/gcc/v10.1.0
CC=/usr/gcc/v9.3.0/bin/gcc CXX=/usr/gcc/v9.3.0/bin/g++
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.1.0 (GCC)
COLLECT_GCC_OPTIONS='-O3' '-Wall' '-Werror' '-c' '-v' '-save-temps'
'-mtune=generic' '-march=x86-64'
/work1/gcc/v10.1.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/10.1.0/cc1 -E -quiet
-v -iprefix /work1/gcc/v10.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0/
gcc-10.1.0-bug-v2.c -mtune=generic -march=x86-64 -Wall -Werror -O3
-fpch-preprocess -o gcc-10.1.0-bug-v2.i
ignoring nonexistent directory
"/work1/gcc/v10.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/include"
ignoring duplicate directory
"/work1/gcc/v10.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/10.1.0/include"
ignoring duplicate directory
"/work1/gcc/v10.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/10.1.0/include-fixed"
ignoring nonexistent directory
"/work1/gcc/v10.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/work1/gcc/v10.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0/include
/work1/gcc/v10.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0/include-fixed
/usr/local/include
/work1/gcc/v10.1.0/bin/../lib/gcc/../../include
/usr/include
End of search list.
COLLECT_GCC_OPTIONS='-O3' '-Wall' '-Werror' '-c' '-v' '-save-temps'
'-mtune=generic' '-march=x86-64'
/work1/gcc/v10.1.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/10.1.0/cc1
-fpreprocessed gcc-10.1.0-bug-v2.i -quiet -dumpbase gcc-10.1.0-bug-v2.c
-mtune=generic -march=x86-64 -auxbase gcc-10.1.0-bug-v2 -O3 -Wall -Werror
-version -o gcc-10.1.0-bug-v2.s
GNU C17 (GCC) version 10.1.0 (x86_64-pc-linux-gnu)
compiled by GNU C version 10.1.0, GMP version 6.2.0, MPFR version
4.0.2, MPC version 1.1.0, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C17 (GCC) version 10.1.0 (x86_64-pc-linux-gnu)
compiled by GNU C version 10.1.0, GMP version 6.2.0, MPFR version
4.0.2, MPC version 1.1.0, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 86d44affd1f923d461a5269e6fdf7b02
Preprocessed output:
# 1 "gcc-10.1.0-bug-v2.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "gcc-10.1.0-bug-v2.c"
# 1 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h" 1
3 4
# 143 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
# 143 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
typedef long int ptrdiff_t;
# 209 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
typedef long unsigned int size_t;
# 321 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
typedef int wchar_t;
# 415 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
typedef struct {
long long __max_align_ll __attribute__((__aligned__(__alignof__(long
long))));
long double __max_align_ld __attribute__((__aligned__(__alignof__(long
double))));
# 426 "/work1/gcc/v10.1.0/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include/stddef.h"
3 4
} max_align_t;
# 5 "gcc-10.1.0-bug-v2.c" 2
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 24 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 399 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 400 "/usr/include/features.h" 2 3 4
# 25 "/usr/include/sys/cdefs.h" 2 3 4
# 392 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 393 "/usr/include/sys/cdefs.h" 2 3 4
# 6 "gcc-10.1.0-bug-v2.c" 2
# 8 "gcc-10.1.0-bug-v2.c"
extern int snprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, ...)
# 10 "gcc-10.1.0-bug-v2.c" 3 4
__attribute__ ((__nothrow__))
# 10 "gcc-10.1.0-bug-v2.c"
__attribute__ ((__format__ (__printf__, 3,
4)));
typedef struct am_option
{
char am_field01[128+1];
char am_field02[256+1];
char am_field03[64+1];
char common01[2048+1];
char am_field04[2048+1];
} awsc_t;
typedef struct az_option
{
char az_field11[128+1];
char az_field12[36+1];
char az_field13[64+1];
char az_field14[36+1];
char *az_field15;
char common01[160+1];
} azrc_t;
typedef struct unified
{
int flags;
union alternatives
{
awsc_t variant01;
azrc_t variant02;
} variant;
} mz_unity;
typedef struct MZ_CB
{
char mz_url[512+1];
mz_unity *mz_creds;
} mz_cb;
extern void mz_format(mz_cb *rcb);
void mz_format(mz_cb *rcb)
{
mz_unity *ocred = rcb->mz_creds;
mz_unity ncred = *ocred;
mz_unity *rcred = &ncred;
snprintf(rcb->mz_url, sizeof(rcb->mz_url), "%s/name/%s/abc1234",
rcred->variant.variant02.az_field11,
rcred->variant.variant02.common01);
}
Source code - contains comments about what happens when fields are omitted
(sometimes, the size increases from 8837 to a larger number when a field is
omitted). The first two comments are superfluous (sorry) but needed to keep
line numbers accurate. The ncred and rcred variables in the function appear to
be a necessary part of the reproduction. Changing the elements in struct
am_option changes the size of the overflow reported.
GCC 9.2.0 on the same machine does not report any problem. Both 9.2.0 and
10.1.0 were compiled on this machine by me - not downloaded from somewhere -
but used the relevant source without any changes.
/* Starting from commit 87db316 */
/* Complains about overwriting 8837 bytes into 513 */
#include <stddef.h> /* size_t */
#include <sys/cdefs.h> /* __THROWNL */
/* From <stdio.h> */
extern int snprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, ...)
__THROWNL __attribute__ ((__format__ (__printf__, 3,
4)));
typedef struct am_option
{
/* Removing any element reduces the size of the overflow */
char am_field01[128+1];
char am_field02[256+1];
char am_field03[64+1];
char common01[2048+1];
char am_field04[2048+1];
} awsc_t;
typedef struct az_option
{
char az_field11[128+1];
/* Removing az_field12 changes size from 8837 to 8877 */
char az_field12[36+1];
/* Removing az_field13 changes size from 8837 to 8901 */
char az_field13[64+1];
/* Removing az_field14 changes size from 8837 to 8877 */
char az_field14[36+1];
/* Removing az_field15 changes size from 8837 to 8849 */
char *az_field15;
char common01[160+1];
} azrc_t;
typedef struct unified
{
int flags;
union alternatives
{
awsc_t variant01;
azrc_t variant02;
} variant;
} mz_unity;
typedef struct MZ_CB
{
char mz_url[512+1];
mz_unity *mz_creds;
} mz_cb;
extern void mz_format(mz_cb *rcb);
void mz_format(mz_cb *rcb)
{
mz_unity *ocred = rcb->mz_creds;
mz_unity ncred = *ocred;
mz_unity *rcred = &ncred;
snprintf(rcb->mz_url, sizeof(rcb->mz_url), "%s/name/%s/abc1234",
rcred->variant.variant02.az_field11,
rcred->variant.variant02.common01);
}
More information about the Gcc-bugs
mailing list