Skip to content

Commit 444d7ba

Browse files
stinosdpgeorge
authored andcommitted
extmod/moductypes: Validate the descriptor tuple.
Fixes various null dereferencing, out-of-bounds memory accesses and `assert(0)` failures in the case of an invalid `uctypes` descriptor. By design `uctypes` can crash because it accesses arbitrary memory, but at least describing the descriptor layout should be forced to be correct and not crash. Fixes issue micropython#12702. Signed-off-by: stijn <[email protected]>
1 parent 6db91df commit 444d7ba

File tree

5 files changed

+63
-10
lines changed

5 files changed

+63
-10
lines changed

extmod/moductypes.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,26 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
143143

144144
// Get size of aggregate type descriptor
145145
static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) {
146+
if (t->len == 0) {
147+
syntax_error();
148+
}
149+
146150
mp_uint_t total_size = 0;
147151

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

151155
switch (agg_type) {
152156
case STRUCT:
157+
if (t->len != 2) {
158+
syntax_error();
159+
}
153160
return uctypes_struct_size(t->items[1], layout_type, max_field_size);
154161
case PTR:
162+
// Second field ignored, but should still be present for consistency.
163+
if (t->len != 2) {
164+
syntax_error();
165+
}
155166
if (sizeof(void *) > *max_field_size) {
156167
*max_field_size = sizeof(void *);
157168
}
@@ -167,15 +178,17 @@ static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
167178
if (item_s > *max_field_size) {
168179
*max_field_size = item_s;
169180
}
170-
} else {
181+
} else if (t->len == 3) {
171182
// Elements of array are aggregates
172183
item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size);
184+
} else {
185+
syntax_error();
173186
}
174187

175188
return item_s * arr_sz;
176189
}
177190
default:
178-
assert(0);
191+
syntax_error();
179192
}
180193

181194
return total_size;

tests/extmod/uctypes_sizeof.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,47 @@
4343
print(uctypes.sizeof(S.sub))
4444
assert uctypes.sizeof(S.sub) == 1
4545

46-
# invalid descriptor
46+
# invalid descriptors
4747
try:
4848
print(uctypes.sizeof([]))
4949
except TypeError:
5050
print("TypeError")
51+
52+
try:
53+
print(uctypes.sizeof(()))
54+
except TypeError:
55+
print("TypeError")
56+
57+
try:
58+
print(uctypes.sizeof(("garbage",)))
59+
except TypeError:
60+
print("TypeError")
61+
62+
try:
63+
# PTR * 3 is intended to be an invalid agg_type (STRUCT, PTR, ARRAY are valid ones).
64+
print(uctypes.sizeof((uctypes.PTR * 3,)))
65+
except TypeError:
66+
print("TypeError")
67+
68+
try:
69+
print(uctypes.sizeof((0, {}, "garbage")))
70+
except TypeError:
71+
print("TypeError")
72+
73+
try:
74+
print(uctypes.sizeof((uctypes.PTR | 0,)))
75+
except TypeError:
76+
print("TypeError")
77+
78+
try:
79+
print(uctypes.sizeof((uctypes.ARRAY | 0,)))
80+
except TypeError:
81+
print("TypeError")
82+
83+
try:
84+
print(uctypes.sizeof((uctypes.ARRAY | 0, 1, {}, "garbage")))
85+
except TypeError:
86+
print("TypeError")
87+
88+
# empty descriptor
89+
print(uctypes.sizeof({}))

tests/extmod/uctypes_sizeof.py.exp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,11 @@ TypeError
55
6
66
1
77
TypeError
8+
TypeError
9+
TypeError
10+
TypeError
11+
TypeError
12+
TypeError
13+
TypeError
14+
TypeError
15+
0

tests/extmod/uctypes_sizeof_od.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,3 @@
4545

4646
print(uctypes.sizeof(S.sub))
4747
assert uctypes.sizeof(S.sub) == 1
48-
49-
# invalid descriptor
50-
try:
51-
print(uctypes.sizeof([]))
52-
except TypeError:
53-
print("TypeError")

tests/extmod/uctypes_sizeof_od.py.exp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
TypeError
55
6
66
1
7-
TypeError

0 commit comments

Comments
 (0)