Skip to content

Commit 4614ee9

Browse files
jeplerdpgeorge
authored andcommitted
py/binary: Add MICROPY_PY_STRUCT_UNSAFE_TYPECODES.
This adds a compile-time flag to disable some "unsafe" and non-standard typecodes in struct, array and related modules. This is useful to turn off when fuzzing, as improper use of these typecodes can crash MicroPython. Signed-off-by: Jeff Epler <jepler@gmail.com>
1 parent 0ee3f99 commit 4614ee9

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

py/binary.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
6969
case 'Q':
7070
size = 8;
7171
break;
72+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
7273
case 'P':
7374
case 'O':
7475
case 'S':
7576
size = sizeof(void *);
7677
break;
78+
#endif
7779
case 'e':
7880
size = 2;
7981
break;
@@ -119,12 +121,14 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
119121
align = alignof(long long);
120122
size = sizeof(long long);
121123
break;
124+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
122125
case 'P':
123126
case 'O':
124127
case 'S':
125128
align = alignof(void *);
126129
size = sizeof(void *);
127130
break;
131+
#endif
128132
case 'e':
129133
align = 2;
130134
size = 2;
@@ -280,12 +284,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) {
280284
case 'd':
281285
return mp_obj_new_float_from_d(((double *)p)[index]);
282286
#endif
283-
// Extension to CPython: array of objects
287+
// Extension to CPython: array of objects
288+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
284289
case 'O':
285290
return ((mp_obj_t *)p)[index];
286291
// Extension to CPython: array of pointers
287292
case 'P':
288293
return mp_obj_new_int((mp_int_t)(uintptr_t)((void **)p)[index]);
294+
#endif
289295
}
290296
return MP_OBJ_NEW_SMALL_INT(val);
291297
}
@@ -334,9 +340,9 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte *
334340

335341
long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
336342

337-
if (val_type == 'O') {
343+
if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'O') {
338344
return (mp_obj_t)(mp_uint_t)val;
339-
} else if (val_type == 'S') {
345+
} else if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'S') {
340346
const char *s_val = (const char *)(uintptr_t)(mp_uint_t)val;
341347
return mp_obj_new_str_from_cstr(s_val);
342348
#if MICROPY_PY_BUILTINS_FLOAT
@@ -407,9 +413,11 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p
407413

408414
mp_uint_t val;
409415
switch (val_type) {
416+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
410417
case 'O':
411418
val = (mp_uint_t)val_in;
412419
break;
420+
#endif
413421
#if MICROPY_PY_BUILTINS_FLOAT
414422
case 'e':
415423
val = mp_encode_half_float(mp_obj_get_float_to_f(val_in));
@@ -474,10 +482,12 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_
474482
((double *)p)[index] = mp_obj_get_float_to_d(val_in);
475483
break;
476484
#endif
485+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
477486
// Extension to CPython: array of objects
478487
case 'O':
479488
((mp_obj_t *)p)[index] = val_in;
480489
break;
490+
#endif
481491
default:
482492
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
483493
if (mp_obj_is_exact_type(val_in, &mp_type_int)) {
@@ -534,9 +544,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_i
534544
((double *)p)[index] = (double)val;
535545
break;
536546
#endif
537-
// Extension to CPython: array of pointers
547+
// Extension to CPython: array of pointers
548+
#if MICROPY_PY_STRUCT_UNSAFE_TYPECODES
538549
case 'P':
539550
((void **)p)[index] = (void *)(uintptr_t)val;
540551
break;
552+
#endif
541553
}
542554
}

py/mpconfig.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,13 @@ typedef time_t mp_timestamp_t;
16011601
#define MICROPY_PY_STRUCT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
16021602
#endif
16031603

1604+
// Whether struct module provides unsafe and non-standard typecodes O, P, S.
1605+
// These typecodes are not in CPython and can cause crashes by accessing arbitrary
1606+
// memory.
1607+
#ifndef MICROPY_PY_STRUCT_UNSAFE_TYPECODES
1608+
#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (1)
1609+
#endif
1610+
16041611
// Whether to provide "sys" module
16051612
#ifndef MICROPY_PY_SYS
16061613
#define MICROPY_PY_SYS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)

0 commit comments

Comments
 (0)