[Bug tree-optimization/93491] Wrong optimization: const-function moved over control flow leading to crashes

ch3root at openwall dot com gcc-bugzilla@gcc.gnu.org
Wed Jan 29 18:11:00 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93491

--- Comment #2 from Alexander Cherepanov <ch3root at openwall dot com> ---
(In reply to Andrew Pinski from comment #1)
> Const functions by definition dont trap or throw.

They don't trap in all cases when they are really called. But this doesn't mean
they must have a sane behavior for other combinations of arguments. At least
that's what I got from the definition[1] of this attribute. In particular, it
reads:

"Declaring such functions with the const attribute allows GCC to avoid emitting
some calls in repeated invocations of the function with the same argument
values."

That is, it allow gcc to eliminate some calls, but not to introduce new ones.

But this is a gcc extension so it could be assigned any meaning that is seemed
beneficial to gcc. In such a case this pr should be considered as a
documentation clarification request.

[1]
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute

> So adding const to a function that traps makes the testcase undefined.

Let me describe the testcase like this: the function `g` is defined only for
non-zero arguments, conforms to the rules of the const attribute for non-zero
arguments, and is called only with non-zero arguments, but the optimizer
introduces a call to it with the zero argument.

Perhaps the minimized example that I posted looks weird. The situation could be
more subtle in real life. For instance, the bad call could be due to an
unitialized variable used as the argument. I mean this variable could be
uninitialized only during speculative execution but perfectly initialized
during ordinary execution.

Or it could be something like this:

----------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>

__attribute__((noipa))
void check_value(int x)
{
    if (x == 0) {
        puts("Fatal error: got invalid value. Shutting down cleanly!");
        exit(0);
    }
}

__attribute__((const,noipa))
int calc(int x)
{
    return 1 / x;
}

int main(int c, char **v)
{
    (void)v;

    int x = 0; // invalid value by default
    // some complex initialization of x that doesn't always succeed
    if (c > 5)
        x = 123;
    // etc.

    for (int i = 0; i < 10; i++) {
        check_value(x);
        printf("result = %d\n", calc(x));
    }
}
----------------------------------------------------------------------
$ gcc -std=c11 -pedantic -Wall -Wextra test.c && ./a.out
Fatal error: got invalid value. Shutting down cleanly!
$ gcc -std=c11 -pedantic -Wall -Wextra -O3 test.c && ./a.out
Floating point exception
----------------------------------------------------------------------
gcc x86-64 version: gcc (GCC) 10.0.1 20200129 (experimental)
----------------------------------------------------------------------

Again, this doesn't mean that gcc have to support such use cases.

> Do you have a testcase were gcc does this optimize without the user adding
> const and still traps?

No. I'll file a separate bug if I stumble upon one, so please disregard this
possibility for now.


More information about the Gcc-bugs mailing list