Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
779 views
in Technique[技术] by (71.8m points)

c - How to circumvent format-truncation warning in GCC?

I'm getting the following gcc format-truncation warning:

test.c:8:33: warning: ‘/input’ directive output may be truncated writing 6 bytes into a region of size between 1 and 20 [-Wformat-truncation=]
snprintf(dst, sizeof(dst), "%s-more", src);
                             ^~~~~~
test.c:8:3: note: ‘snprintf’ output between 7 and 26 bytes into a destination of size 20
snprintf(dst, sizeof(dst), "%s-more", src);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

on code like this:

char dst[20];
char src[20];
scanf("%s", src);
snprintf(dst, sizeof(dst), "%s-more", src);
printf("%s
", dst);

I'm aware that it might be truncated - but this is exactly the reason why I'm using snprintf in the first place. Is there a way how to make it clear to the compiler that this is intended (without using a pragma or -Wno-format-truncation)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

  1. The warning was added in gcc7.1, see gcc7.1 release changes.
  2. From gcc docs:

Level 1 of -Wformat-truncation [...] warns only about calls to bounded functions whose return value is unused and that will most likely result in output truncation.

  1. The issue was a bug report and was closed as NOTABUG:

Unhandled output truncation is typically a bug in the program. [...]
In cases when truncation is expected the caller typically checks the return value from the function and handles it somehow (e.g., by branching on it). In those cases, the warning is not issued. The source line printed by the warning suggests that this is not one of those cases. The warning is doing what it was designed to do.

  1. But we can just check the return value of snprintf, which returns a negative value on error.

#include <stdio.h>
#include <stdlib.h>
void f(void) {
    char dst[2], src[2];
    // snprintf(dst, sizeof(dst), "%s!", src);

    int ret = snprintf(dst, sizeof(dst), "%s!", src);
    if (ret < 0) {
         abort();
    }

    // But don't we love confusing one liners?
    for (int ret = snprintf(dst, sizeof(dst), "%s!", src); ret < 0;) exit(ret);
    // Can we do better?
    snprintf(dst, sizeof(dst), "%s!", src) < 0 ? abort() : (void)0;
    // Don't we love obfuscation?
#define snprintf_nowarn(...) (snprintf(__VA_ARGS__) < 0 ? abort() : (void)0)
    snprintf_nowarn(dst, sizeof(dst), "%s!", src);
}

Tested on https://godbolt.org/ with gcc7.1 gcc7.2 gcc7.3 gcc8.1 with -O{0,1,2,3} -Wall -Wextra -pedantic. Gives no warning whatsoever. gcc8.1 optimizes/removes the call to abort() with optimization greater than -O1.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...