aboutsummaryrefslogtreecommitdiff
path: root/py/runtime.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-04-01 00:00:58 +1100
committerDamien George <damien@micropython.org>2022-04-01 09:20:42 +1100
commitbd556b69960cafc97353e736f825eca5c00b0c29 (patch)
treec92422308d39f738ecefeef4fed269b5fde2ddf7 /py/runtime.c
parente3de723e2d955ca89c8b06bb2c4ae86724aad77b (diff)
py: Fix compiling and decoding of *args at large arg positions.
There were two issues with the existing code: 1. "1 << i" is computed as a 32-bit number so would overflow when executed on 64-bit machines (when mp_uint_t is 64-bit). This meant that *args beyond 32 positions would not be handled correctly. 2. star_args must fit as a positive small int so that it is encoded correctly in the emitted code. MP_SMALL_INT_BITS is too big because it overflows a small int by 1 bit. MP_SMALL_INT_BITS - 1 does not work because it produces a signed small int which is then sign extended when extracted (even by mp_obj_get_int_truncated), and this sign extension means that any position arg after *args is also treated as a star-arg. So the maximum bit position is MP_SMALL_INT_BITS - 2. This means that MP_OBJ_SMALL_INT_VALUE() can be used instead of mp_obj_get_int_truncated() to get the value of star_args. These issues are fixed by this commit, and a test added. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py/runtime.c')
-rw-r--r--py/runtime.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/py/runtime.c b/py/runtime.c
index 594e63082..ad066acb1 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -702,7 +702,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
}
size_t n_args = n_args_n_kw & 0xff;
size_t n_kw = (n_args_n_kw >> 8) & 0xff;
- mp_uint_t star_args = mp_obj_get_int_truncated(args[n_args + 2 * n_kw]);
+ mp_uint_t star_args = MP_OBJ_SMALL_INT_VALUE(args[n_args + 2 * n_kw]);
DEBUG_OP_printf("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, map=%u)\n", fun, self, n_args, n_kw, args, star_args);
@@ -720,7 +720,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
if (star_args != 0) {
for (size_t i = 0; i < n_args; i++) {
- if (star_args & (1 << i)) {
+ if ((star_args >> i) & 1) {
mp_obj_t len = mp_obj_len_maybe(args[i]);
if (len != MP_OBJ_NULL) {
// -1 accounts for 1 of n_args occupied by this arg
@@ -773,7 +773,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
for (size_t i = 0; i < n_args; i++) {
mp_obj_t arg = args[i];
- if (star_args & (1 << i)) {
+ if ((star_args >> i) & 1) {
// star arg
if (mp_obj_is_type(arg, &mp_type_tuple) || mp_obj_is_type(arg, &mp_type_list)) {
// optimise the case of a tuple and list