Skip to content

<random>: independent_bits_engine performs forbidden full shifts #5719

Description

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);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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