py/objringio: Detect incorrect constructor calls.

ringbuffer.size must be at least 2, and is a 16-bit quantity.

This fixes several cases including the one the fuzzer discovered, which
would lead to a fatal signal when accessing the object.

Fixes issue #17847.

Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
Jeff Epler 2025-08-06 10:15:57 -05:00 committed by Damien George
parent 803da9645f
commit 0615d13963
5 changed files with 60 additions and 11 deletions

View file

@ -39,22 +39,19 @@ typedef struct _micropython_ringio_obj_t {
static mp_obj_t micropython_ringio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_int_t buff_size = -1;
mp_buffer_info_t bufinfo = {NULL, 0, 0};
if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
buff_size = mp_obj_get_int(args[0]);
bufinfo.len = mp_obj_get_int(args[0]) + 1;
bufinfo.buf = m_new(uint8_t, bufinfo.len);
}
if (bufinfo.len < 2 || bufinfo.len > UINT16_MAX) {
mp_raise_ValueError(NULL);
}
micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type);
if (bufinfo.buf != NULL) {
// buffer passed in, use it directly for ringbuffer.
self->ringbuffer.buf = bufinfo.buf;
self->ringbuffer.size = bufinfo.len;
self->ringbuffer.iget = self->ringbuffer.iput = 0;
} else {
// Allocate new buffer, add one extra to buff_size as ringbuf consumes one byte for tracking.
ringbuf_alloc(&(self->ringbuffer), buff_size + 1);
}
self->ringbuffer.buf = bufinfo.buf;
self->ringbuffer.size = bufinfo.len;
self->ringbuffer.iget = self->ringbuffer.iput = 0;
return MP_OBJ_FROM_PTR(self);
}

View file

@ -46,3 +46,21 @@ try:
micropython.RingIO(None)
except TypeError as ex:
print(type(ex))
try:
# Buffer may not be empty
micropython.RingIO(bytearray(0))
except ValueError as ex:
print(type(ex))
try:
# Buffer may not be too small
micropython.RingIO(bytearray(1))
except ValueError as ex:
print(type(ex))
try:
# Size may not be too small
micropython.RingIO(0)
except ValueError as ex:
print(type(ex))

View file

@ -14,3 +14,6 @@ b'\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01'
0
b'\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01'
<class 'TypeError'>
<class 'ValueError'>
<class 'ValueError'>
<class 'ValueError'>

View file

@ -0,0 +1,29 @@
# Check that micropython.RingIO works correctly.
import micropython
try:
micropython.RingIO
except AttributeError:
print("SKIP")
raise SystemExit
try:
# The maximum possible size
micropython.RingIO(bytearray(65535))
micropython.RingIO(65534)
try:
# Buffer may not be too big
micropython.RingIO(bytearray(65536))
except ValueError as ex:
print(type(ex))
try:
# Size may not be too big
micropython.RingIO(65535)
except ValueError as ex:
print(type(ex))
except MemoryError:
print("SKIP")
raise SystemExit

View file

@ -0,0 +1,2 @@
<class 'ValueError'>
<class 'ValueError'>