Date: Thu, 12 Dec 2024 09:57:39 -0300
On Thursday 12 December 2024 01:42:50 Brasilia Standard Time Oliver Hunt
wrote:
> To be sure UB allows the compiler to do all sorts of things. The
> introduction of optimizations based on UB for overflow caused a lot of
> security vulnerabilities, the canonical
>
> If (x + y < x) abort()
>
> removals that started turning previously “correct” code to gain exploitable
> security failures.
Indeed, but the actually correct code, using __builtin_add_overflow(), is not
only just correct, it's also faster in that it asks the CPU whether an overflow
has happened.
The other important thing is what you wrote: the introduction of
optimisations. There's an important trade-off. (And this happened 15 years ago
or so)
> I’m not sure - because UB around these conversions is always obnoxious :D -
> but I _think_ that a compiler could see
>
> signed x = some_unsigned;
> ...
> If (x < 0 || x > size) abort()
>
> And remove the x<0 because I think x<0 would require the unsigned->signed
> conversion to be UB
This was never UB. C++14 ([conv.integral]/4]) said:
"If the destination type is signed, the value is unchanged if it can be
represented in the destination type (and bit-field width); otherwise, the value
is implementation-defined."
while current C23 (6.3.1.3/3) says:
"Otherwise, the new type is signed and the value cannot be represented in it;
either the result is implementation-defined or an implementation-defined signal
is raised."
A particularly hostile implementation could have produced an implementation-
defined conversion that would map the out-of-range unsigned values to zero, in
which case the behaviour you're describing could be the case. Fortunately for
us, this has never happened and never shall for C++.
Current C++ has done away with even the implementation-defined behaviour and
mandates that "the result is the unique value of the destination type that is
congruent to the source integer modulo 2^N, where N is the width of the
destination type." - https://eel.is/c++draft/conv.integral#3
wrote:
> To be sure UB allows the compiler to do all sorts of things. The
> introduction of optimizations based on UB for overflow caused a lot of
> security vulnerabilities, the canonical
>
> If (x + y < x) abort()
>
> removals that started turning previously “correct” code to gain exploitable
> security failures.
Indeed, but the actually correct code, using __builtin_add_overflow(), is not
only just correct, it's also faster in that it asks the CPU whether an overflow
has happened.
The other important thing is what you wrote: the introduction of
optimisations. There's an important trade-off. (And this happened 15 years ago
or so)
> I’m not sure - because UB around these conversions is always obnoxious :D -
> but I _think_ that a compiler could see
>
> signed x = some_unsigned;
> ...
> If (x < 0 || x > size) abort()
>
> And remove the x<0 because I think x<0 would require the unsigned->signed
> conversion to be UB
This was never UB. C++14 ([conv.integral]/4]) said:
"If the destination type is signed, the value is unchanged if it can be
represented in the destination type (and bit-field width); otherwise, the value
is implementation-defined."
while current C23 (6.3.1.3/3) says:
"Otherwise, the new type is signed and the value cannot be represented in it;
either the result is implementation-defined or an implementation-defined signal
is raised."
A particularly hostile implementation could have produced an implementation-
defined conversion that would map the out-of-range unsigned values to zero, in
which case the behaviour you're describing could be the case. Fortunately for
us, this has never happened and never shall for C++.
Current C++ has done away with even the implementation-defined behaviour and
mandates that "the result is the unique value of the destination type that is
congruent to the source integer modulo 2^N, where N is the width of the
destination type." - https://eel.is/c++draft/conv.integral#3
-- Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org Principal Engineer - Intel DCAI Platform & System Engineering
Received on 2024-12-12 12:57:51