Skip to content

Commit

Permalink
Merge pull request #9789 from jepler/detect-invalid-json-dump-types
Browse files Browse the repository at this point in the history
Throw TypeError when json-serializing invalid types
  • Loading branch information
dhalbert authored Nov 4, 2024
2 parents 24a8927 + 9113e17 commit 973f597
Show file tree
Hide file tree
Showing 12 changed files with 32 additions and 16 deletions.
7 changes: 7 additions & 0 deletions py/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
}
#endif
const mp_obj_type_t *type = mp_obj_get_type(o_in);
// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
#if MICROPY_PY_JSON
if (kind == PRINT_JSON && !(type->flags & MP_TYPE_FLAG_PRINT_JSON)) {
mp_raise_msg_varg(&mp_type_TypeError,
MP_ERROR_TEXT("can't convert %q to %q"), type->name, MP_QSTR_json);
}
#endif
if (MP_OBJ_TYPE_HAS_SLOT(type, print)) {
MP_OBJ_TYPE_GET_SLOT(type, print)((mp_print_t *)print, o_in, kind);
} else {
Expand Down
2 changes: 2 additions & 0 deletions py/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);
#define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100)
#define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM)
#define MP_TYPE_FLAG_INSTANCE_TYPE (0x0200)
// CIRCUITPY-CHANGE: check for valid types in json dumps
#define MP_TYPE_FLAG_PRINT_JSON (0x0400)

typedef enum {
PRINT_STR = 0,
Expand Down
3 changes: 2 additions & 1 deletion py/objbool.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ static mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(value), rhs_in);
}

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
// can match all numeric types
mp_type_bool,
MP_QSTR_bool,
MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE,
MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_PRINT_JSON,
make_new, bool_make_new,
print, bool_print,
unary_op, bool_unary_op,
Expand Down
6 changes: 4 additions & 2 deletions py/objdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,11 @@ static const mp_rom_map_elem_t dict_locals_dict_table[] = {

static MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_dict,
MP_QSTR_dict,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_dict_make_new,
print, dict_print,
unary_op, dict_unary_op,
Expand All @@ -724,10 +725,11 @@ MP_DEFINE_CONST_OBJ_TYPE(
);

#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_ordereddict,
MP_QSTR_OrderedDict,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_dict_make_new,
print, dict_print,
unary_op, dict_unary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objfloat.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ static mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
return mp_obj_float_binary_op(op, lhs_val, rhs_in);
}

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE,
mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_PRINT_JSON,
make_new, float_make_new,
print, float_print,
unary_op, float_unary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objint.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,10 +588,11 @@ static const mp_rom_map_elem_t int_locals_dict_table[] = {

static MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_int,
MP_QSTR_int,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_int_make_new,
print, mp_obj_int_print,
unary_op, mp_obj_int_unary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,11 @@ static const mp_rom_map_elem_t list_locals_dict_table[] = {

static MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table);

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_list,
MP_QSTR_list,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_list_make_new,
print, list_print,
unary_op, list_unary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objnone.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ static void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
}
}

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_NoneType,
MP_QSTR_NoneType,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_PRINT_JSON,
print, none_print
);

Expand Down
3 changes: 2 additions & 1 deletion py/objstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2203,10 +2203,11 @@ MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_memoryview_locals_dict,
#if !MICROPY_PY_BUILTINS_STR_UNICODE
static mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_str,
MP_QSTR_str,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_str_make_new,
print, str_print,
binary_op, mp_obj_str_binary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objstrunicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,11 @@ static mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
}

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_str,
MP_QSTR_str,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_str_make_new,
print, uni_print,
unary_op, uni_unary_op,
Expand Down
3 changes: 2 additions & 1 deletion py/objtuple.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,11 @@ static const mp_rom_map_elem_t tuple_locals_dict_table[] = {

static MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table);

// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_tuple,
MP_QSTR_tuple,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON,
make_new, mp_obj_tuple_make_new,
print, mp_obj_tuple_print,
unary_op, mp_obj_tuple_unary_op,
Expand Down
9 changes: 3 additions & 6 deletions tests/extmod/json_dumps_extra.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# test uPy json behaviour that's not valid in CPy

try:
import json
except ImportError:
print("SKIP")
raise SystemExit
# CIRCUITPY-CHANGE: This behavior matches CPython
print("SKIP")
raise SystemExit

print(json.dumps(b"1234"))

0 comments on commit 973f597

Please sign in to comment.