Skip to content

Native View.slice can overflow its bounds check and return an oversized view #183

Closed

Description

@dimensionscape

cpp::marshal::View::slice(index, length) checks inIndex + inLength > length using signed int64_t addition. A large positive requested length can overflow that addition and bypass the bounds check on a valid, small view.

I reproduced this against checkout 793e054 on Linux x86_64 through WSL, using Haxe 4.3.3 with HXCPP_M64 and directly including the current View.hpp in a native probe:

#include <cpp/marshal/View.hpp>
#include <cstdint>

unsigned char data[16] = {};
cpp::marshal::View<unsigned char> view(cpp::Pointer<unsigned char>(data), 16);
auto bad = view.slice(1, INT64_MAX);

The call returned without throwing, and bad.length was 9223372036854775807. No out-of-bounds access was performed in the probe.

The constructor accepts a real 16-byte buffer here; the invalid view is created by slice's own bounds check. Subsequent indexed access trusts that oversized length, and clear/copy operations also use it. This can turn invalid slice arguments into out-of-bounds reads or writes. The addition itself is signed-overflow undefined behavior.

After validating a nonnegative index within the original view, compare the requested length against length - inIndex instead of adding the two input values. Add boundary tests for INT64_MAX, an empty slice at the end, a valid exact-end slice, and negative arguments. Run the boundary cases under UBSan too.

This is in the native marshalling View API, separate from Haxe Array slicing and the earlier Array byte-count fixes in #94.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions