Skip to content

UBSan output is incorrect for non power-of-2 sized _BitInt types #88093

@bjope

Description

@bjope

Consider this test case:

unsigned foo(unsigned _BitInt(44) x) {
    _BitInt(9) c = -2;
    return x >> c;
}

int main() {
  return foo(5) ? 1 : 0;    
}

As shown by https://godbolt.org/z/M614qnhco , the result when compiling and running this program (with ubsan) is weird:

/app/example.c:3:14: runtime error: shift exponent 510 is too large for 64-bit type 'unsigned _BitInt(44)'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.c:3:14 

The expected error here would be "shift exponent -2 is negative". But it is not only the detection of isNegative for the exponent that is wrong, it also reports an incorrect bitwidth (64-bit type) for the shifted value.

Afaict the problem is that the TypeDescriptor encoding (compiler-rt/lib/ubsan/ubsan_value.h) encodes the _BitInt types like ordinary integer types:

    /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
    /// value. Remaining bits are log_2(bit width). The value representation is
    /// the integer itself if it fits into a ValueHandle, and a pointer to the
    /// integer otherwise.
    TK_Integer = 0x0000,

But using log_2(bit width) does not work that well when having non-power-of-two bit widths.

One idea could be to introduce a new TK_BitInt kind, that encodes the bit wifth in some other way? Although I have no idea how big impact that has on the rest of the code.

This problem was found when running tests with the fix from #88004

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions