From 7d58a197cffa7c0dd3686402d2e381812bb8ddeb Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Wed, 25 Sep 2019 17:53:30 +1200 Subject: [PATCH] py: Rename MP_QSTR_NULL to MP_QSTRnull to avoid intern collisions. Fixes #5140. --- ports/stm32/pin.c | 4 ++-- ports/unix/coverage-frzmpy/frzqstr.py | 3 +++ py/compile.c | 6 +++--- py/makeqstrdata.py | 2 +- py/moduerrno.c | 4 ++-- py/obj.c | 2 +- py/objexcept.c | 2 +- py/objstr.c | 6 +++--- py/objtype.c | 2 +- py/parse.c | 8 ++++---- py/parsenum.c | 2 +- py/qstr.h | 4 ++-- py/repl.c | 2 +- tests/unix/extra_coverage.py | 4 ++++ tests/unix/extra_coverage.py.exp | 1 + tools/mpy-tool.py | 2 +- 16 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 ports/unix/coverage-frzmpy/frzqstr.py diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index a8068d8998..d032d99145 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -214,14 +214,14 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t mp_print_str(print, qstr_str(mode_qst)); // pull mode - qstr pull_qst = MP_QSTR_NULL; + qstr pull_qst = MP_QSTRnull; uint32_t pull = pin_get_pull(self); if (pull == GPIO_PULLUP) { pull_qst = MP_QSTR_PULL_UP; } else if (pull == GPIO_PULLDOWN) { pull_qst = MP_QSTR_PULL_DOWN; } - if (pull_qst != MP_QSTR_NULL) { + if (pull_qst != MP_QSTRnull) { mp_printf(print, ", pull=Pin.%q", pull_qst); } diff --git a/ports/unix/coverage-frzmpy/frzqstr.py b/ports/unix/coverage-frzmpy/frzqstr.py new file mode 100644 index 0000000000..051f2a9c16 --- /dev/null +++ b/ports/unix/coverage-frzmpy/frzqstr.py @@ -0,0 +1,3 @@ +# Checks for regression on MP_QSTR_NULL +def returns_NULL(): + return "NULL" diff --git a/py/compile.c b/py/compile.c index a8ec0bf112..90d1bfd138 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1205,7 +1205,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { // do the import qstr dummy_q; do_import_name(comp, pn_import_source, &dummy_q); - EMIT_ARG(import, MP_QSTR_NULL, MP_EMIT_IMPORT_STAR); + EMIT_ARG(import, MP_QSTRnull, MP_EMIT_IMPORT_STAR); } else { EMIT_ARG(load_const_small_int, import_level); @@ -2823,7 +2823,7 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn return; } - qstr param_name = MP_QSTR_NULL; + qstr param_name = MP_QSTRnull; uint param_flag = ID_FLAG_IS_PARAM; mp_parse_node_struct_t *pns = NULL; if (MP_PARSE_NODE_IS_ID(pn)) { @@ -2882,7 +2882,7 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn } } - if (param_name != MP_QSTR_NULL) { + if (param_name != MP_QSTRnull) { id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED); if (id_info->kind != ID_INFO_KIND_UNDECIDED) { compile_syntax_error(comp, pn, "argument name reused"); diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 163b7fce75..7799be0a93 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -339,7 +339,7 @@ def print_qstr_data(qcfgs, qstrs): print('') # add NULL qstr with no hash or data - print('QDEF(MP_QSTR_NULL, (const byte*)"%s%s" "")' % ('\\x00' * cfg_bytes_hash, '\\x00' * cfg_bytes_len)) + print('QDEF(MP_QSTRnull, (const byte*)"%s%s" "")' % ('\\x00' * cfg_bytes_hash, '\\x00' * cfg_bytes_len)) # go through each qstr and print it out for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]): diff --git a/py/moduerrno.c b/py/moduerrno.c index de66c941b0..0e0a3f008d 100644 --- a/py/moduerrno.c +++ b/py/moduerrno.c @@ -104,7 +104,7 @@ qstr mp_errno_to_str(mp_obj_t errno_val) { // We have the errorcode dict so can do a lookup using the hash map mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP); if (elem == NULL) { - return MP_QSTR_NULL; + return MP_QSTRnull; } else { return MP_OBJ_QSTR_VALUE(elem->value); } @@ -115,7 +115,7 @@ qstr mp_errno_to_str(mp_obj_t errno_val) { return MP_OBJ_QSTR_VALUE(mp_module_uerrno_globals_table[i].key); } } - return MP_QSTR_NULL; + return MP_QSTRnull; #endif } diff --git a/py/obj.c b/py/obj.c index 1797ee56be..4588d896a5 100644 --- a/py/obj.c +++ b/py/obj.c @@ -93,7 +93,7 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) { #endif // the block name can be NULL if it's unknown qstr block = values[i + 2]; - if (block == MP_QSTR_NULL) { + if (block == MP_QSTRnull) { mp_print_str(print, "\n"); } else { mp_printf(print, ", in %q\n", block); diff --git a/py/objexcept.c b/py/objexcept.c index 7e3fdcc27c..dadbe98ae8 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -121,7 +121,7 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin // try to provide a nice OSError error message if (o->base.type == &mp_type_OSError && mp_obj_is_small_int(o->args->items[0])) { qstr qst = mp_errno_to_str(o->args->items[0]); - if (qst != MP_QSTR_NULL) { + if (qst != MP_QSTRnull) { mp_printf(print, "[Errno " INT_FMT "] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst); return; } diff --git a/py/objstr.c b/py/objstr.c index 1047ea94c9..8824363637 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -169,7 +169,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ // Check if a qstr with this data already exists qstr q = qstr_find_strn((const char*)str_data, str_len); - if (q != MP_QSTR_NULL) { + if (q != MP_QSTRnull) { return MP_OBJ_NEW_QSTR(q); } @@ -2042,7 +2042,7 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { // if not a bytes object, look if a qstr with this data already exists if (type == &mp_type_str) { qstr q = qstr_find_strn(vstr->buf, vstr->len); - if (q != MP_QSTR_NULL) { + if (q != MP_QSTRnull) { vstr_clear(vstr); vstr->alloc = 0; return MP_OBJ_NEW_QSTR(q); @@ -2067,7 +2067,7 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { mp_obj_t mp_obj_new_str(const char* data, size_t len) { qstr q = qstr_find_strn(data, len); - if (q != MP_QSTR_NULL) { + if (q != MP_QSTRnull) { // qstr with this data already exists return MP_OBJ_NEW_QSTR(q); } else { diff --git a/py/objtype.c b/py/objtype.c index 318c7b9a3c..236c79e6ad 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -460,7 +460,7 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } // Binary-op enum values not listed here will have the default value of 0 in the -// table, corresponding to MP_QSTR_NULL, and are therefore unsupported (a lookup will +// table, corresponding to MP_QSTRnull, and are therefore unsupported (a lookup will // fail). They can be added at the expense of code size for the qstr. // Qstrs for special methods are guaranteed to have a small value, so we use byte // type to represent them. diff --git a/py/parse.c b/py/parse.c index 254dbc7ba0..82b5413e59 100644 --- a/py/parse.c +++ b/py/parse.c @@ -502,7 +502,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) { // Don't automatically intern all strings/bytes. doc strings (which are usually large) // will be discarded by the compiler, and so we shouldn't intern them. - qstr qst = MP_QSTR_NULL; + qstr qst = MP_QSTRnull; if (lex->vstr.len <= MICROPY_ALLOC_PARSE_INTERN_STRING_LEN) { // intern short strings qst = qstr_from_strn(lex->vstr.buf, lex->vstr.len); @@ -510,7 +510,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { // check if this string is already interned qst = qstr_find_strn(lex->vstr.buf, lex->vstr.len); } - if (qst != MP_QSTR_NULL) { + if (qst != MP_QSTRnull) { // qstr exists, make a leaf node pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst); } else { @@ -705,7 +705,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, "constant must be an integer"); mp_obj_exception_add_traceback(exc, parser->lexer->source_name, - ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTR_NULL); + ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTRnull); nlr_raise(exc); } @@ -1138,7 +1138,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } // add traceback to give info about file name and location // we don't have a 'block' name, so just pass the NULL qstr to indicate this - mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL); + mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTRnull); nlr_raise(exc); } diff --git a/py/parsenum.c b/py/parsenum.c index ae9b834192..2b01b7259a 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -41,7 +41,7 @@ STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { // exception's type from ValueError to SyntaxError and add traceback info if (lex != NULL) { ((mp_obj_base_t*)MP_OBJ_TO_PTR(exc))->type = &mp_type_SyntaxError; - mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL); + mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTRnull); } nlr_raise(exc); } diff --git a/py/qstr.h b/py/qstr.h index f4375ee0e9..8153ef29fc 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -35,7 +35,7 @@ // Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx") // for qstrs that are referenced this way, but you don't want to have them in ROM. -// first entry in enum will be MP_QSTR_NULL=0, which indicates invalid/no qstr +// first entry in enum will be MP_QSTRnull=0, which indicates invalid/no qstr enum { #ifndef NO_QSTR #define QDEF(id, str) id, @@ -61,7 +61,7 @@ typedef struct _qstr_pool_t { void qstr_init(void); mp_uint_t qstr_compute_hash(const byte *data, size_t len); -qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTR_NULL if not found +qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTRnull if not found qstr qstr_from_str(const char *str); qstr qstr_from_strn(const char *str, size_t len); diff --git a/py/repl.c b/py/repl.c index da0fefb3a9..9389b34248 100644 --- a/py/repl.c +++ b/py/repl.c @@ -159,7 +159,7 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print if (str < top) { // a complete word, lookup in current object qstr q = qstr_find_strn(s_start, s_len); - if (q == MP_QSTR_NULL) { + if (q == MP_QSTRnull) { // lookup will fail return 0; } diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index cb68bae4d9..09bb48f0f1 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -74,3 +74,7 @@ except ZeroDivisionError: import uio buf = uio.resource_stream('frzstr_pkg2', 'mod.py') print(buf.read(21)) + +# test for MP_QSTR_NULL regression +from frzqstr import returns_NULL +print(returns_NULL()) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 07fde6c09c..54c5b63e2b 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -107,3 +107,4 @@ frzmpy_pkg2.mod 1 ZeroDivisionError b'# test frozen package' +NULL diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 557ee98ffe..c6f90e4f89 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -70,7 +70,7 @@ class QStrType: self.qstr_id = 'MP_QSTR_' + self.qstr_esc # Initialise global list of qstrs with static qstrs -global_qstrs = [None] # MP_QSTR_NULL should never be referenced +global_qstrs = [None] # MP_QSTRnull should never be referenced for n in qstrutil.static_qstr_list: global_qstrs.append(QStrType(n))