make_uninitialized_space() decides whether it has room with
auto s = size<D>();
if (s + count > capacity<D>()) {
return make_uninitialized_space_new<D>(s, p, count);
}
shift_right(p, data<D>() + s, p + count);
s + count is unchecked. A large count wraps around, the comparison says the elements fit, and the in-place shift path runs with a garbage count.
auto vec = std::vector<int>{1, 2, 3};
vec.insert(vec.begin(), SIZE_MAX - 1, 5); // std::vector: threw length_error
auto sv = ankerl::svector<int, 4>{1, 2, 3};
sv.insert(sv.begin(), SIZE_MAX - 1, 5); // svector: writes out of bounds
std::vector: threw length_error
svector: size=3 capacity=5, inserting SIZE_MAX-1...
ERROR: AddressSanitizer: stack-buffer-overflow
#4 svector<int, 4ul>::shift_right(int*, int*, int*) svector.h:566
#5 svector<int, 4ul>::make_uninitialized_space<direction::direct> svector.h:596
#7 svector<int, 4ul>::insert(int const*, unsigned long, int const&) svector.h:1041
detail::storage<T>::alloc() already has careful overflow checks and calculate_new_capacity() checks against max_size(), but neither is reached: the wrapped comparison sends the call down the path that never allocates.
Same applies to insert(pos, first, last) if std::distance returns something huge.
Suggestion
Check before adding, e.g.
if (count > max_size() - s) {
throw std::length_error("svector: too many elements");
}
std::vector throws length_error here, which is what max_size() is for.
Reproduced with g++ 16, -O1 -fsanitize=address, libstdc++.
make_uninitialized_space()decides whether it has room withs + countis unchecked. A largecountwraps around, the comparison says the elements fit, and the in-place shift path runs with a garbage count.detail::storage<T>::alloc()already has careful overflow checks andcalculate_new_capacity()checks againstmax_size(), but neither is reached: the wrapped comparison sends the call down the path that never allocates.Same applies to
insert(pos, first, last)ifstd::distancereturns something huge.Suggestion
Check before adding, e.g.
std::vectorthrowslength_errorhere, which is whatmax_size()is for.Reproduced with g++ 16,
-O1 -fsanitize=address, libstdc++.