Skip to content

Commit fdc0c6f

Browse files
committed
py/dynruntime: Make malloc functions raise MemoryError on failure.
Addresses some TODOs in this file. Signed-off-by: Damien George <[email protected]>
1 parent 994751c commit fdc0c6f

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

py/dynruntime.h

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828

2929
// This header file contains definitions to dynamically implement the static
3030
// MicroPython runtime API defined in py/obj.h and py/runtime.h.
31+
//
32+
// All of the symbols made available in this header are overriding those defined
33+
// in py/obj.h and py/runtime.h. This is done with macros. For macros that
34+
// would be too complicated (usually more than a single expression), they call a
35+
// static-inline function for the implementation. This function has the same
36+
// name as the macro (hence the same name as a public API function) but with
37+
// "_dyn" appended. For example, the m_malloc() macro calls the m_malloc_dyn()
38+
// static-inline function.
3139

3240
#include "py/binary.h"
3341
#include "py/nativeglue.h"
@@ -39,6 +47,10 @@
3947
#error "dynruntime.h included in non-dynamic-module build."
4048
#endif
4149

50+
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
51+
#error "MICROPY_MALLOC_USES_ALLOCATED_SIZE must be disable in a dynamic-module build."
52+
#endif
53+
4254
#undef MP_ROM_QSTR
4355
#undef MP_OBJ_QSTR_VALUE
4456
#undef MP_OBJ_NEW_QSTR
@@ -52,22 +64,40 @@
5264
/******************************************************************************/
5365
// Memory allocation
5466

67+
#define m_malloc_fail(num_bytes) (m_malloc_fail_dyn((num_bytes)))
5568
#define m_malloc(n) (m_malloc_dyn((n)))
5669
#define m_free(ptr) (m_free_dyn((ptr)))
5770
#define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes)))
71+
#define m_realloc_maybe(ptr, new_num_bytes, allow_move) (m_realloc_maybe_dyn((ptr), (new_num_bytes), (allow_move)))
72+
73+
static NORETURN inline void m_malloc_fail_dyn(size_t num_bytes) {
74+
mp_fun_table.raise_msg(
75+
mp_fun_table.load_global(MP_QSTR_MemoryError),
76+
"memory allocation failed");
77+
}
78+
79+
static inline void *m_realloc_maybe_dyn(void *ptr, size_t new_num_bytes, bool allow_move) {
80+
return mp_fun_table.realloc_(ptr, new_num_bytes, allow_move);
81+
}
82+
83+
static inline void *m_realloc_checked_dyn(void *ptr, size_t new_num_bytes, bool allow_move) {
84+
ptr = m_realloc_maybe(ptr, new_num_bytes, allow_move);
85+
if (ptr == NULL && new_num_bytes != 0) {
86+
m_malloc_fail(new_num_bytes);
87+
}
88+
return ptr;
89+
}
5890

5991
static inline void *m_malloc_dyn(size_t n) {
60-
// TODO won't raise on OOM
61-
return mp_fun_table.realloc_(NULL, n, false);
92+
return m_realloc_checked_dyn(NULL, n, false);
6293
}
6394

6495
static inline void m_free_dyn(void *ptr) {
6596
mp_fun_table.realloc_(ptr, 0, false);
6697
}
6798

6899
static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) {
69-
// TODO won't raise on OOM
70-
return mp_fun_table.realloc_(ptr, new_num_bytes, true);
100+
return m_realloc_checked_dyn(ptr, new_num_bytes, true);
71101
}
72102

73103
/******************************************************************************/

0 commit comments

Comments
 (0)