From 5bf3765631e645412dbd62a616cfdadeca5ea0c3 Mon Sep 17 00:00:00 2001 From: Lars Haulin Date: Fri, 8 Jul 2022 17:48:40 +0200 Subject: [PATCH] py/objnamedtuple: Fix segfault with empty namedtuple. The empty tuple is usually a constant object, but named tuples must be allocated to allow modification. Added explicit allocation to fix this. Also added a regression test to verify creating an empty named tuple works. Fixes issue #7870. Signed-off-by: Lars Haulin --- py/objnamedtuple.c | 7 ++++--- tests/basics/namedtuple1.py | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 214cad257..b21299350 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -108,9 +108,10 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, #endif } - // Create a tuple and set the type to this namedtuple - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL)); - tuple->base.type = type_in; + // Create a namedtuple with explicit malloc. Calling mp_obj_new_tuple + // with num_fields=0 returns a read-only object. + mp_obj_tuple_t *tuple = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, num_fields, type_in); + tuple->len = num_fields; // Copy the positional args into the first slots of the namedtuple memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args); diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 47c0360eb..e8247e4d6 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -85,3 +85,8 @@ print(t.foo, t.bar) # Not implemented so far #T2 = namedtuple("TupComma", "foo,bar") #t = T2(1, 2) + +# Creating an empty namedtuple should not segfault +T5 = namedtuple("TupEmpty", []) +t = T5() +print(t)