https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113761
--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Tomasz Kaminski <[email protected]>: https://gcc.gnu.org/g:7bed7d9276c11bef5a9a214e20c985af713f1532 commit r17-509-g7bed7d9276c11bef5a9a214e20c985af713f1532 Author: Tomasz KamiÅski <[email protected]> Date: Wed May 13 17:05:05 2026 +0200 libstdc++: Fix reserve of size_t(-1) elements in piecewise_constant_distribution. [PR113761] The piecewise_constant_distribution constructor from std::initializer_list il, unconditionally reserve _M_den for il.size()-1 elements. In case when the il.size() was zero, this led to unsigned overflow, and attempt to allocate size_t(-1) elements. This patch addresses above, by refactoring the constructors of param_type for both piecewise_constant_distribution and piecewise_linear_distribution, to exit early (and do not populate internal vectors) if number of intervals range is smaller than two. For the constructor accepting pair of iterators, this is done by checking result of __detail::__load_first2, that extracts up to two elements, and returns false, if less than two is found. Furthermore, we if the number of intervals is equal to two (for iterator __bbegin is at __bend after __load_first2), we store densities value on stack, and call newly introduced an _M_initialize2 helper, that does not populate internal vector if __ints and __dens values correspond to default configuration. With both of above changes, we no longer populate _M_int and _M_den with default values, and corresponding code that clears them in _M_initialize is not necessary. This avoids any unnecessary memory allocators. For constructor accepting two iterators, we reserve required space in _M_int vector, if the iterators are forward (or model sized_sentinel in C++20). The _M_den initialization is performed afterwards, so _M_int size is already determined (even for input iterators) and it can be used for call to reserve. Finally, the _M_initialize members are renamed to _M_configure, so the new implementation that skips the check, is not used by TU compiler will other that would invoke it with empty vector, and thus retrigger the issue. PR libstdc++/113761 libstdc++-v3/ChangeLog: * include/bits/random.h (piecewise_constant_distribution::param_type::_M_initialize) (piecewise_linear_distribution::param_type::_M_initialize): Remove. (piecewise_constant_distribution::param_type::_M_configure) (piecewise_linear_distribution::param_type::_M_configure): Define. (piecewise_constant_distribution::param_type::_M_initialize2) (piecewise_linear_distribution::param_type::_M_initialize2): Declare. * include/bits/random.tcc (__detail::__load_first2): Define. (piecewise_constant_distribution::param_type::_M_initialize) (piecewise_linear_distribution::param_type::_M_initialize): Rename to... (piecewise_constant_distribution::param_type::_M_configure) (piecewise_linear_distribution::param_type::_M_configure): Renamed implementation of _M_initialize, that removes checks for default values. (piecewise_constant_distribution::param_type::_M_initialize2) (piecewise_linear_distribution::param_type::_M_initialize2): Define. (piecewise_constant_distribution::param_type::param_type) (piecewise_linear_distribution::param_type::param_type): Exit early for less that two intervals. Use _M_initialize2 to handle two intervals case. Reserve _M_int for iterators case. * testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc: Test input and forward iterators, in addition to random_access ones. * testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc: Likewise. * testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc: New test. * testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc: New test. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz KamiÅski <[email protected]>
