Bug 21360 - snprintf %n does not conform to ISO C when characters are not printed
Summary: snprintf %n does not conform to ISO C when characters are not printed
Alias: None
Product: glibc
Classification: Unclassified
Component: stdio (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2017-04-07 14:17 UTC by Vincent Lefèvre
Modified: 2017-04-12 11:05 UTC (History)
1 user (show)

See Also:
Last reconfirmed:
fweimer: security-


Note You need to log in before you can comment on or make changes to this bug.
Description Vincent Lefèvre 2017-04-07 14:17:52 UTC
Consider the following example:

#include <stdio.h>

int main(void)
  int r, n = -1;

  r = snprintf (NULL, 0, "foo%n", &n);
  printf ("%d %d\n", r, n);
  return 0;

With glibc 2.24, I get 3 3 instead of the expected 3 0. Indeed, the glibc manual (whose description seems equivalent to ISO C11) says for %n:

12.12.6 Other Output Conversions
   The '%n' conversion is unlike any of the other output conversions.
It uses an argument which must be a pointer to an 'int', but instead of
printing anything it stores the number of characters printed so far by
this call at that location.

but due to the size 0, nothing has been printed. Thus one should have n = 0.

Note that in its snprintf description:

     The return value is the number of characters which would be
     generated for the given input, excluding the trailing null.

"would be", thus the expected r = 3. There is no such "would be" for %n. In the C11 draft I have, this is said in a similar way:

     The snprintf function returns the number of characters that would
     have been written had n been sufficiently large, [...]

The "had n been sufficiently large" is quite explicit. But again, there is no such thing for %n.
Comment 1 Andreas Schwab 2017-04-07 17:22:18 UTC
The description only talks about the produced characters being discarded instead of written to memory.  The side effects of producing the output is still performed.  In case of lack of space the output stream is just the equivalent of /dev/null.
Comment 2 Florian Weimer 2017-04-12 11:05:12 UTC
Agreed, this looks like an imprecision or a defect in the C standard.