@@ -67,32 +67,52 @@ typedef unsigned int uint;
6767#define MP_CEIL_DIVIDE (a , b ) (((a) + (b) - 1) / (b))
6868#define MP_ROUND_DIVIDE (a , b ) (((a) + (b) / 2) / (b))
6969
70- /** memory allocation ******************************************/
70+ #ifdef _MSC_VER
71+ static inline bool mp_mul_overflow (size_t a , size_t b , size_t * res ) {
72+ // TODO what if size_t is uint64_t
73+ uint64_t ab = (uint64_t )a * (uint64_t )b ;
74+ * res = ab ;
75+ return ab > UINT32_MAX ;
76+ }
77+ #else
78+ static inline bool mp_mul_overflow (size_t a , size_t b , size_t * res ) {
79+ return __builtin_mul_overflow (a , b , res );
80+ }
81+ #endif
82+
83+ #if MICROPY_HEAP_OVERFLOW_CHECKS
84+ size_t mp_checked_mul (size_t a , size_t b );
85+ size_t mp_checked_add (size_t a , size_t b );
86+ #else
87+ static inline size_t mp_checked_mul (size_t a , size_t b ) {
88+ return a * b ;
89+ }
90+ static inline size_t mp_checked_add (size_t a , size_t b ) {
91+ return a + b ;
92+ }
93+ #endif
7194
7295
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))
96+ /** memory allocation ******************************************/
7797
7898// TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element)
7999
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))))
100+ #define m_new (type , num ) ((type *)(m_malloc(mp_checked_mul(sizeof( type) , num))))
101+ #define m_new_maybe (type , num ) ((type *)(m_malloc_maybe(mp_checked_mul(sizeof( type) , num))))
102+ #define m_new0 (type , num ) ((type *)(m_malloc0(mp_checked_mul(sizeof( type) , num))))
83103#define m_new_obj (type ) (m_new(type, 1))
84104#define m_new_obj_maybe (type ) (m_new_maybe(type, 1))
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)))
105+ #define m_new_obj_var (obj_type , var_field , var_type , var_num ) ((obj_type *)m_malloc(mp_checked_add (offsetof(obj_type, var_field), mp_checked_mul(sizeof( var_type) , var_num) )))
106+ #define m_new_obj_var0 (obj_type , var_field , var_type , var_num ) ((obj_type *)m_malloc0(mp_checked_add (offsetof(obj_type, var_field), mp_checked_mul(sizeof( var_type) , var_num) )))
107+ #define m_new_obj_var_maybe (obj_type , var_field , var_type , var_num ) ((obj_type *)m_malloc_maybe(mp_checked_add (offsetof(obj_type, var_field), mp_checked_mul(sizeof( var_type) , var_num) )))
88108#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
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) ))
109+ #define m_renew (type , ptr , old_num , new_num ) ((type *)(m_realloc((ptr), sizeof (type) * old_num, mp_checked_mul(sizeof( type) , new_num))))
110+ #define m_renew_maybe (type , ptr , old_num , new_num , allow_move ) ((type *)(m_realloc_maybe((ptr), sizeof (type) * old_num, mp_checked_mul(sizeof( type) , new_num), (allow_move))))
111+ #define m_del (type , ptr , num ) m_free(ptr, sizeof (type) * num)
112+ #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))
93113#else
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))))
114+ #define m_renew (type , ptr , old_num , new_num ) ((type *)(m_realloc((ptr), mp_checked_mul(sizeof( type) , new_num))))
115+ #define m_renew_maybe (type , ptr , old_num , new_num , allow_move ) ((type *)(m_realloc_maybe((ptr), mp_checked_mul(sizeof( type) , new_num), (allow_move))))
96116#define m_del (type , ptr , num ) ((void)(num), m_free(ptr))
97117#define m_del_var (obj_type , var_field , var_type , var_num , ptr ) ((void)(var_num), m_free(ptr))
98118#endif
0 commit comments