Skip to content

Commit 0615d13

Browse files
jeplerdpgeorge
authored andcommitted
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 micropython#17847. Signed-off-by: Jeff Epler <jepler@gmail.com>
1 parent 803da96 commit 0615d13

File tree

5 files changed

+60
-11
lines changed

5 files changed

+60
-11
lines changed

py/objringio.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,19 @@ typedef struct _micropython_ringio_obj_t {
3939

4040
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) {
4141
mp_arg_check_num(n_args, n_kw, 1, 1, false);
42-
mp_int_t buff_size = -1;
4342
mp_buffer_info_t bufinfo = {NULL, 0, 0};
4443

4544
if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
46-
buff_size = mp_obj_get_int(args[0]);
45+
bufinfo.len = mp_obj_get_int(args[0]) + 1;
46+
bufinfo.buf = m_new(uint8_t, bufinfo.len);
4747
}
48-
micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type);
49-
if (bufinfo.buf != NULL) {
50-
// buffer passed in, use it directly for ringbuffer.
51-
self->ringbuffer.buf = bufinfo.buf;
52-
self->ringbuffer.size = bufinfo.len;
53-
self->ringbuffer.iget = self->ringbuffer.iput = 0;
54-
} else {
55-
// Allocate new buffer, add one extra to buff_size as ringbuf consumes one byte for tracking.
56-
ringbuf_alloc(&(self->ringbuffer), buff_size + 1);
48+
if (bufinfo.len < 2 || bufinfo.len > UINT16_MAX) {
49+
mp_raise_ValueError(NULL);
5750
}
51+
micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type);
52+
self->ringbuffer.buf = bufinfo.buf;
53+
self->ringbuffer.size = bufinfo.len;
54+
self->ringbuffer.iget = self->ringbuffer.iput = 0;
5855
return MP_OBJ_FROM_PTR(self);
5956
}
6057

tests/micropython/ringio.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,21 @@
4646
micropython.RingIO(None)
4747
except TypeError as ex:
4848
print(type(ex))
49+
50+
try:
51+
# Buffer may not be empty
52+
micropython.RingIO(bytearray(0))
53+
except ValueError as ex:
54+
print(type(ex))
55+
56+
try:
57+
# Buffer may not be too small
58+
micropython.RingIO(bytearray(1))
59+
except ValueError as ex:
60+
print(type(ex))
61+
62+
try:
63+
# Size may not be too small
64+
micropython.RingIO(0)
65+
except ValueError as ex:
66+
print(type(ex))

tests/micropython/ringio.py.exp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ b'\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01'
1414
0
1515
b'\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01'
1616
<class 'TypeError'>
17+
<class 'ValueError'>
18+
<class 'ValueError'>
19+
<class 'ValueError'>

tests/micropython/ringio_big.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Check that micropython.RingIO works correctly.
2+
3+
import micropython
4+
5+
try:
6+
micropython.RingIO
7+
except AttributeError:
8+
print("SKIP")
9+
raise SystemExit
10+
11+
try:
12+
# The maximum possible size
13+
micropython.RingIO(bytearray(65535))
14+
micropython.RingIO(65534)
15+
16+
try:
17+
# Buffer may not be too big
18+
micropython.RingIO(bytearray(65536))
19+
except ValueError as ex:
20+
print(type(ex))
21+
22+
try:
23+
# Size may not be too big
24+
micropython.RingIO(65535)
25+
except ValueError as ex:
26+
print(type(ex))
27+
except MemoryError:
28+
print("SKIP")
29+
raise SystemExit
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<class 'ValueError'>
2+
<class 'ValueError'>

0 commit comments

Comments
 (0)