6 ms·
A few key points (also mentioned in the README): The "%n" specifier makes printf() fetch an int* argument and write the number of characters written so far to t
by st_goliath 4y ago
A few key points (also mentioned in the README): The "%n" specifier makes printf() fetch an int* argument and write the number of characters written so far to the target location. The funky stuff happens when you abuse that to overwrite the format string itself, actually making printf() Turing-complete.
This also means that if you lazily stuff a user controller string into a printf() style function (instead of doing e.g. `printf("%s", str)`), this can be used as a gadget for arbitrary memory writes (in addition to arbitrary stack reads). For this reason, there are compiler warnings if you use a format string that isn't a string literal (IIRC now on by default in GCC 11) and some C libraries like dietlibc refuse to implement %n.
- roenxi 4y ago%n looks like one of those mis-features that not only never should have been implemented but it is worth breaking backwards compatibility to remove. Programmers should be able to assume that printf isn't writing to memory under ordinary operation.
- deleted 4y ago[deleted]
- quietbritishjim 4y agoI think it's not that serious really. Using the wrong format string already has undefined behaviour so you should always hard code it as part of the logic of your program, even if %n didn't exist.
- zarzavat 4y agoBut usually using the wrong format string would just read from undefined memory locations. While that could be bad, it’s not as obviously catastrophic as writing to arbitrary memory locations.
- quietbritishjim 4y agoI had my language lawyer hat on. Technically undefined behaviour means literally any behaviour could happen, so in principle you could have a printf that wrote to random memory locations when you use a bad format string (even without %d) and it would be a conforming implementation. But looking at it now from a more practical point of view, I guess I can't see how that would happen, even with aggressive compiler optimisations (which are the usual thing to trigger really surprising consequences of undefined behaviours).
- ori_b 4y agoThat's what OpenBSD did: > The %n conversion specifier has serious security implications, so it was changed to no longer store the number of bytes written so far into the variable indicated by the pointer argument. Instead a syslog(3) message will be generated, after which the program is aborted with SIGABRT. https://man.openbsd.org/printf.3 https://man.openbsd.org/printf.3
- ojeda 4y agoN2834 ("Deprecate the %n format specifier in C2X") was discussed in WG14 (no consensus). https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2834.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2834.htm