Skip to content

<ranges>: Access violation on find in byte range with unreachable_sentinel #2431

@AlexGuteniev

Description

@AlexGuteniev

Describe the bug
ranges::find with unreachable_sentinel may read beyond the found element.
This is due to memchr optimization and memchr misbehavior reported as DevCom-1615707

Command-line test case

#include <cassert>
#include <ranges>
#include <utility>

#include <Windows.h>

using namespace std;

void* volatile discard;

int main() {
    SYSTEM_INFO si = {};
    GetSystemInfo(&si);

    const size_t page  = si.dwPageSize;
    const size_t alloc = max<size_t>(page * 2, si.dwAllocationGranularity);

    void* p = VirtualAlloc(nullptr, alloc, MEM_RESERVE, PAGE_NOACCESS);
    assert(p != nullptr);
    void* p2 = VirtualAlloc(p, page, MEM_COMMIT, PAGE_READWRITE);
    assert(p2 != nullptr);

    const auto p3    = reinterpret_cast<char*>(p2) + page - 3;
    p3[0]            = '1';
    p3[1]            = '2';
    p3[2]            = '3';
    const auto bingo = ranges::find(p3, unreachable_sentinel, '3');
    assert(bingo == p3 + 2);

    const auto bingo2 = ranges::find(p3 - 16, unreachable_sentinel, '2');
    assert(bingo2 == p3 + 1);

    const auto bingo3 = ranges::find(p3 - 32, unreachable_sentinel, '1');
    assert(bingo3 == p3);

    const auto bingo4 = ranges::find(p3 - 64, unreachable_sentinel, '3');
    assert(bingo4 == p3 + 2);

    VirtualFree(p, 0, MEM_RELEASE);
}

Expected behavior
No crash. But still with optimization of this case.

STL version
Version 17.1.0 Preview 1.1

Additional context
Relates to #2379 - in scope of this improvement can also address this problem

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!rangesC++20/23 ranges

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions