From a3e01d3642d6c287bf2d0c14b3d75bf305327819 Mon Sep 17 00:00:00 2001 From: Mike Wadsten Date: Sun, 18 Feb 2018 21:51:04 -0600 Subject: [PATCH] py/objdict: Disallow possible modifications to fixed dicts. --- py/objdict.c | 13 +++++++++ tests/basics/dict_fixed.py | 48 ++++++++++++++++++++++++++++++++++ tests/basics/dict_fixed.py.exp | 7 +++++ 3 files changed, 68 insertions(+) create mode 100644 tests/basics/dict_fixed.py create mode 100644 tests/basics/dict_fixed.py.exp diff --git a/py/objdict.c b/py/objdict.c index f6fb594b3c..c0647067a1 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -195,9 +195,16 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { /******************************************************************************/ /* dict methods */ +STATIC void mp_ensure_not_fixed(const mp_obj_dict_t *dict) { + if (dict->map.is_fixed) { + mp_raise_TypeError(NULL); + } +} + STATIC mp_obj_t dict_clear(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); mp_map_clear(&self->map); @@ -253,6 +260,9 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromk STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); + if (lookup_kind != MP_MAP_LOOKUP) { + mp_ensure_not_fixed(self); + } mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind); mp_obj_t value; if (elem == NULL || elem->value == MP_OBJ_NULL) { @@ -295,6 +305,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { @@ -313,6 +324,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); + mp_ensure_not_fixed(self); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); @@ -578,6 +590,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) { mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return self_in; } diff --git a/tests/basics/dict_fixed.py b/tests/basics/dict_fixed.py new file mode 100644 index 0000000000..4261a06557 --- /dev/null +++ b/tests/basics/dict_fixed.py @@ -0,0 +1,48 @@ +# test that fixed dictionaries cannot be modified + +try: + import uerrno +except ImportError: + print("SKIP") + raise SystemExit + +# Save a copy of uerrno.errorcode, so we can check later +# that it hasn't been modified. +errorcode_copy = uerrno.errorcode.copy() + +try: + uerrno.errorcode.popitem() +except TypeError: + print("TypeError") + +try: + uerrno.errorcode.pop(0) +except TypeError: + print("TypeError") + +try: + uerrno.errorcode.setdefault(0, 0) +except TypeError: + print("TypeError") + +try: + uerrno.errorcode.update([(1, 2)]) +except TypeError: + print("TypeError") + +try: + del uerrno.errorcode[1] +except TypeError: + print("TypeError") + +try: + uerrno.errorcode[1] = 'foo' +except TypeError: + print("TypeError") + +try: + uerrno.errorcode.clear() +except TypeError: + print("TypeError") + +assert uerrno.errorcode == errorcode_copy diff --git a/tests/basics/dict_fixed.py.exp b/tests/basics/dict_fixed.py.exp new file mode 100644 index 0000000000..ffaeb4085c --- /dev/null +++ b/tests/basics/dict_fixed.py.exp @@ -0,0 +1,7 @@ +TypeError +TypeError +TypeError +TypeError +TypeError +TypeError +TypeError