diff --git a/src/pack.c b/src/pack.c index 23e4004..a904b9b 100644 --- a/src/pack.c +++ b/src/pack.c @@ -77,9 +77,16 @@ pack_command(PyObject *cmd) } else if (PyMemoryView_Check(item)) { - Py_buffer *p_buf = PyMemoryView_GET_BUFFER(item); - tokens[i] = sdsnewlen(p_buf->buf, p_buf->len); - lengths[i] = p_buf->len; + Py_buffer buffer; + if (PyObject_GetBuffer(item, &buffer, PyBUF_SIMPLE) == -1) + { + // PyObject_GetBuffer sets an exception. + goto cleanup; + } + + tokens[i] = sdsnewlen(buffer.buf, buffer.len); + lengths[i] = buffer.len; + PyBuffer_Release(&buffer); } else { diff --git a/tests/test_pack.py b/tests/test_pack.py index 2c3dbfd..be9d32f 100644 --- a/tests/test_pack.py +++ b/tests/test_pack.py @@ -45,3 +45,12 @@ def __init__(self) -> None: with pytest.raises(TypeError): hiredis.pack_command(("HSET", "foo", Bar())) + + +def test_non_contiguous_memoryview(): + # A reversed memoryview starts at the last byte of its buffer, so copying + # nbytes forward from it reads past the end of the bytearray. + view = memoryview(bytearray(b"0123456789abcdef"))[::-1] + + with pytest.raises(BufferError): + hiredis.pack_command(("SET", "a", view))