5 ms·
"format not a string literal" is one warning I always upgrade to an error. Dear reader: you should do this, too!
by tom_ 4y ago
"format not a string literal" is one warning I always upgrade to an error. Dear reader: you should do this, too!
- wrigby 4y agoThanks! This prompted me to look up the flag to enable this. For GCC it’s: -Werror=format-security
- fay59 4y agoThe flag is -Wformat-nonliteral or -Wformat=2. -Wformat-security only includes a weaker variant that will warn if you pass a variable and no arguments to printf.
- Gigachad 4y agoWhy are these not compiler errors by default? Opting in to such important safety features seems like broken design.
- tedunangst 4y agoThere's more than one compiler.
- Conscat 4y agoHow could that really work? printf is a library function, not an intrinsic. A function named printf can do anything your heart desires.
- ladberg 4y agoDepends on the compiler, but you'd mark the printf function with something like: __attribute__((format(printf, 1, 2)))
- account42 4y agoIt's a standard library function meaning the compiler can assume that it follows the standard. Specifically for GCC [0]: > The ISO C90 functions abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, exp, fabs, floor, fmod, fprintf, fputs, free, frexp, fscanf, isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper, labs, ldexp, log10, log, malloc, memchr, memcmp, memcpy, memset, modf, pow, printf, putchar, puts, realloc, scanf, sinh, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, tanh, tan, vfprintf, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). Builtin here doesn't mean that GCC won't ever emit calls to library functions, only that it reserves not to and allows itselfs to make assumptions about how the functions work, including diagnosing misuse. The library functions themselves might also be marked with __attribute__(format(...)) as the sibling comment notes but that is not necessarily required for GCC to check the format strings. [0] https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
- layer8 4y agoOne reason is locale-dependent format strings which are loaded from resource files. Also, in personal projects, I almost always used custom wrapper functions for printf/fprintf/sprintf for various reasons, so that default wouldn’t be of much use, unless maybe I could enable it for the custom functions.
- garaetjjte 4y agoAt least for GCC/clang, you can mark your functions with special __attribute__ format. For loading translated strings, I'm missing some library function to verify whether two format strings are argument-compatible.
- wyldfire 4y ago> One reason is locale-dependent format strings which are loaded from resource files. Aren't those usually resolved to string literals by preprocessor such that the compiler still could emit a warning?
- AnimalMuppet 4y agoThat might be possible if the "resource file" was processed at compile time. I've never seen a C toolchain that did it that way, though - I've only seen them read in at runtime. And at that point, the preprocessor can't save you.
- layer8 4y agoSince the locale is only determined at runtime, and might even change at runtime, the format strings are usually dynamically loaded from text files, and are not in the form of string literals seen by the compiler.
- panzi 4y agoYou can with __attribute__((format(printf, 1, 2))) See: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attrib...
- tom_ 4y ago
- plq 4y agoIn principle, they are not enabled by default because a C compiler must be able to compile standard C by default. One practical reason I can think of is because not everyone compiles their own code. You must most definitely look for and enable such flags as they become available in your own projects. (eg I was rooting for -Wlifetime but it did not land for various reasons) But when you compile other people's code, your breaking your local build doesn't help anyone. Best you can do is to submit a bug report, which may or may not be ignored.
- tialaramex 4y agoI don't like a lot of things in C++, but one thing worth praising in particular is std::format std::format specifically only works for constant† format strings. Not because they can't make it work with a dynamic format, std::vformat is exactly that, but most of the time you don't want and shouldn't use a dynamic format and the choice to refuse dynamic formats in std::format means fewer people are going to end up shooting themselves in the foot. Because it requires constant formats, std::format also gets to guarantee compile time errors. Too many or not enough arguments? Program won't build. Wrong types? Program won't build. This shifts some nasty errors hard left. † Not necessarily a literal, any constant expression, so it just needs to have some concrete value when it's compiled.
- planede 4y agoNice, I didn't know about https://wg21.link/P2216 https://wg21.link/P2216 .