sprintf behavies different than printf

G

google

Consider the following code:

char str[100];
char str2[100];
strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
printf("printf: ");
printf("1%s2", str);
printf("\nsprintf: ");
sprintf(str2, "1%s2", str); //Interesting stuff happens here
printf(str2);
printf("\n");

The code should format the string "1%s2" by replacing %s with "%alfa%
%beta% d%100%d %gamma% %delta%". First printf is used, and then
sprintf. The output should be:

printf: 1%alfa% %beta% d%100%d %gamma% %delta%2
sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2

However, this is not what happens i either Visual C++ 6.0, Visual C++
2003 and GCC (version 4 I think, compiled and tested in Linux). In all
these compilers printf works as expected, but fails with sprintf where
the result is either a crash or a malformed string. The problem seems
to be that the %-character is used in the argument which, as fair as I
know, shouldn't be any problem.

If I replace %s with "%%alfa%% %%beta%% d%%100%%d %%gamma%% %%delta%%"
the output will instead by (at least in Visual C++ 2003):

printf: 1%%alfa%% %%beta%% d%%100%%d %%gamma%% %%delta%%2
sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2

So when using sprintf %% is replaced by % which should be the is these
characters where written in the format string, but this is a very
different case.

Unless I have misunderstand the specification of sprintf there is a
quite critical bug in sprintf and this in several compilers. Is this
an known problem? Are more compilers affected? Why are the problem in
both Visual C++ and GCC? Isn't this very interesting? :)

PEK
 
E

Eric Sosman

Consider the following code:

char str[100];
char str2[100];
strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
printf("printf: ");
printf("1%s2", str);
printf("\nsprintf: ");
sprintf(str2, "1%s2", str); //Interesting stuff happens here

Not very. What happens on the next line is far more
interesting, if undefined behavior is "interesting" to you.
printf(str2);

This is equivalent to

printf("1%alfa% %beta% d%100%d %gamma% %delta%2");

.... which is faulty on several counts: Undefined conversion
specifiers ("%a", "% ", "%b", "%100%", "%2"), and specifiers
without values for them to convert ("%g", "%d"). printf()
can do whatever it pleases; Garbage In, Garbage Out.
 
B

Ben Pfaff

Consider the following code:

char str[100];
char str2[100];
strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
printf("printf: ");
printf("1%s2", str);
printf("\nsprintf: ");
sprintf(str2, "1%s2", str); //Interesting stuff happens here
printf(str2);

You mean:
printf("%s", str2);
Otherwise the % directives in str2 are interpreted by printf(),
with undefined results.
 
M

Martien Verbruggen

Consider the following code:

char str[100];
char str2[100];
strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
printf("printf: ");
printf("1%s2", str);
printf("\nsprintf: ");
sprintf(str2, "1%s2", str); //Interesting stuff happens here
printf(str2);

This line is the problem. Not the previous one.

What you're trying to do is

printf("%s", str2);

What you're doing is passing str2 as the format specifier to printf,
which means it will try to parse and interpret it as such, with many
problems and undefined results due to invalid format specifications and
missing parameters.
Unless I have misunderstand the specification of sprintf there is a
quite critical bug in sprintf and this in several compilers. Is this
an known problem? Are more compilers affected? Why are the problem in
both Visual C++ and GCC? Isn't this very interesting? :)

It is probably not a good idea to assume that there is a bug in a
compiler or library, especially not if other compilers support its
behaviour, until you are 100% certain that you're right, and those
compilers are wrong. Apart from anything else, it just means that you
waste your time chasing red herrings.

Regards,
Martien
 
M

Martin Ambuhl

Consider the following code:

[replaced with the legal program, with one extra line:]
#include <stdio.h>
#include <string.h>

