Skip to content

Commit 25a9bcc

Browse files
encukoudpgeorge
authored andcommitted
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 adafruit#5121.
1 parent 26e90a0 commit 25a9bcc

4 files changed

Lines changed: 30 additions & 7 deletions

File tree

py/compile.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,13 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
11961196
} while (0);
11971197

11981198
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
1199+
#if MICROPY_CPYTHON_COMPAT
1200+
if (comp->scope_cur->kind != SCOPE_MODULE) {
1201+
compile_syntax_error(comp, (mp_parse_node_t)pns, "import * not at module level");
1202+
return;
1203+
}
1204+
#endif
1205+
11991206
EMIT_ARG(load_const_small_int, import_level);
12001207

12011208
// build the "fromlist" tuple

tests/cmdline/cmd_showbc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def closure():
115115
# import
116116
import a
117117
from a import b
118-
from a import *
118+
#from sys import * # tested at module scope
119119

120120
# raise
121121
raise
@@ -154,3 +154,6 @@ class Class:
154154
# load super method
155155
def f(self):
156156
super().f()
157+
158+
# import * (needs to be in module scope)
159+
from sys import *

tests/cmdline/cmd_showbc.py.exp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ arg names:
77
(N_EXC_STACK 0)
88
bc=0 line=1
99
########
10-
bc=\\d\+ line=155
10+
bc=\\d\+ line=159
1111
00 MAKE_FUNCTION \.\+
1212
\\d\+ STORE_NAME f
1313
\\d\+ MAKE_FUNCTION \.\+
@@ -27,6 +27,11 @@ arg names:
2727
\\d\+ DELETE_NAME Class
2828
\\d\+ MAKE_FUNCTION \.\+
2929
\\d\+ STORE_NAME f
30+
\\d\+ LOAD_CONST_SMALL_INT 0
31+
\\d\+ LOAD_CONST_STRING '*'
32+
\\d\+ BUILD_TUPLE 1
33+
\\d\+ IMPORT_NAME 'sys'
34+
\\d\+ IMPORT_STAR
3035
\\d\+ LOAD_CONST_NONE
3136
\\d\+ RETURN_VALUE
3237
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
@@ -300,11 +305,6 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
300305
\\d\+ IMPORT_FROM 'b'
301306
\\d\+ STORE_DEREF 14
302307
\\d\+ POP_TOP
303-
\\d\+ LOAD_CONST_SMALL_INT 0
304-
\\d\+ LOAD_CONST_STRING '*'
305-
\\d\+ BUILD_TUPLE 1
306-
\\d\+ IMPORT_NAME 'a'
307-
\\d\+ IMPORT_STAR
308308
\\d\+ RAISE_LAST
309309
\\d\+ LOAD_CONST_SMALL_INT 1
310310
\\d\+ RAISE_OBJ

tests/import/import_star_error.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# test errors with import *
2+
3+
# 'import *' is not allowed in function scope
4+
try:
5+
exec('def foo(): from x import *')
6+
except SyntaxError as er:
7+
print('function', 'SyntaxError')
8+
9+
# 'import *' is not allowed in class scope
10+
try:
11+
exec('class C: from x import *')
12+
except SyntaxError as er:
13+
print('class', 'SyntaxError')

0 commit comments

Comments
 (0)