integer overflow in scanf functions

C

Chris Torek

2006-12-18 said:
As far as I can tell, the ["environmental limits"] rules apply.

That rule does not allow a limit for any scanf function - it allows
limits for other things which allows an implementation to be written for
which no such case is possible for scanf or fscanf - that is not the
same thing.

Possibly not. I think it still applies, though.
The section you quoted has absolutely nothing to do with any *scanf
function, and even less to do with sscanf.

If you do not like my answer, you probably want comp.std.c, not
comp.lang.c. :)
 
R

Random832

2006-12-19 said:
2006-12-18 said:
As far as I can tell, the ["environmental limits"] rules apply.

That rule does not allow a limit for any scanf function - it allows
limits for other things which allows an implementation to be written for
which no such case is possible for scanf or fscanf - that is not the
same thing.

Possibly not. I think it still applies, though.

What environmental limit does my test program posted earlier violate?
[if there's an auto array size limit that i'm not considering, move the
array to file scope]
 
C

Chris Torek

2006-12-19 said:
Chris said:
Possibly not. I think [the "environmental limit"] still applies [to
sscanf], though.

What environmental limit does my test program posted earlier violate?

Although the limit is for "lines" in text files, and a string is
not a line in a text file, I believe it is intended to generalize
to "text mode stdio streams". If (as I believe) sscanf treats a
string as if it were a text-mode stdio stream, the limit then
intrudes itself rudely upon strings fed to sscanf().

(Since this is really a question about interpreting the number of
angels that must be collectible on various pin-heads in the Standard,
comp.std.c is a better group.)
 
R

Random832

2006-12-19 said:
2006-12-19 said:
Possibly not. I think [the "environmental limit"] still applies [to
sscanf], though.

What environmental limit does my test program posted earlier violate?

Although the limit is for "lines" in text files, and a string is
not a line in a text file, I believe it is intended to generalize
to "text mode stdio streams". If (as I believe) sscanf treats a
string as if it were a text-mode stdio stream, the limit then
intrudes itself rudely upon strings fed to sscanf().

(Since this is really a question about interpreting the number of
angels that must be collectible on various pin-heads in the Standard,
comp.std.c is a better group.)

Agreed. For those of you just joining us, my implementation is documented thus:

Numerical strings are truncated to 512 characters; for example, %f
and %d are implicitly %512f and %512d.

Is this permitted by the standard?

That is, is an implementation allowed to, on a %f format, interpret
1.0<etc>0e1 as 1.0 rather than 10.0, and to leave some of the <etc>0e1
for the next format specifier? Some people think the limitation on
text file line lengths covers this case, I think it does not, as, first
of all, the implementation otherwise supports text file lines of
arbitrary length, and, second, the argument to sscanf is not a line of
a text file.
 
C

Chris Torek

Note that here, "such an input" is, e.g., "1.23e-xyz":

int n;
double d;
char buf[100];

n = sscanf("1.23e-xyz", "%lf%99s", &d, buf);

I disagree that such an input must fail.

If you mean "it is possible to handle this in a computer program,
without having it `fail', so that d is set to 1.23 and buf is set
to e-xyz", then yes.

If you mean "the Standard does not require that this fail", then
no: a DR or TR at some point in the past (back in the 1990s) said
otherwise.

This irked me, because my stdio handled it just fine, setting n
to 2, d to 1.23, and copying the string "e-xyz" into buf[]. But
that is what they said: it must fail. Here, n must be set to 0,
and d and buf[] must be unaltered.
In practice this all means that the scanf series of functions
should not be used to input numerics without limiting the call to a
single field.

Because of the silly required failure, it should not even be used
for that. Better to get the string into a buffer, and then sscanf()
or (better) strtod(), strtol(), etc.

Note that the Standard requires that, given:

char *ep;
d = strtod("1.23e-xyz", &ep);

d must be set to 1.23, and ep must point to the 'e' in "e-xyz".
That is, the requirements for strtod() and the scanf() family are
different.

It might be nice if the Standard would (or, possibly, does) also
require that both the scanf engine and the strtod() routine handle
"arbitrarily long" inputs wherever they can occur, i.e., in sscanf(),
and in fscanf() and plain scanf() if there are no actual line-length
limits "underneath" the C library, as it were. A scanf engine
*could* handle this internally: if LDBL_MAX_EXP is, say, 10000, at
most a few more than 10000 decimal digits are required to hold a
number (and in fact even fewer are really necessary, if the
implementor wants to fiddle with mantissa and exponent in stringy
ways before calling strtod() internall).
 
A

av

2006-12-16 said:
Anyway, I found a possible situation in which my scanf is
non-conformant:

Numerical strings are truncated to 512 characters; for example, %f
and %d are implicitly %512f and %512d.

So, if I send %f

1.0000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
e1

it converts to 1 instead of 10. Does the standard allow this?

Yes:

Environmental limits

[#7] An implementation shall support text files with lines
containing at least 254 characters, including the
terminating new-line character. The value of the macro
BUFSIZ shall be at least 256.

And what about sscanf?

int main() {
char *x[515];

is it not better here char x[515];?
double n;
memset(x+2,'0',510);

here x[2..511]='0';
x[0] = '1'; x[1] = '.'; x[512] = 'e'; x[513] = '1'; x[514] = 0;
sscanf(x,"%lf",&n); printf("%f",x);
}

prints 1 or 10?

for me has to print 10
or sscanf has to return fail
Marry Christmas
 
R

Random832

2006-12-22 said:
2006-12-16 said:
Anyway, I found a possible situation in which my scanf is
non-conformant:

Numerical strings are truncated to 512 characters; for example, %f
and %d are implicitly %512f and %512d.

So, if I send %f

1.0000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
e1

it converts to 1 instead of 10. Does the standard allow this?

Yes:

Environmental limits

[#7] An implementation shall support text files with lines
containing at least 254 characters, including the
terminating new-line character. The value of the macro
BUFSIZ shall be at least 256.

And what about sscanf?

int main() {
char *x[515];

is it not better here char x[515];?

Yes, sorry, that was a typo
double n;
memset(x+2,'0',510);

here x[2..511]='0';
x[0] = '1'; x[1] = '.'; x[512] = 'e'; x[513] = '1'; x[514] = 0;
sscanf(x,"%lf",&n); printf("%f",x);
}

prints 1 or 10?

for me has to print 10
or sscanf has to return fail

Right, I didn't check the return of sscanf, but my feeling was that
"succeeding" and translating the first 512 bytes to a 1 and leaving the
e1 alone is not the right way to do it.

Incidentally, despite the documentation, my implementation actually does
result in 10. So it's a quality of implementation issue on the docs. I'm
still curious as to whether the behavior described is permitted
 

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

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top