This patch adds %n to printf, as well as a compiler flag to disable it.
This is due to it having serious security issues when misused.
Details
- Reviewers
sivachandra lntue - Commits
- rG88b801392c93: [libc] add integer writing to printf
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I know that you are tied to the standards. Maybe expose llvmllibc extensions of safe or hardened functions, e.g., save_printf.
While the idea of having a seperate "safe" version of printf is not inherently bad, it's already been tried to little success. In the standard right now is the definitions for the _s versions of printf functions. These have bounds checking and disable %n, but are also not widely used. Convincing developers to switch is hard, so my current plan is to use the compile-time switch I've added to disable %n by default in the existing printf functions. This provides the security enhancements by default for all of the people who don't care/didn't know that %n existed, while still allowing people to turn it back on if they are really sure they know what they're doing.
Some libc implementations support compiling sources with FORTIFY_SOURCE, which (with compiler support) can call _chk() versions of functions like printf().
How best to support FORTIFY_SOURCE is an open question but it is something that is being thought about. Is this an area you are interested in helping with?
And that's one potential approach, to do more things with FORTIFY_SOURCE in Clang (and not require libc to carry special FORTIFY bits).
Do you really need compiler support?
#ifdef FORTIFY_SOURCE #include "checked_printf.h" #else #include "fast_printf.h" #endif
FORTIFY_SOURCE support has typically been provided through a combination of compiler and libc support (e.g. gcc and glibc, Clang and bionic). Multiple applications can link against the same libc, and some will want the FORTIFY_SOURCE versions and some will not, but all user code still just wants to call "mempcpy()" or whatever. When FORTIFY_SOURCE is enabled, the compiler can know to pick the _chk versions of the functions (and do some other work as well).
Maybe I'm stupid, but I would expect both headers to expose a printf.
int printf(const char * restrict format, ...) { do some checks here }
You could certainly do something like that.
FORTIFY_SOURCE is a long-established way of inserting a relatively low-cost runtime check to a number of libc functions. The compiler can also do some static checks and it can also decide things like "should this call to mempcpy() invoke the regular mempcpy(), or the one with extra checks?" and not simply call the one with extra checks every time.
For many projects, a "hardened" libc is nice but not sufficient, and they use tools like ASan instead (which can help catch memory problems across all the code and not just in the libc functions).
I think if we want to have "safe" versions of these functions we should do it via the FORTIFY_SOURCE mechanism since both glibc and bionic support it. LLVM's libc could carry code (like glibc and bionic) to support FORTIFY, if someone wants to contribute those patches. There might be other ways to achieve the same functionality. I'd like to continue this discussion, but that's probably best done on discourse.
libc/src/stdio/printf_core/write_int_converter.h | ||
---|---|---|
24 | How is this return value defined? Aren't errors normally -1? And do we have tests for this? |
add test for the nullptr check
libc/src/stdio/printf_core/write_int_converter.h | ||
---|---|---|
24 | this check is not in any of the specifications, and is a convenience feature that I added. The return value is negative, since the return value for printf is negative on errors. As for why it's -3, that's because -1 and -2 are used for file writing errors, and this allows me as the developer to tell what the error was. I have now added a test to check that it returns an error value when passed a null pointer. |
libc/src/stdio/printf_core/write_int_converter.h | ||
---|---|---|
24 | Sound like we'll need some commonly defined macros for these values as the number of different errors grows. |
add comment explaining the negative return value.
libc/src/stdio/printf_core/write_int_converter.h | ||
---|---|---|
24 | I don't expect the number of errors to grow much, but I will make a followup patch adding the error values to core_structs.h. |
How is this return value defined? Aren't errors normally -1? And do we have tests for this?