From c60f77d5ab5c68f1fdaf0c734b77629418c7f903 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 4 Feb 2019 15:33:36 -0800 Subject: [PATCH 1/3] Check sequence multiply for length overflow Fixes #1279 --- py/obj.h | 2 ++ py/objlist.c | 3 ++- py/objstr.c | 3 ++- py/objtuple.c | 3 ++- py/sequence.c | 9 +++++++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/py/obj.h b/py/obj.h index 74ce6a0a98..95e2080214 100644 --- a/py/obj.h +++ b/py/obj.h @@ -844,6 +844,8 @@ typedef struct { mp_int_t step; } mp_bound_slice_t; +// Compute the new length of a sequence and ensure an exception is thrown on overflow. +size_t mp_seq_multiply_len(size_t item_sz, size_t len); void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest); #if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes); diff --git a/py/objlist.c b/py/objlist.c index 67940e44c8..16ca4b353e 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -126,7 +126,8 @@ STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { if (n < 0) { n = 0; } - mp_obj_list_t *s = list_new(o->len * n); + size_t new_len = mp_seq_multiply_len(o->len, n); + mp_obj_list_t *s = list_new(new_len); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return MP_OBJ_FROM_PTR(s); } diff --git a/py/objstr.c b/py/objstr.c index 9b6cb0cf4d..7236d97727 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -332,8 +332,9 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_const_empty_bytes; } } + size_t new_len = mp_seq_multiply_len(lhs_len, n); vstr_t vstr; - vstr_init_len(&vstr, lhs_len * n); + vstr_init_len(&vstr, new_len); mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, vstr.buf); return mp_obj_new_str_from_vstr(lhs_type, &vstr); } diff --git a/py/objtuple.c b/py/objtuple.c index d3262cebd4..474f81c1a5 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -160,7 +160,8 @@ mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { if (n <= 0) { return mp_const_empty_tuple; } - mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len * n, NULL)); + size_t new_len = mp_seq_multiply_len(o->len, n); + mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(new_len, NULL)); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return MP_OBJ_FROM_PTR(s); } diff --git a/py/sequence.c b/py/sequence.c index cc31be9831..26b432578c 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -34,6 +34,15 @@ #define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; } +// Detect when a multiply causes an overflow. +size_t mp_seq_multiply_len(size_t item_sz, size_t len) { + size_t new_len; + if (__builtin_umul_overflow(item_sz, len, &new_len)) { + mp_raise_msg(&mp_type_OverflowError, translate("small int overflow")); + } + return new_len; +} + // Implements backend of sequence * integer operation. Assumes elements are // memory-adjacent in sequence. void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest) { From 0c50154c837df7900dbc55dbc3fb81c2d25a21c9 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 4 Feb 2019 16:11:16 -0800 Subject: [PATCH 2/3] Use generic overflow so 64 bit is handled ok. --- py/sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/sequence.c b/py/sequence.c index 26b432578c..a750e5bac4 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -37,7 +37,7 @@ // Detect when a multiply causes an overflow. size_t mp_seq_multiply_len(size_t item_sz, size_t len) { size_t new_len; - if (__builtin_umul_overflow(item_sz, len, &new_len)) { + if (__builtin_mul_overflow(item_sz, len, &new_len)) { mp_raise_msg(&mp_type_OverflowError, translate("small int overflow")); } return new_len; From 844c20106bee7639f5fa83535806932bae354a71 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 4 Feb 2019 18:00:18 -0800 Subject: [PATCH 3/3] Turn off `micropython.mem_info` on SAMD to get ~1k back --- ports/atmel-samd/mpconfigport.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 137091b6de..080b7ff69f 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -54,6 +54,7 @@ #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_URANDOM (0) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) #define MICROPY_PY_STRUCT (0) @@ -256,7 +257,6 @@ extern const struct _mp_obj_module_t pixelbuf_module; #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UERRNO_ERRORCODE (0) #define MICROPY_PY_URE (1) - #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #ifndef MICROPY_PY_FRAMEBUF #define MICROPY_PY_FRAMEBUF (0) #endif @@ -342,7 +342,6 @@ extern const struct _mp_obj_module_t pixelbuf_module; #else #define MICROPY_PY_BUILTINS_REVERSED (0) - #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_FRAMEBUF (0) #ifndef EXTRA_BUILTIN_MODULES #define EXTRA_BUILTIN_MODULES