This is my code:
#include <stdio.h>
int main(void) {
int n;
fprintf(stdout, "Hello%n World\n", &n);
fprintf(stdout, "n: %d\n", n);
return 0;
}
This is my output:
Hellon: 0
fprintf
format specifier "%n"
not work? ISO/IEC 9899:201x C11 - 7.21.6.1 - The fprintf function
The conversion specifiers and their meanings are:
(...)
%n The argument shall be a pointer to signed integer into which is written the number of characters written to the output stream so far by this call to fprintf. No argument is converted, but one is consumed. If the conversion specification includes any flags, a field width, or a precision, the behavior is undefined. ...
(...)
This is my compiler version used on Code::Blocks:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=C:/Program\ Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev
0/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --bu
ild=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysr
oot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable
-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdc
xx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-
lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --
enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx
-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls
--disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=noco
na --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/p
rerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86
_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-s
tatic --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgv
ersion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https:/
/sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x
86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x
86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/
include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6
-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include
-I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/
mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prere
quisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw
32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-
rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L
/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
What is the use of %n in printf()? In C language, %n is a special format specifier. It cause printf() to load the variable pointed by corresponding argument. The loading is done with a value which is equal to the number of characters printed by printf() before the occurrence of %n.
In C printf(), %n is a special format specifier which instead of printing something causes printf() to load the variable pointed by the corresponding argument with a value equal to the number of characters that have been printed by printf() before the occurrence of %n.
Printf is not the thing being buffered, it's stdio, so all similar functions will behave in the same way. To demonstrate the buffering, all you have to do is printf a lot of characters, usually more than 1024, and printf will print as you will have exceeded the maximum buffer length and it will automatically fflush.
By using %n in your format string, you tell Java to use the value returned by System. getProperty("line. separator") , which is the line separator for the current system.
As documented in the Microsoft documentation, the %n
is disabled by default in the Microsoft C library used on your MinGW system:
Important
Because the
%n
format is inherently insecure, it is disabled by default. If%n
is encountered in a format string, the invalid parameter handler is invoked, as described in Parameter Validation. To enable%n
support, see_set_printf_count_output
.
Whether %n
is actually unsafe as claimed by Microsoft is highly debatable. The examples shown to support this claim combine this printf
function with the use of a variable format string that can by changed by the attacker via a buffer overflow error.
On some Microsoft systems (but maybe not the latest), you could fix your program this way:
#include <stdio.h>
int main(void) {
int n;
_set_printf_count_output(1);
fprintf(stdout, "Hello%n World\n", &n);
fprintf(stdout, "n: %d\n", n);
return 0;
}
For a more portable approach, here is a work around to avoid using %n
and still get the same results:
#include <stdio.h>
int main(void) {
int n;
n = fprintf(stdout, "Hello");
fprintf(stdout, " World\n");
fprintf(stdout, "n: %d\n", n);
return 0;
}
Output:
Hello World
n: 5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With