Skip to content

Fix partial construction vulnerabilities in VLA w/ exceptions #37

Description

@thirtytwobits

The VLA does not, currently, rollback already constructed items when an exception is thrown from a constructor when initializing lists of items.

One way to fix this is to implement https://en.cppreference.com/w/cpp/memory/uninitialized_move and use that.

Activity

  1. added theissue type on Mar 6, 2025
  2. scottdarch commented on Sep 29, 2026

    @scottdarch

    Development plan

    Implement this work in the following order. The prerequisite defects and the polyfill remain separately tracked changes.

    1. Fix and close both allocator-taking move constructor bugs

    Gate: both fixes must be merged, their regression tests must pass, and both issues must be closed before starting the polyfill implementation in step 2.

    These prerequisites establish usable exception propagation and correct buffer bookkeeping for subsequent VLA failure-path tests. Their fixes remain in their own issues/PRs.

    2. Implement and close the pf17 polyfill task

    Use its construction tracking and rollback machinery as the core mechanism for this fix. Keep standard move semantics in the public algorithm and make the internal rollback support reusable by allocator-aware container operations.

    Gate: merge the polyfill and its passing tests, and close #206 before integrating it into VLA for this issue.

    3. Add VLA regression tests for partial construction

    Add a dedicated exception-safety test suite using elements that throw on a selected construction attempt, plus allocation and object-lifetime tracking. Inject failures at the first, intermediate, and final construction positions.

    Cover:

    • Initializer-list, range, and copy construction.
    • Element-wise move construction with an unequal allocator.
    • Replacement-buffer construction in reserve() and shrink_to_fit().
    • Both resize overloads, with spare capacity and with allocation growth.
    • Newly constructed elements during copy assignment, unequal-allocator move assignment, and growth through assign(count, value).

    Check exact destruction counts, outstanding allocations, allocator ownership, allocation/deallocation sizes, and the surviving container state. Where an operation leaves a live container, exercise it again after catching the exception to detect hidden live objects or inconsistent bookkeeping.

    4. Integrate the polyfill's rollback mechanism into VLA

    Adapt the shared mechanism for VLA's construction operations:

    • Preserve allocator_traits::construct and allocator-aware object lifetime handling.
    • Preserve the existing move_if_noexcept relocation decision in the VLA layer.
    • Apply the same rollback discipline to copy, move, default, and fill construction, including assignment's newly constructed suffix.
    • Retain the trivial-type fast paths.

    Track each successfully constructed destination element. If construction fails, destroy exactly that constructed range and propagate the exception.

    Guard allocation ownership separately: the uninitialized-memory algorithm cleans up objects, while VLA must release any abandoned new buffer. Failed container constructors need explicit storage cleanup because their VLA destructor will not run. Existing container-owned storage must remain owned and accounted for.

    Commit size_, data_, and capacity_ only after the corresponding construction/ownership transition succeeds. Keep the generic VLA and the shared bool storage implementation consistent.

    5. Verify guarantees and complete this issue

    • Failed construction leaves no leaked allocation, missed destructor, or double destruction.
    • Failed reserve/shrink relocation preserves the original container when copying provides rollback.
    • Failed resize construction destroys the new suffix and retains the original size; capacity already acquired during growth may remain.
    • Assignment maintains valid lifetime and ownership bookkeeping after failure; already assigned values need not be restored.
    • Throwing move-only elements may leave source elements moved from; document this limitation rather than promising value rollback.
    • Focused exception-safety tests and all existing VLA tests pass, including allocator propagation/equality cases and bool regressions.
    • Supported GCC/Clang and language-mode checks pass, including C++14 and exceptions-disabled DebugEP/ReleaseEP builds. Guard exception-specific tests appropriately and run sanitizer checks where supported.

    Close #37 after its VLA integration and regression coverage are merged and verified. Implementing #206 alone does not complete the container ownership and state-management work.

  3. self-assigned this
    on Oct 6, 2026
  4. added a commit that references this issue on Oct 6, 2026
    ff27d2f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

acceptedThis is an accepted item to be implemented.component/VLAvariable_length_array issues

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions