Skip to content

insert(pos, count, value) overflows instead of throwing length_error #69

Description

@martinus

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++.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions