Skip to content

Commit b19d7fc

Browse files
committed
py/misc.h: prevent m_new from overflowing size_t when multiplying type
size and number of elements Previously, it could led to a situation where m_new(type, BIG_NUMBER) would call m_alloc(zero) because sizeof(type)*BIG_NUMBER would return 0. This change ensures that a MemoryError is raised.
1 parent ad3552a commit b19d7fc

1 file changed

Lines changed: 18 additions & 12 deletions

File tree

py/misc.h

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,30 @@ typedef unsigned int uint;
6969

7070
/** memory allocation ******************************************/
7171

72+
73+
// Ensure that m_new does not overflow the multiplication when computing sizeof(type) * num.
74+
#define CAPPED_SIZE_NUM_OBJ(type, num) ((sizeof(type) * (num)) / sizeof(type) != (size_t)(num) ? SIZE_MAX : sizeof(type) * (num))
75+
// Ensure that the multiplication and the addition do not overflow.
76+
#define CAPPED_SIZE_OBJ_NUM_VAR(obj_type, var_type, var_num) ((sizeof(var_type) * (var_num)) / sizeof(var_type) != (size_t)(var_num) || sizeof(obj_type) + sizeof(var_type) * (var_num) < sizeof(var_type) * (var_num) ? SIZE_MAX : sizeof(obj_type) + sizeof(var_type) * (var_num))
77+
7278
// TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element)
7379

74-
#define m_new(type, num) ((type *)(m_malloc(sizeof(type) * (num))))
75-
#define m_new_maybe(type, num) ((type *)(m_malloc_maybe(sizeof(type) * (num))))
76-
#define m_new0(type, num) ((type *)(m_malloc0(sizeof(type) * (num))))
80+
#define m_new(type, num) ((type *)(m_malloc(CAPPED_SIZE_NUM_OBJ(type, num))))
81+
#define m_new_maybe(type, num) ((type *)(m_malloc_maybe(CAPPED_SIZE_NUM_OBJ(type, num))))
82+
#define m_new0(type, num) ((type *)(m_malloc0(CAPPED_SIZE_NUM_OBJ(type, num))))
7783
#define m_new_obj(type) (m_new(type, 1))
7884
#define m_new_obj_maybe(type) (m_new_maybe(type, 1))
79-
#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num)))
80-
#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num)))
81-
#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num)))
85+
#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(CAPPED_SIZE_OBJ_NUM_VAR(offsetof(obj_type, var_field), var_type, var_num)))
86+
#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(CAPPED_SIZE_OBJ_NUM_VAR(offsetof(obj_type, var_field), var_type, var_num)))
87+
#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(CAPPED_SIZE_OBJ_NUM_VAR(offsetof(obj_type, var_field), var_type, var_num)))
8288
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
83-
#define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num))))
84-
#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move))))
85-
#define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num))
86-
#define m_del_var(obj_type, var_field, var_type, var_num, ptr) (m_free(ptr, offsetof(obj_type, var_field) + sizeof(var_type) * (var_num)))
89+
#define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), CAPPED_SIZE_NUM_OBJ(type, old_num), CAPPED_SIZE_NUM_OBJ(type, new_num))))
90+
#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), CAPPED_SIZE_NUM_OBJ(type, old_num), CAPPED_SIZE_NUM_OBJ(type, new_num), (allow_move))))
91+
#define m_del(type, ptr, num) m_free(ptr, CAPPED_SIZE_NUM_OBJ(type, num))
92+
#define m_del_var(obj_type, var_field, var_type, var_num, ptr) (m_free(ptr, CAPPED_SIZE_OBJ_NUM_VAR(offsetof(obj_type, var_field), var_type, var_num)))
8793
#else
88-
#define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (new_num))))
89-
#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (new_num), (allow_move))))
94+
#define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), CAPPED_SIZE_NUM_OBJ(type, new_num))))
95+
#define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), CAPPED_SIZE_NUM_OBJ(type, new_num), (allow_move))))
9096
#define m_del(type, ptr, num) ((void)(num), m_free(ptr))
9197
#define m_del_var(obj_type, var_field, var_type, var_num, ptr) ((void)(var_num), m_free(ptr))
9298
#endif

0 commit comments

Comments
 (0)