Skip to content

Commit 7a169aa

Browse files
committed
py/objtype: Eliminate __set_name__ hazard.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
1 parent 8a3e849 commit 7a169aa

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

py/objtype.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,20 +1242,35 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
12421242
}
12431243

12441244
#if MICROPY_PY_DESCRIPTORS
1245-
// call __set_name__ on all entries (especially descriptors)
1245+
// make a list of all names of __set_name__-able attributes that won't be mutated by __set_name__ calls
1246+
mp_obj_list_t *setname_list = MP_OBJ_TO_PTR(mp_obj_list_make_new(&mp_type_list, 0, 0, NULL));
12461247
for (size_t i = 0; i < locals_map->alloc; i++) {
12471248
if (mp_map_slot_is_filled(locals_map, i)) {
12481249
elem = &(locals_map->table[i]);
12491250

1250-
mp_obj_t set_name_method[4];
1251-
mp_load_method_maybe(elem->value, MP_QSTR___set_name__, set_name_method);
1251+
mp_obj_t set_name_method[2];
1252+
mp_load_method_protected(elem->value, MP_QSTR___set_name__, set_name_method, true);
12521253
if (set_name_method[1] != MP_OBJ_NULL) {
1253-
set_name_method[2] = MP_OBJ_FROM_PTR(o);
1254-
set_name_method[3] = elem->key;
1255-
mp_call_method_n_kw(2, 0, set_name_method);
1254+
mp_obj_list_append(MP_OBJ_FROM_PTR(setname_list), elem->key);
12561255
}
12571256
}
12581257
}
1258+
1259+
nlr_buf_t nlr;
1260+
if (nlr_push(&nlr) == 0) {
1261+
// then use that list to call __set_name__ on each
1262+
for (size_t i = 0; i < setname_list->len; i++) {
1263+
elem = mp_map_lookup(locals_map, setname_list->items[i], MP_MAP_LOOKUP);
1264+
mp_obj_t set_name_method[4] = { [2] = MP_OBJ_FROM_PTR(o), [3] = elem->key };
1265+
mp_load_method(elem->value, MP_QSTR___set_name__, set_name_method);
1266+
mp_call_method_n_kw(2, 0, set_name_method);
1267+
}
1268+
nlr_pop();
1269+
} else {
1270+
m_del_obj(&mp_type_list, setname_list);
1271+
nlr_raise(nlr.ret_val);
1272+
}
1273+
m_del_obj(&mp_type_list, setname_list);
12591274
#endif
12601275

12611276
return MP_OBJ_FROM_PTR(o);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy