%n !!

K

karthikbalaguru

Hi,

In the below code, i get a strange output.

int main(void)
{
int a=2;
printf( "ABC %d Ok\n", a );
printf( "ABC %d Ok\n", &a );
printf( "ABC %n Ok\n", &a );
printf( "a = %d\n", a );
return 0;
}

I get the below output -
ABC 2 Ok
ABC 2162224 Ok
ABC

Before exeuction of the final printf, it showed
a warning. Then, it printed only ABC.
I did not get that 'Ok'. Why ?
Further it also did not print 'a = 3' ?

I am eager to know the logic behind %n ?
Does it count and store the characters until it
faces a space or % ?

Thx in advans,
Karthik Balaguru
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,

In the below code, i get a strange output.

int main(void)
{
int a=2;
printf( "ABC %d Ok\n", a );
printf( "ABC %d Ok\n", &a );
printf( "ABC %n Ok\n", &a );
printf( "a = %d\n", a );
return 0;
}

I get the below output -
ABC 2 Ok
ABC 2162224 Ok
ABC

Before exeuction of the final printf, it showed
a warning. Then, it printed only ABC.
I did not get that 'Ok'. Why ?
Further it also did not print 'a = 3' ?

I am eager to know the logic behind %n ?
Does it count and store the characters until it
faces a space or % ?

Thx in advans,
Karthik Balaguru

Most probably your libc is buggy. Mine does the following (correct) thing:

falcon@squall ~ $ ./a.out
ABC 2 Ok
ABC -1075926016 Ok
ABC Ok
a = 4
falcon@squall ~ $

%n just stores the exact number of characters printed by the call to
printf() it appears in, at the point where it finds the %n. So it has
counted "ABC ", which is four characters.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJqc23AAoJEKmxP9YxEE4rA3IQAJ0UMh4g5mdKs3Dk3ZnGW2XB
FkXui2iJFTLZwvUn3YQnfz2BXKA8VIlEIHSaPpoGCKLiSVlq8sf475pNqX4K8fi7
d0U12097jv+tw5sK+imM1nms5GHXc/fXmXr+GQ3/RFW0Sp9ZPC2b+F18s2SJFkUU
4HFEHraeQ6fWpxXR0MjFuu6q9SOikqZ9uorrOlw/lnOBGhMzRlKA4lAwtZUZ1nSA
MYvffzDsvX3nCq3VgBTB85PgwLNo+azv+9U/hYTDNXk40OY+5MmmXG9WfV3rwdtu
FLD0G88jprhT+rQCa8CXrd7Ms/qEHzhCFm1yLpCXq986BbAMQn/kpIqpEGvMY2RE
QSBpfj1QWAd/QlPl1/dX6P5KxcK1jKpwm/8WuU8oA3iRk1prLZyOIf0YmrVk6G6y
fYDbDKZSrH4fPgZuwkIhyMNKPbr7IsjFdOXAG/m7038Hfz6AjP3WqCO645w8v7+B
JYZmMdTfjXwhEjmitpe2XkCpW+0gpbqc4oMzoRsvi4/hN7DCL33e2iz4Gj1cvyGx
4MLDPUOPjI5ee0uNiX7s+A59oirlXWcSmTXmkIDgaZaccsT/zARNHAbkkFWpF66s
y9usyPl59wbGbfK7zKalfdn6Q1yjDveVwczLS2qDMdOLfpyPECfg4p/q4g8Et70G
Ft0NyGDAIu/2NOq3QMvH
=PxfX
-----END PGP SIGNATURE-----
 
K

karthikbalaguru

karthikbalaguru said:




If you're going to call a variadic function such as printf, you
absolutely must have a valid prototype in scope for it. Otherwise,
the behaviour is undefined. The fix is to #include <stdio.h>



If you're going to print a pointer value, you absolutely must make
sure that you use the %p format specifier. Otherwise, the behaviour
is undefined. Furthermore, you should get the type right. The fix
is:

  printf( "ABC %p Ok\n", (void *)&a );

Yes. Done.
This is fine.



If you get the same result after fixing the problems I mentioned,
raise the matter with your compiler vendor.

Yes, i get the same result even after those %p related changes.
I use Visual C++ 2008 Express edition.
Does it work fine in gcc ?
Any ideas ?

Thx in advans,
Karthik Balaguru
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Yes. Done.


Yes, i get the same result even after those %p related changes.
I use Visual C++ 2008 Express edition.
Does it work fine in gcc ?
Any ideas ?

Thx in advans,
Karthik Balaguru

For what it's worth, the thing I posted below was done after compiling
the code in gcc with the header file included.

It would not surprise me if VC++ 2008 (not technically a C compiler at
all) implemented printf() and in particular %n in a buggy way.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJqdDkAAoJEKmxP9YxEE4rBEUQAI76ctB+a+Aedvib9WD1ccQH
vpm828Dwk66ejwIZ42nTIDFD1VTP/uP4x0CzJsvtQ5afY6N4TEa7c1TnTQ5ph+3O
bxw2iDTmkPf1AVbNMktBxxp2jm3YH9N7g+ofeebC/XRv02NVFI+rkMq3JdHlJu/0
pgAaiZylsI+dToAnoXM51+k/tezBpQkVFe2i0JDRLlPpTMcs6NawVcXO6c9Zli1a
P0YIqt+QFJV+TQO/Q4wmjc9UhGC52RKWI3oiBiuvwXiOAauUnqX1xG4GSUjwoOdg
Hr0ejjrrzLYbnGf3A9KQCufqkn6k43mDfjnUFUMaFkgJicUW1+nmN7Ef4SLi4gvR
m2dvmLqIvl+IpZtMaOak+cnU8CUIiNxdfpyICgHkuF1J09Fxnd2XjbLpA4uYISBM
NrDNL90aZ6t+mBb+OrwyjqQFsTsNHBhmrMUKZlM4sCcT639VntIgTAZkPnVnq8Du
f/AjjoNEr5w0qpC+cBdz8him9QUwG4Axs7QokAwYEX3xrAWd/suuYFSErkeGO4cF
4CsCuosb1qfjG015LpdNF0GPg4MCoNdOn3t+jisoWVSD4zpWT5ZD5dH73M8LXZ3L
57qGMVRkHSBXUBkS6molJXIeL1BhNbxpNA1eRict3+iDSZfINYR8pNQ3jM5A0zWP
tbAaMz1LFQyCBMOGiCbY
=Ahy8
-----END PGP SIGNATURE-----
 
K

karthikbalaguru

Yes. Done.








Yes, i get the same result even after those %p related changes.
I use Visual C++ 2008 Express edition.
Does it work fine in gcc ?
Any ideas ?

I find that the %n option is disabled by default in this edition.
_set_printf_count_output - For enabling / disabling of %n.
I came across the below links that helped very much -
http://weblogs.asp.net/george_v_reilly/archive/2007/02/06/printf-n.aspx
http://msdn.microsoft.com/en-us/library/ms175782(VS.80).aspx

I think, in gcc, it is enabled by default . Any ideas ?

Thx,
Karthik Balaguru
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I find that the %n option is disabled by default in this edition.
_set_printf_count_output - For enabling / disabling of %n.
I came across the below links that helped very much -
http://weblogs.asp.net/george_v_reilly/archive/2007/02/06/printf-n.aspx
http://msdn.microsoft.com/en-us/library/ms175782(VS.80).aspx

I think, in gcc, it is enabled by default . Any ideas ?

Thx,
Karthik Balaguru

You might want to ask in a different group that has more people who know
about configuring MSVS. However, let it be known (with utmost pedantry)
that enabling (or not) of %n is not a function of gcc, being as it is a
compiler. %n is defined by the libc.

Do you still have a problem?

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJqej8AAoJEKmxP9YxEE4rOIIP/1RfTgC8MERu095WhLLimtqp
cVAPWY9VU0fmdqWa2w9oE8OAyOsUkJfVG4GFble8DpIbBPlUuvwCc+dk9/ZoKHFV
Kp3cG/T8VY/P2r2yKY/su9MfrhPnqtTwWhjS3G+HmLbX9JhCymCjBeZK4V3zGjDI
GLvXRPxD30X2NlO8lafBFyUzPLlRqz/xSM1hzBETyCqXaefEgm4IylHjxBgwSLSJ
yQwjg5UkUrofMa+9OLPEMGe0KdVedixjLMhloAOmVRK/2OR/w3nLMLJ7ewuB4vYV
m02TsDYIqfoKKrBvJdkuDFJrhoNUsabvPJei1fd7GYET9Az72TcCzYJv+fZ5Ezfr
n+nPWW2f96U/vmKsMn3/LlIq9azHks+ApQTwuqqlguXfNkPQ9bPQpnNWU7ECXIRb
r51y7rtYt/HbX90x1+uTSBFzyoBlo70B6PDzFwmRbixiS3/jW5aerHZ6BZYUYtze
GoDTkasNEICV+BBioAdKx528pehF/N4MhFpQIIjhW5hce5MklUsNqR1D1XnXwplz
6usLtAly9xECeEOjcG6EbMEKPIzF2L4ypkGbvKMPcADvZUMRCBhuTrXS7JlDklyc
KZQVuCK3st8Gv5IuoStvYb4f2W7+gE9VlWJUoCxrfvBoQli2mnZ+YQM+Lhj+svTI
J0FmNSWDuSvSlqDKEjdN
=jsS6
-----END PGP SIGNATURE-----
 
