CVE-2022-4969
Description
Buffer overflow in rockhopper's binary parser allows local attackers to read arbitrary memory or cause denial of service via crafted input.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Buffer overflow in rockhopper's binary parser allows local attackers to read arbitrary memory or cause denial of service via crafted input.
Vulnerability
Overview
CVE-2022-4969 describes a buffer overflow vulnerability in the rockhopper library (versions up to 0.1.2). The flaw is located in the count_rows function within rockhopper/src/ragged_array.c, which is part of the binary parser used by RaggedArray.loads(). When parsing binary data with a row length type (ldtype) of np.uint64, a maliciously crafted row length value close to 2^64 can cause the internal buffer pointer to overflow, leading to out-of-bounds memory access [1][2][3].
Exploitation
Conditions
Exploitation requires local access to the system. An attacker must supply a specially crafted binary file to the RaggedArray.loads() function. No authentication or special privileges are needed beyond the ability to execute code that calls this function. The attack surface is limited to local users or processes that can feed untrusted data into the library [2][4].
Impact
Successful exploitation can result in reading arbitrary memory within the address space of the process using rockhopper, potentially leaking sensitive information. Alternatively, if the overflow causes the pointer to map to an unmapped memory region, a segmentation fault occurs, leading to a denial of service. The vulnerability is rated as critical in the original advisory, with a CVSS v3 base score of 5.3 (Medium) [2].
Mitigation
The issue is fixed in rockhopper version 0.2.0. The patch (commit 1a15fad5e06ae693eb9b8908363d2c8ef455104e) adds a guard that detects the pointer overflow and raises a ValueError instead of allowing the unsafe memory access. Users are strongly recommended to upgrade to the latest version [3][4].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
rockhopperPyPI | < 0.2.0 | 0.2.0 |
Affected products
1Patches
21a15fad5e06aFix a potential security exploit in RaggedArray.loads(buffer, ldtype=np.uint64).
3 files changed · +47 −2
rockhopper/src/ragged_array.c+2 −1 modified@@ -59,8 +59,9 @@ int count_rows(void * raw, int raw_length, int length_power, int big_endian, int rows = 0; + void * start = raw; void * end = raw + raw_length; - while (raw <= end - (1 << length_power)) { + while (raw <= end - (1 << length_power) && raw >= start) { uint64_t length = read(raw); raw += (1 << length_power); raw += length * itemsize;
setup.py+1 −1 modified@@ -34,7 +34,7 @@ extras_require={ "test": [ 'pytest>=3', 'pytest-order', 'coverage', 'pytest-cov', - 'coverage-conditional-plugin' + 'coverage-conditional-plugin', 'hypothesis' ] }, license="MIT license",
tests/test_io.py+44 −0 modified@@ -7,6 +7,7 @@ import numpy as np import pytest from cslug import ptr +from hypothesis import given, strategies, settings, Verbosity, example from rockhopper import RaggedArray from rockhopper._ragged_array import _2_power, _big_endian @@ -61,6 +62,49 @@ def test_dump_load(dtype, byteorder): assert consumed == len(bin) +int_types = [ + np.uint8, np.uint16, np.uint32, np.uint64, + np.int8, np.int16, np.int32, np.int64, +] +blob = bytes(range(256)) + bytes(range(256))[::-1] + + +@pytest.mark.parametrize("dtype", int_types) +@pytest.mark.parametrize("ldtype", int_types) +def test_loads_pointer_overflow_guard(dtype, ldtype): + """Test that the check for pointer overflowing caused by reading a huge row + length works.""" + for i in range(-30, len(blob)): + try: + RaggedArray.loads(blob[i: i+30], dtype=dtype, ldtype=ldtype) + except ValueError: + pass + + +@pytest.mark.parametrize("dtype", int_types) +@pytest.mark.parametrize("ldtype", int_types) +def test_fuzz_loads(dtype, ldtype): + """Scan for possible segfaults. + + All invalid inputs must lead to a ValueError rather than a seg-fault or + RaggedArray.loads() could be tricked into reading arbitrary memory addresses + by a maliciously constructed invalid data file. + + """ + @given(strategies.binary()) + @example(b'\xc0\\\\\xb0\x93\x91\xff\xffpEfe\x167\xee') + def fuzz(x): + print(x) + try: + self, _ = RaggedArray.loads(x, dtype=dtype, ldtype=ldtype) + except ValueError: + pass + else: + assert self.dumps(ldtype=ldtype).tobytes() == x + + fuzz() + + def test_dump_byteorder(): self = RaggedArray.from_nested([[0x0109, 0x0208, 0x0307]], dtype=np.uint16)
d608ebbcffd9Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6News mentions
0No linked articles in our index yet.