int main(void)
{
char str[100];
char str2[100];
strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
printf("printf: ");
printf("1%s2", str);
printf("\nsprintf: ");
sprintf(str2, "1%s2", str); /* Interesting stuff happens here */
printf(str2);
printf("\n");
printf("%s\n", str2); /* the extra line */
return 0;
}
The code should format the string "1%s2" by replacing %s with "%alfa%
%beta% d%100%d %gamma% %delta%". First printf is used, and then
sprintf. The output should be:

printf: 1%alfa% %beta% d%100%d %gamma% %delta%2
sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2

No, it should not. The format string in printf(str2) is
"1%alfa% %beta% d%100%d %gamma% %delta%2"
This format string tells printf to expect several additional arguments:
"%a" (in C99) specifies a double to be represented with
hex digits.
(in C90) undefined conversion
"% " undefined (no space is allowed as a flag in "%%")
"%b" undefined conversion
"% d" signed int represented as decimal integer with a leading space
or '-'
"%100" undefined
"%d" signed int represented as decimal integer
"%g" double represented as with "%f" or "%e"
"% " undefined (no space is allowed as a flag in "%%")
"%d" signed int represented as decimal integer
"%2" undefined (no conversion specified, width = 2)

You provide none of these arguments.
See the result of the added line/


Your various guesses are irrelevant. You call printf with a format
string specifying additional atguments which you do not provide.
 
D

Doug Miller

Consider the following code:

[crap snipped]
Unless I have misunderstand the specification of sprintf there is a
quite critical bug in sprintf and this in several compilers.

Upon sober reflection, which of these circumstances seems to you to be the
more likely of the two?
 
G

google

[A lot of stupid things]

Thanks for all replies that made me feel embarrassed, stupid, and more
embarrassed. To all compilers I just can say:

while(1)
{
printf("I'm sorry!\n");
printf("I will never blame you again.\n");
printf("You make beautiful and prefect things, and I make bugs.\n");
printf("I'm sorry again, please forgive me for my evil words.\n");
printf("You are the master, and I'm the stupid slave.\n\n");
}

I really should know better than this. I will never make any more
premature conclusions (at least not this week).

PEK
 
R

Richard Heathfield

(e-mail address removed) said:
[A lot of stupid things]

Thanks for all replies that made me feel embarrassed, stupid, and more
embarrassed.

Yes, it can be a bit face-reddening, can't it? Generally speaking, The
Compiler Is Always Right. This isn't actually true, but it's a very useful
lie with considerable explanatory power. Of course compilers have bugs -
but the number of bugs in mainstream compilers or standard libraries that
are likely to be first reported by a relatively inexperienced programmer
is vanishingly small.

In general, then, if you and the implementation disagree, you may safely
assume that you are wrong.

War story: when Visual Studio 6 was relatively fresh and exciting, a *very*
inexperienced programmer showed me this program, which he'd copied from
K&R2:

#include <stdio.h>

/* count characters in input: first version */
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

He could not get it to produce any output. I smiled, and explained how to
trigger the loop condition with ^Z, and he said that actually he happened
to know about that, and in any case it wouldn't produce any output even
when data was redirected in from a file.

He was convinced that he had somehow mistyped something, and had compared
every single character to the K&R2 original. He'd changed spacing, used
tabs, changed the tab size on his editor - everything. He couldn't see
what he'd done wrong, but he was sure he'd done *something* wrong.

You know where I'm headed with this, I'm sure. The bug was fixed in
Microsoft's next Visual Studio Service Pack.

So yes, inexperienced programmers do sometimes find bugs in
implementations. But it doesn't happen much more often than Patent Office
clerks win Nobel Prizes.

An experienced programmer will assume, in the first instance, that his or
her code is wrong (because, in his or her experience, that is the most
likely explanation). It is only after much head-scratching ("that's
funny"), puzzled discussions with colleagues ("what's wrong with this
code?"), and detailed consultations with experts in the field ("well, /I/
can't see anything wrong with my code, but there must be something wrong
with it - how about it, folks?"), that he or she might eventually conclude
that the compiler or the library implementation is in error.
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top