K

karthikbalaguru

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1









You might want to ask in a different group that has more people who know
about configuring MSVS.  However, let it be known (with utmost pedantry)
that enabling (or not) of %n is not a function of gcc, being as it is a
compiler.  %n is defined by the libc.

Do you still have a problem?
No. It is working.
And i am clear of %n functionality.
Thx.

Karthik Balaguru
 
N

Nate Eldredge

Falcon Kirtaran said:
Most probably your libc is buggy.

After reading the links posted by the OP, I'll say in Microsoft's
defense that this is not a bug but a feature :) A somewhat common source
of security problems in C programs are so-called "format string
vulnerabilities"; if a user-supplied string is passed to a function like
printf(), the user might include %n specifiers, which would have the
effect of writing to some area of memory. In some cases this can be
exploited to get the program to do something that it is not supposed to,
perhaps letting the user do things that he ought not be allowed to do.

The proper fix, of course, is not to pass user-supplied strings to
printf(), at least not without sanitizing them first. However, since
there is a substantial amount of old (and, sadly, new) code written by
people who didn't realize the danger of such code, and relatively few
legitimate uses of %n, Microsoft made the decision to disable this
feature by default. Enabling requires calling a Microsoft-specific
function. This breaks ISO compliance, of course, and evidently confuses
some programmers, but does make the world a somewhat safer place, at
least in the short term.

The wisdom of this decision is certainly subject to debate, but it *was*
a decision, not an accident, and has at least some justification.
 
S

Spiros Bousbouras

After reading the links posted by the OP, I'll say in Microsoft's
defense that this is not a bug but a feature :) A somewhat common source
of security problems in C programs are so-called "format string
vulnerabilities"; if a user-supplied string is passed to a function like
printf(), the user might include %n specifiers, which would have the
effect of writing to some area of memory.

Ok , I'm curious , under what circumstances might it be
useful for a programme to pass a user-supplied string to
printf() ?
...SNIP... Microsoft made the decision to disable this
feature by default. Enabling requires calling a Microsoft-specific
function. This breaks ISO compliance, of course, and evidently confuses
some programmers, but does make the world a somewhat safer place, at
least in the short term.

I doubt that it makes the world a safer place. Even if all the
users were angels and even if %n didn't exist there are
still many things that can go wrong with arbitrary printf()
format strings. If a programmer doesn't realise that and
takes measures to deal with it then the lack of default
inclusion of %n isn't going to save them.
 
I

Ike Naar

Ok , I'm curious , under what circumstances might it be
useful for a programme to pass a user-supplied string to
printf() ?

Programmers do it even if it's not useful.

$ cat silly.c
#include <stdio.h>
int main(void)
{
char data[32];
fgets(data, sizeof data, stdin);
printf("You entered: ");
printf(data);
return 0;
}
$ gcc silly.c
$ ./a.out
foo bar
You entered: foo bar
$ ./a.out
foo %n bar
Memory fault (core dumped)
$
 
H

Harald van Dijk

Ok , I'm curious , under what circumstances might it be useful for a
programme to pass a user-supplied string to printf() ?

It's come up recently here:

printf(_("Hello, %s.\n"), name);

where _ is a function that returns a pointer to a translation of its
argument. Such translations can be stored in a separate file, editable by
translators, where translators have exactly as much to do with the code
as the users.
 
R

Richard Tobin

Han from China said:
Many libraries have taken the draconian measure of disabling the
%n conversion specifier by default for security reasons. In a certain kind
of common programming bug, the %n specifier can be used to overwrite
critical data in memory and gain control of the process.

One would have thought that the compiler could arrange for it only
to be disabled when the format string was not a literal.

-- Richard
 
H

Harald van Dijk

One would have thought that the compiler could arrange for it only to be
disabled when the format string was not a literal.

That, in my opinion, was a bad decision of the glibc folks (note: glibc
is not the compiler). It caused pre-compile checks to see whether %n is
supported to report that it is in fact supported, and then aborted the
program at runtime when %n was actually used.
 
B

Ben Bacarisse

Spiros Bousbouras said:
Ok , I'm curious , under what circumstances might it be
useful for a programme to pass a user-supplied string to
printf() ?

You said "useful" rather than "a good idea" so I can answer. I have
seen it more than once as a lazy solution to offering the user very
flexible output options. Rather than offer options to control width,
precision, format and so on, the programmer provides the command-line
option -f that takes a format string. Users can than have everything
from %g to %12.5e with only one option.
 
