Skip to content

<random>: independent_bits_engine performs forbidden full shifts #5719

@StephanTLavavej

Description

@StephanTLavavej

Found by Clang 20 UBSan in P0952R2_new_generate_canonical's usage of independent_bits_engine. Reduced:

D:\GitHub\STL\out\x64>type meow.cpp
#include <cstddef>
#include <cstdint>
#include <print>
#include <random>
#include <string_view>
using namespace std;

template <class Engine, size_t W>
void test(const string_view name) {
    println("test<{}, {}>():", name, W);
    independent_bits_engine<Engine, W, uint64_t> ibe;
    const auto val = ibe();
    println("val: {}", val);
    println();
}

int main() {
    test<mt19937_64, 64>("mt19937_64");
    test<mt19937, 64>("mt19937");
    test<mt19937, 32>("mt19937");
}
D:\GitHub\STL\out\x64>clang-cl /EHsc /nologo /W4 /std:c++latest -fsanitize=undefined meow.cpp /Zi /Fdmeow.pdb /link /ignore:4217 && meow
   Creating library meow.lib and object meow.exp
test<mt19937_64, 64>():
D:\GitHub\STL\out\x64\out\inc\random:1977:25: runtime error: shift exponent 64 is too large for 64-bit type '_Eres' (aka 'unsigned long long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:25
D:\GitHub\STL\out\x64\out\inc\random:1977:34: runtime error: shift exponent 64 is too large for 64-bit type '_Eres' (aka 'unsigned long long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:34
D:\GitHub\STL\out\x64\out\inc\random:1978:27: runtime error: shift exponent 64 is too large for 64-bit type '_Eres' (aka 'unsigned long long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:27
D:\GitHub\STL\out\x64\out\inc\random:1978:42: runtime error: shift exponent 64 is too large for 64-bit type '_Eres' (aka 'unsigned long long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:42
D:\GitHub\STL\out\x64\out\inc\random:1915:25: runtime error: shift exponent 64 is too large for 64-bit type 'result_type' (aka 'unsigned long long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1915:25
val: 14514284786278117030

test<mt19937, 64>():
D:\GitHub\STL\out\x64\out\inc\random:1977:25: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:25
D:\GitHub\STL\out\x64\out\inc\random:1977:34: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:34
D:\GitHub\STL\out\x64\out\inc\random:1978:27: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:27
D:\GitHub\STL\out\x64\out\inc\random:1978:42: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:42
val: 15028999435905310454

test<mt19937, 32>():
D:\GitHub\STL\out\x64\out\inc\random:1977:25: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:25
D:\GitHub\STL\out\x64\out\inc\random:1977:34: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1977:34
D:\GitHub\STL\out\x64\out\inc\random:1978:27: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:27
D:\GitHub\STL\out\x64\out\inc\random:1978:42: runtime error: shift exponent 32 is too large for 32-bit type '_Eres' (aka 'unsigned int')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior D:\GitHub\STL\out\x64\out\inc\random:1978:42
val: 3499211612

Affected lines:

STL/stl/inc/random

Lines 1977 to 1978 in 0cb8132

_Yx0 = (_Rx >> _Wx0) << _Wx0;
_Yx1 = (((_Rx >> _Wx0) >> 1) << _Wx0) << 1;

_Res = _Res << _Wx0 | (static_cast<result_type>(_Val) & _Mask);

I am suspicious of this line, but I haven't found a case to trigger it yet:

_Res = _Res << (_Wx0 + 1) | (static_cast<result_type>(_Val) & _Mask);

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions