scanf函数中的整数溢出 [英] integer overflow in scanf functions

查看:195
本文介绍了scanf函数中的整数溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨。


我想知道为什么scanf函数在读取数字时没有检查溢出

。例如,scanf(32位机器上的%d认为

1和4294967297是相同的。


我追踪到转换本身发生的代码。

scanfs中的代码只是忽略了转换程序的返回值。


如果glibc在这里发布了更多信息:
http://board.flatassembler.net/topic.php? t = 6359


AFAIK,实现并没有定义溢出时的行为,所以

glibc可以考虑这个错误并返回errno = ERANGE

hi.

i wanted to know why doesn''t the scanf functions check for overflow
when reading number. For example scanf("%d" on 32bit machine considers
"1" and "4294967297" to be the same.

I tracked to code to where the conversion itself happens. Code in
scanfs just ignores return value from conversion procedures.

More info in case of glibc posted here:
http://board.flatassembler.net/topic.php?t=6359

AFAIK, implementation doesn''t define behavior in case of overflow, so
glibc could consider this error and return errno=ERANGE

推荐答案

文章< 11 ****************** ****@79g2000cws.googlegroups.com> ;,
vi****@gmail.com < vi ****@gmail.com写道:
In article <11**********************@79g2000cws.googlegroups. com>,
vi****@gmail.com <vi****@gmail.comwrote:

>我想知道为什么scanf函数没有检查overfl在阅读号码时。例如,scanf(32位机器上的%d认为
1和4294967297是相同的。
>i wanted to know why doesn''t the scanf functions check for overflow
when reading number. For example scanf("%d" on 32bit machine considers
"1" and "4294967297" to be the same.



因为'它是如何规范的。


"输入项被定义为

字符的最长匹配序列,除非它超过指定的字段宽度,在

这种情况​​下它是该长度​​的初始子序列

序列。[...]


除了%说明符之外,输入项(或者,在%n指令的

情况下,输入字符的数量)是

转换为适合转换说明符的类型。[...]

除非用*表示赋值抑制,否则转换的结果

放入第一个

参数指向的对象,格式参数后面没有

已经收到转换结果。如果这个对象没有

有一个适当的类型,或者如果转换的结果不能在所提供的空格中表示,则行为是未定义的。

所以你有它:如果你没有不要输入字段宽度,然后

%d是*必需*来拉入那里的所有小数位数,并且

如果那个'太大了对于一个int,那么结果是正式未定义的。

这就是fscanf(以及因此scanf)需要的方式 - 按照

工作到标准。

-

当时我很年轻,但我也很沮丧。

- 克里斯托弗牧师

Because that''s how it is spec''d.

"An input item is defined as the longest matching sequence of
characters, unless that exceeds a specified field width, in
which case it is the initial subsequence of that length in
the sequence." [...]

"Except in the case of a % specifier, the input item (or, in the
case of a %n directive, the count of input characters) is
converted to a type appropriate for the conversion specifier. [...]
Unless assignment suppression was indicated by a *, the result
of the conversion is placed in the object pointed to by the first
argument following the format argument that has not
already received a conversion result. If this object does not
have an appropriate type, or if the result of the conversion cannot
be represented in the space provided, the behaviour is undefined."
So there you have it: if you didn''t put in a field width, then
the %d is *required* to pull in all the decimal digits there, and
if that''s too big for an int, then the result is officially undefined.
This is how fscanf (and hence scanf) are -required- to work according
to the standard.
--
I was very young in those days, but I was also rather dim.
-- Christopher Priest


2006-12-15< el ********** @ canopus.cc.umanitoba.ca>,

Walter Roberson写道:
2006-12-15 <el**********@canopus.cc.umanitoba.ca>,
Walter Roberson wrote:

文章< 11 ********************** @ 79g2000cws.googlegroups。 com>,
vi****@gmail.com < vi **** @ gmail.comwrote:
In article <11**********************@79g2000cws.googlegroups. com>,
vi****@gmail.com <vi****@gmail.comwrote:

>>我想知道为什么scanf函数在读取数字时没有检查溢出
。例如,scanf(32位机器上的%d认为
1和4294967297是相同的。
>>i wanted to know why doesn''t the scanf functions check for overflow
when reading number. For example scanf("%d" on 32bit machine considers
"1" and "4294967297" to be the same.



因为'这是怎么说的。


输入项被定义为

个字符的最长匹配序列,


Because that''s how it is spec''d.

"An input item is defined as the longest matching sequence of
characters,



以什么方式是429496729匹配的字符序列,如果

没有这样的整数值?

And in what way is "429496729" a matching sequence of characters, if
there is no such integer value?


除非超过指定的字段宽度,否则在

中,这是该序列中该长度的初始子序列。

序列。[ ...]


"除了%说明符的情况外,输入项(或者,在%n指令的

情况下,输入字符的数量)

转换为适合转换说明符的类型。[...]

除非用*表示赋值抑制,否则结果<转换的
是放置在第一个

参数指向的对象之后,格式参数没有

已经收到转换结果。如果此对象没有合适的类型,或者如果转换的结果不能在提供的空格中表示,则行为是未定义的。
unless that exceeds a specified field width, in
which case it is the initial subsequence of that length in
the sequence." [...]

"Except in the case of a % specifier, the input item (or, in the
case of a %n directive, the count of input characters) is
converted to a type appropriate for the conversion specifier. [...]
Unless assignment suppression was indicated by a *, the result
of the conversion is placed in the object pointed to by the first
argument following the format argument that has not
already received a conversion result. If this object does not
have an appropriate type, or if the result of the conversion cannot
be represented in the space provided, the behaviour is undefined."



这是未定义的。这意味着没有要求。

实现可以免费将其视为1,或429496729,其中7仍然在流上,或者因为7 _not_仍然在流上,或者作为

4294967295(饱和度)等等


无论如何,我发现我的scanf可能出现的情况

不符合:


数字字符串被截断为512个字符;例如,%f

和%d隐含地为%512f和%512d。


因此,如果我发送%f


1.000000000000000000000000000000000000000000000000 0000000000000
$ b $ 00 00000000000000000000000000000000000000000000000000 0000000000000
$ b $ 00 00000000000000000000000000000000000000000000000000 0000000000000

00000000000000000000000000000000000000000000000000 0000000000000

00000000000000000000000000000000000000000000000000 0000000000000

00000000000000000000000000000000000000000000000000 0000000000000
$ b $ 00 00000000000000000000000000000000000000000000000000 0000000000000
$ b $ 00 00000000000000000000000000000000000000000000000000 0000000000000

e1


它转换为标准是否允许这样做?

It''s undefined. Which means there _are_ no requirements. An
implementation is free to treat it as 1, or as 429496729 with 7 still on
the stream, or as such with 7 _not_ still on the stream, or as
4294967295 (saturation), etc, etc

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.000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
00000000000000000000000000000000000000000000000000 0000000000000
e1

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


Walter Robersonaécrit:
Walter Roberson a écrit :

在文章中< 11 ********************** @ 79g2000cws.googlegroups。 com>,
vi****@gmail.com < vi **** @ gmail.comwrote:

In article <11**********************@79g2000cws.googlegroups. com>,
vi****@gmail.com <vi****@gmail.comwrote:


>>我想知道为什么scanf函数在读取数字时不检查溢出
。例如,scanf(32位机器上的%d认为
1和4294967297是相同的。
>>i wanted to know why doesn''t the scanf functions check for overflow
when reading number. For example scanf("%d" on 32bit machine considers
"1" and "4294967297" to be the same.




因为这就是它的规格。


"输入项被定义为

字符的最长匹配序列,除非在超过指定字段宽度的情况下,在

中,这是该序列中该长度的初始子序列。

序列。[...]


"除了%说明符之外,输入项(或者,在%n指令的

情况下,输入字符的数量)是

转换为适合转换说明符的类型。[...]

除非用*表示赋值抑制,否则结果

转换被放置在第一个

参数指向的对象之后,格式参数没有

已经收到转换结果。如果此对象没有

ha如果转换的结果不能在所提供的空格中表示,则行为未定义。


那么你拥有它:如果你没有放入字段宽度,那么

%d是*必需*来拉入那里的所有小数位数,并且

if这对于int来说太大了,那么结果是官方未定义的。

这就是fscanf(以及因此scanf)需要的工作方式 - 按照
来工作标准。



Because that''s how it is spec''d.

"An input item is defined as the longest matching sequence of
characters, unless that exceeds a specified field width, in
which case it is the initial subsequence of that length in
the sequence." [...]

"Except in the case of a % specifier, the input item (or, in the
case of a %n directive, the count of input characters) is
converted to a type appropriate for the conversion specifier. [...]
Unless assignment suppression was indicated by a *, the result
of the conversion is placed in the object pointed to by the first
argument following the format argument that has not
already received a conversion result. If this object does not
have an appropriate type, or if the result of the conversion cannot
be represented in the space provided, the behaviour is undefined."
So there you have it: if you didn''t put in a field width, then
the %d is *required* to pull in all the decimal digits there, and
if that''s too big for an int, then the result is officially undefined.
This is how fscanf (and hence scanf) are -required- to work according
to the standard.



一般来说,像scanf这样的函数是无法使用的。它们是有问题的,它们在它们工作时是一个奇迹。


使用strtol,或类似的函数将给出合理的
错误返回...

In general functions like scanf are unusable. They are so
problematic, that it is a wonder when they work at all.

Use strtol, or a similar function that will give reasonable
error returns...


这篇关于scanf函数中的整数溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