N

Nate Eldredge

Spiros Bousbouras said:
Ok , I'm curious , under what circumstances might it be
useful for a programme to pass a user-supplied string to
printf() ?

It could be useful if you want to let the user specify the format for
some output. More commonly, it would be done for no particular reason.
Perhaps when a string containing user data needs to be output, and
output is generally being done by a printf-like function, and one
doesn't think to use `fputs' or `fprintf("%s",...)'. *printf is so
often used to output constant strings with no format specifiers that
it's easy to get in the habit of using it that way for non-constant
strings too.

On Unix, this issue commonly arises with the syslog(3) function, where
the only way to log a string uses printf-type format specifiers; there's
no equivalent to `fputs' that one might use instead.
I doubt that it makes the world a safer place. Even if all the
users were angels and even if %n didn't exist there are
still many things that can go wrong with arbitrary printf()
format strings. If a programmer doesn't realise that and
takes measures to deal with it then the lack of default
inclusion of %n isn't going to save them.

"Safer", not "safe". I think without %n, there's a lot less harm an
attacker can do. Did you have something specific in mind?
 
R

Richard Tobin

After reading the links posted by the OP, I'll say in Microsoft's
defense that this is not a bug but a feature :) A somewhat common source
of security problems in C programs are so-called "format string
vulnerabilities"; if a user-supplied string is passed to a function like
printf(), the user might include %n specifiers, which would have the
effect of writing to some area of memory.
[/QUOTE]
Ok , I'm curious , under what circumstances might it be
useful for a programme to pass a user-supplied string to
printf() ?

It was not unheard of in the past to come across programs that used
printf(s) to output an arbitrary string. Of course, this doesn't work
properly for any string containing %, but %n can have a particularly
bad effect.

I haven't seen any examples of this recently.

-- Richard
 
S

Spiros Bousbouras

On Unix, this issue commonly arises with the syslog(3) function, where
the only way to log a string uses printf-type format specifiers; there's
no equivalent to `fputs' that one might use instead.

Who is the user in this case , the programme calling syslog() ?
"Safer", not "safe". I think without %n, there's a lot less harm an
attacker can do. Did you have something specific in mind?

I had in mind unterminated strings causing DOS or crashes,
strings with other specifiers apart from %n and even
printf("%s",user_supplied_string) is not safe. What happens if
the string contains control characters ? It could mess up the
display and more specifically cause information a cracker does
not want to be seen to not appear [1]. I also wonder if there have
been terminals which could be made to explode with the right
sequence of control characters.

Then there's also this:

From http://www.azillionmonkeys.com/windoze/analysis_windoze.html
While its no surprise that Windows has bugs in it, simply
sending too many backspaces to it appears to send the NT
kernel (read: NT, 2K, XP) into a blue screen of death, followed
by a spontaneous reboot.


In view of all the above , making harder to use %n seems a drop
in an ocean. Furthermore a programmer who doesn't realise the
above dangers will activate %n when they need it and happily
forget about it. There goes your increase in safety.



[1] Off-topic this but one thing I want to investigate and
haven't got around to is how the Unix ps utility is going to
display processes whose name contains control characters.
 
S

Spiros Bousbouras

It's come up recently here:

printf(_("Hello, %s.\n"), name);

where _ is a function that returns a pointer to a translation of its
argument.

If it's a translation it's not the same thing at all. A
translation can make it safe.
 
S

Spiros Bousbouras

You said "useful" rather than "a good idea" so I can answer.

I'm afraid we're going to have to enter into a semantics war
now. If it's not "a good idea" then you shouldn't be using it
and if you shouldn't be using it then it's not useful.
I have
seen it more than once as a lazy solution to offering the user very
flexible output options. Rather than offer options to control width,
precision, format and so on, the programmer provides the command-line
option -f that takes a format string. Users can than have everything
from %g to %12.5e with only one option.

What does the documentation of such a programme say , that the
user shouldn't use % more than X times or bad things will
happen ?
 
B

Ben Bacarisse

Spiros Bousbouras said:
I'm afraid we're going to have to enter into a semantics war
now. If it's not "a good idea" then you shouldn't be using it
and if you shouldn't be using it then it's not useful.

No problem, I have no desire to argue words. If you don't consider
that example to be an example of what you were asking for, then so be
it. The example can turn from a bad idea into a tolerable one by a
simple scan of the format and a call to exit if anything odd is seen.
Does that suit your definition of useful?
What does the documentation of such a programme say , that the
user shouldn't use % more than X times or bad things will
happen ?

It said nothing. I.e. the effect of passing %s or %n was usually a
big bang.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top