|
|
Subscribe / Log in / New account

usual arithmetic promotions

usual arithmetic promotions

Posted Jan 10, 2005 12:59 UTC (Mon) by jejones3141 (guest, #27116)
In reply to: Tone and correctness by BruceRamsay
Parent article: grsecurity 2.1.0 and kernel vulnerabilities

>After a quick look at the bugs listed I have a few questions about some of
>the analysis. For example:

>>> if(len > sizeof(moxaBuff))
>> ^ signed int has only upper-bound checked
>>> return -EINVAL;

>On all systems I know of, sizeof() produces an unsigned number. In C,
>comparisons between unsigned numbers and signed numbers are done as
>unsigned comparisons. In fact, -1 > sizeof(moxaBuff) is true. Therefore
>the comment "signed int has only upper-bound checked" is incorrect. After
>the test we are guaranteed that 0 <= len <= sizeof(moxaBuff). (I am
>speaking about real world C implementations and not theoretically possible
>C compilers.)

Some pre-ANSI/ISO C compilers did "unsigned preserving" promotions,
and for them your analysis is correct. ANSI/ISO, however, has "value
preserving" promotions, i.e. the compiler tries to find a type that
will represent all possible values of the types of both operands of >
to widen the operands to. Pre-C9X, since 64-bit arithmetic isn't
mandated, given that size_t (the type that sizeof() yields) is an
unsigned 32-bit type, the compiler will fail to find such a type.
I _think_ it ends up using an unsigned 32-bit integer. If C9X, which
requires 64-bit integer types, follows through with value preserving
rules (and size_t is still 32-bit), it may well do the comparison
in 64-bit signed integers, in which case -1 will not be greater than
sizeof(moxaBuff).


to post comments

usual arithmetic promotions

Posted Jan 10, 2005 14:38 UTC (Mon) by khim (subscriber, #9252) [Link]

Have you actually tried gcc ?

The only compiler used by kernel developers will use "unsigned int" for calculation - thus all standards are irrelevant.

Yes, it's still nice thing to fix (who know what'll happen in future version of gcc?) but it's not "security bug" anymore. That's the point.

usual arithmetic promotions

Posted Jan 10, 2005 15:37 UTC (Mon) by velco (guest, #27121) [Link]

> ANSI/ISO, however, has "value preserving" promotions, i.e. the compiler
> tries to find a type that will represent all possible values of the types
> of both operands of to widen the operands to.

Incorrect. If operand types (after integer promotions) differ, one of
the operands can be at most widened to the unsigned version of the type of
the other operand. IOW, the original operand types set an upper limit on
the width of the promoted operands. The relevant section of Teh Standard
follows:

| If both operands have the same type, then no
| further conversion is needed.
|
| Otherwise, if both operands have signed integer
| types or both have unsigned integer types, the
| operand with the type of lesser integer conversion
| rank is converted to the type of the operand with
| greater rank.
|
| Otherwise, if the operand that has unsigned
| integer type has rank greater or equal to the rank
| of the type of the other operand, then the operand
| with signed integer type is converted to the type
| of the operand with unsigned integer type.
|
| Otherwise, if the type of the operand with signed
| integer type can represent all of the values of
| the type of the operand with unsigned integer
| type, then the operand with unsigned integer type
| is converted to the type of the operand with
| signed integer type.
|
| Otherwise, both operands are converted to the
| unsigned integer type corresponding to the type of
| the operand with signed integer type.

In the concrete case of comparing int and size_t, for all the cases of
practical interest (i.e., size_t having conversion rank greater than or
equal to the conversion rank of int), the int operand will be converted to
size_t and negative value will result in an error return.

~velco


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds