Skip to content

Commit

Permalink
extmod/moductypes: Validate the descriptor tuple.
Browse files Browse the repository at this point in the history
Fixes issue micropython#12702 i.e. various null dereferencing,
out of bounds access and assert(0) failures.

Signed-off-by: stijn <[email protected]>
  • Loading branch information
stinos committed Nov 8, 2023
1 parent 958c6d9 commit 6564e0e
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
18 changes: 16 additions & 2 deletions extmod/moductypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,27 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {

// Get size of aggregate type descriptor
STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) {
if (t->len == 0) {
syntax_error();
}


mp_uint_t total_size = 0;

mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
mp_uint_t agg_type = GET_TYPE(offset_, AGG_TYPE_BITS);

switch (agg_type) {
case STRUCT:
if (t->len != 2) {
syntax_error();
}
return uctypes_struct_size(t->items[1], layout_type, max_field_size);
case PTR:
// Second field ignored, but should still be present for consistency.
if (t->len != 2) {
syntax_error();
}
if (sizeof(void *) > *max_field_size) {
*max_field_size = sizeof(void *);
}
Expand All @@ -167,15 +179,17 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
if (item_s > *max_field_size) {
*max_field_size = item_s;
}
} else {
} else if (t->len == 3) {
// Elements of array are aggregates
item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size);
} else {
syntax_error();
}

return item_s * arr_sz;
}
default:
assert(0);
syntax_error();
}

return total_size;
Expand Down
35 changes: 34 additions & 1 deletion tests/extmod/uctypes_sizeof.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,41 @@
print(uctypes.sizeof(S.sub))
assert uctypes.sizeof(S.sub) == 1

# invalid descriptor
# invalid descriptors
try:
print(uctypes.sizeof([]))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof(()))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof(("garbage")))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof((0, {}, "garbage")))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof((uctypes.PTR | 0)))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof((uctypes.ARRAY | 0)))
except TypeError:
print("TypeError")

try:
print(uctypes.sizeof((uctypes.ARRAY | 0, 1, {}, "garbage")))
except TypeError:
print("TypeError")

# empty descriptor
print(uctypes.sizeof({}))
7 changes: 7 additions & 0 deletions tests/extmod/uctypes_sizeof.py.exp
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ TypeError
6
1
TypeError
TypeError
TypeError
TypeError
TypeError
TypeError
TypeError
0
6 changes: 0 additions & 6 deletions tests/extmod/uctypes_sizeof_od.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,3 @@

print(uctypes.sizeof(S.sub))
assert uctypes.sizeof(S.sub) == 1

# invalid descriptor
try:
print(uctypes.sizeof([]))
except TypeError:
print("TypeError")
1 change: 0 additions & 1 deletion tests/extmod/uctypes_sizeof_od.py.exp
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
TypeError
6
1
TypeError

0 comments on commit 6564e0e

Please sign in to comment.