py/compile: Disallow 'import *' outside module level.
This check follows CPython's behaviour, because 'import *' always populates the globals with the imported names, not locals. Since it's safe to do this (doesn't lead to a crash or undefined behaviour) the check is only enabled for MICROPY_CPYTHON_COMPAT. Fixes issue #5121.
This commit is contained in:
parent
26e90a0514
commit
25a9bccdee
@ -1196,6 +1196,13 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
|
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
|
||||||
|
#if MICROPY_CPYTHON_COMPAT
|
||||||
|
if (comp->scope_cur->kind != SCOPE_MODULE) {
|
||||||
|
compile_syntax_error(comp, (mp_parse_node_t)pns, "import * not at module level");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EMIT_ARG(load_const_small_int, import_level);
|
EMIT_ARG(load_const_small_int, import_level);
|
||||||
|
|
||||||
// build the "fromlist" tuple
|
// build the "fromlist" tuple
|
||||||
|
@ -115,7 +115,7 @@ def f():
|
|||||||
# import
|
# import
|
||||||
import a
|
import a
|
||||||
from a import b
|
from a import b
|
||||||
from a import *
|
#from sys import * # tested at module scope
|
||||||
|
|
||||||
# raise
|
# raise
|
||||||
raise
|
raise
|
||||||
@ -154,3 +154,6 @@ del Class
|
|||||||
# load super method
|
# load super method
|
||||||
def f(self):
|
def f(self):
|
||||||
super().f()
|
super().f()
|
||||||
|
|
||||||
|
# import * (needs to be in module scope)
|
||||||
|
from sys import *
|
||||||
|
@ -7,7 +7,7 @@ arg names:
|
|||||||
(N_EXC_STACK 0)
|
(N_EXC_STACK 0)
|
||||||
bc=0 line=1
|
bc=0 line=1
|
||||||
########
|
########
|
||||||
bc=\\d\+ line=155
|
bc=\\d\+ line=159
|
||||||
00 MAKE_FUNCTION \.\+
|
00 MAKE_FUNCTION \.\+
|
||||||
\\d\+ STORE_NAME f
|
\\d\+ STORE_NAME f
|
||||||
\\d\+ MAKE_FUNCTION \.\+
|
\\d\+ MAKE_FUNCTION \.\+
|
||||||
@ -27,6 +27,11 @@ arg names:
|
|||||||
\\d\+ DELETE_NAME Class
|
\\d\+ DELETE_NAME Class
|
||||||
\\d\+ MAKE_FUNCTION \.\+
|
\\d\+ MAKE_FUNCTION \.\+
|
||||||
\\d\+ STORE_NAME f
|
\\d\+ STORE_NAME f
|
||||||
|
\\d\+ LOAD_CONST_SMALL_INT 0
|
||||||
|
\\d\+ LOAD_CONST_STRING '*'
|
||||||
|
\\d\+ BUILD_TUPLE 1
|
||||||
|
\\d\+ IMPORT_NAME 'sys'
|
||||||
|
\\d\+ IMPORT_STAR
|
||||||
\\d\+ LOAD_CONST_NONE
|
\\d\+ LOAD_CONST_NONE
|
||||||
\\d\+ RETURN_VALUE
|
\\d\+ RETURN_VALUE
|
||||||
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
|
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
|
||||||
@ -300,11 +305,6 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
|||||||
\\d\+ IMPORT_FROM 'b'
|
\\d\+ IMPORT_FROM 'b'
|
||||||
\\d\+ STORE_DEREF 14
|
\\d\+ STORE_DEREF 14
|
||||||
\\d\+ POP_TOP
|
\\d\+ POP_TOP
|
||||||
\\d\+ LOAD_CONST_SMALL_INT 0
|
|
||||||
\\d\+ LOAD_CONST_STRING '*'
|
|
||||||
\\d\+ BUILD_TUPLE 1
|
|
||||||
\\d\+ IMPORT_NAME 'a'
|
|
||||||
\\d\+ IMPORT_STAR
|
|
||||||
\\d\+ RAISE_LAST
|
\\d\+ RAISE_LAST
|
||||||
\\d\+ LOAD_CONST_SMALL_INT 1
|
\\d\+ LOAD_CONST_SMALL_INT 1
|
||||||
\\d\+ RAISE_OBJ
|
\\d\+ RAISE_OBJ
|
||||||
|
13
tests/import/import_star_error.py
Normal file
13
tests/import/import_star_error.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# test errors with import *
|
||||||
|
|
||||||
|
# 'import *' is not allowed in function scope
|
||||||
|
try:
|
||||||
|
exec('def foo(): from x import *')
|
||||||
|
except SyntaxError as er:
|
||||||
|
print('function', 'SyntaxError')
|
||||||
|
|
||||||
|
# 'import *' is not allowed in class scope
|
||||||
|
try:
|
||||||
|
exec('class C: from x import *')
|
||||||
|
except SyntaxError as er:
|
||||||
|
print('class', 'SyntaxError')
|
Loading…
Reference in New Issue
Block a user