summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/atmel-samd/mpconfigport.h3
-rw-r--r--py/obj.h2
-rw-r--r--py/objlist.c3
-rw-r--r--py/objstr.c3
-rw-r--r--py/objtuple.c3
-rw-r--r--py/sequence.c9
6 files changed, 18 insertions, 5 deletions
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index 137091b6d..080b7ff69 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
diff --git a/py/obj.h b/py/obj.h
index 74ce6a0a9..95e208021 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 67940e44c..16ca4b353 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 9b6cb0cf4..7236d9772 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 d3262cebd..474f81c1a 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 cc31be983..a750e5bac 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_mul_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) {