What is the use of the %n format specifier in C?

CPrintfFormat String

C Problem Overview


What is the use of the %n format specifier in C? Could anyone explain with an example?

C Solutions


Solution 1 - C

Most of these answers explain what %n does (which is to print nothing and to write the number of characters printed thus far to an int variable), but so far no one has really given an example of what use it has. Here is one:

int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");

will print:

hello: Foo
       Bar

with Foo and Bar aligned. (It's trivial to do that without using %n for this particular example, and in general one always could break up that first printf call:

int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");

Whether the slightly added convenience is worth using something esoteric like %n (and possibly introducing errors) is open to debate.)

Solution 2 - C

Nothing printed. The argument must be a pointer to a signed int, where the number of characters written so far is stored.

#include <stdio.h>

int main()
{
  int val;

  printf("blah %n blah\n", &val);

  printf("val = %d\n", val);

  return 0;

}

The previous code prints:

blah  blah
val = 5

Solution 3 - C

I haven't really seen many practical real world uses of the %n specifier, but I remember that it was used in oldschool printf vulnerabilities with a format string attack quite a while back.

Something that went like this

void authorizeUser( char * username, char * password){
    
    ...code here setting authorized to false...
    printf(username);
    
    if ( authorized ) {
         giveControl(username);
    }
}

where a malicious user could take advantage of the username parameter getting passed into printf as the format string and use a combination of %d, %c or w/e to go through the call stack and then modify the variable authorized to a true value.

Yeah it's an esoteric use, but always useful to know when writing a daemon to avoid security holes? :D

Solution 4 - C

From here we see that it stores the number of characters printed so far.

> n The argument shall be a pointer to an integer into which is written the number of bytes written to the output so far by this call to one of the fprintf() functions. No argument is converted.

An example usage would be:

int n_chars = 0;
printf("Hello, World%n", &n_chars);

n_chars would then have a value of 12.

Solution 5 - C

So far all the answers are about that %n does, but not why anyone would want it in the first place. I find it's somewhat useful with sprintf/snprintf, when you might need to later break up or modify the resulting string, since the value stored is an array index into the resulting string. This application is a lot more useful, however, with sscanf, especially since functions in the scanf family don't return the number of chars processed but the number of fields.

Another really hackish use is getting a pseudo-log10 for free at the same time while printing a number as part of another operation.

Solution 6 - C

The argument associated with the %n will be treated as an int* and is filled with the number of total characters printed at that point in the printf.

Solution 7 - C

The other day I found myself in a situation where %n would nicely solve my problem. Unlike my earlier answer, in this case, I cannot devise a good alternative.

I have a GUI control that displays some specified text. This control can display part of that text in bold (or in italics, or underlined, etc.), and I can specify which part by specifying starting and ending character indices.

In my case, I am generating the text to the control with snprintf, and I'd like one of the substitutions to be made bold. Finding the starting and ending indices to this substitution is non-trivial because:

  • The string contains multiple substitutions, and one of the substitutions is arbitrary, user-specified text. This means that doing a textual search for the substitution I care about is potentially ambiguous.

  • The format string might be localized, and it might use the $ POSIX extension for positional format specifiers. Therefore searching the original format string for the format specifiers themselves is non-trivial.

  • The localization aspect also means that I cannot easily break up the format string into multiple calls to snprintf.

Therefore the most straightforward way to find the indices around a particular substitution would be to do:

char buf[256];
int start;
int end;

snprintf(buf, sizeof buf,
         "blah blah %s %f yada yada %n%s%n yakety yak",
         someUserSpecifiedString,
         someFloat,
         &start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);

Solution 8 - C

It doesn't print anything. It is used to figure out how many characters got printed before %n appeared in the format string, and output that to the provided int:

#include <stdio.h>

int main(int argc, char* argv[])
{
    int resultOfNSpecifier = 0;
    _set_printf_count_output(1); /* Required in visual studio */
    printf("Some format string%n\n", &resultOfNSpecifier);
    printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
    return 0;
}

(Documentation for _set_printf_count_output)

Solution 9 - C

It will store value of number of characters printed so far in that printf() function.

Example:

int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);

The output of this program will be

Hello World
Characters printed so far = 12

Solution 10 - C

Those who want to use %n Format Specifier may want to look at this:

Do Not Use the "%n" Format String Specifier

> In C, use of the "%n" format specification in printf() and sprintf() > type functions can change memory values. Inappropriate > design/implementation of these formats can lead to a vulnerability > generated by changes in memory content. Many format vulnerabilities, > particularly those with specifiers other than "%n", lead to > traditional failures such as segmentation fault. The "%n" specifier > has generated more damaging vulnerabilities. The "%n" vulnerabilities > may have secondary impacts, since they can also be a significant > consumer of computing and networking resources because large > guantities of data may have to be transferred to generate the desired > pointer value for the exploit. Avoid using the "%n" format > specifier. Use other means to accomplish your purpose.

Source: link

Solution 11 - C

%n is C99, works not with VC++.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjoshView Question on Stackoverflow
Solution 1 - CjamesdlinView Answer on Stackoverflow
Solution 2 - CStarkeyView Answer on Stackoverflow
Solution 3 - CXzhshView Answer on Stackoverflow
Solution 4 - CKLee1View Answer on Stackoverflow
Solution 5 - CR.. GitHub STOP HELPING ICEView Answer on Stackoverflow
Solution 6 - CEvanView Answer on Stackoverflow
Solution 7 - CjamesdlinView Answer on Stackoverflow
Solution 8 - CMerlyn Morgan-GrahamView Answer on Stackoverflow
Solution 9 - CSudhanshu MishraView Answer on Stackoverflow
Solution 10 - Cthe kamilzView Answer on Stackoverflow
Solution 11 - Cuser411313View Answer on Stackoverflow