Skip to content

Commit 5015779

Browse files
jimmodpgeorge
authored andcommitted
py/builtinevex: Handle invalid filenames for execfile.
If a non-string buffer was passed to execfile, then it would be passed as a non-null-terminated char* to mp_lexer_new_from_file. This changes mp_lexer_new_from_file to take a qstr instead (as in almost all cases a qstr will be created from this input anyway to set the `__file__` attribute on the module). This now makes execfile require a string (not generic buffer) argument, which is probably a good fix to make anyway. Fixes issue micropython#12522. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 480659b commit 5015779

File tree

25 files changed

+62
-46
lines changed

25 files changed

+62
-46
lines changed

extmod/vfs_reader.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ STATIC void mp_reader_vfs_close(void *data) {
6969
m_del_obj(mp_reader_vfs_t, reader);
7070
}
7171

72-
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
72+
void mp_reader_new_file(mp_reader_t *reader, qstr filename) {
7373
mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t);
7474
mp_obj_t args[2] = {
75-
mp_obj_new_str(filename, strlen(filename)),
75+
MP_OBJ_NEW_QSTR(filename),
7676
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
7777
};
7878
rf->file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map);

mpy-cross/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
7171
if (strcmp(file, "-") == 0) {
7272
lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, STDIN_FILENO, false);
7373
} else {
74-
lex = mp_lexer_new_from_file(file);
74+
lex = mp_lexer_new_from_file(qstr_from_str(file));
7575
}
7676

7777
qstr source_name;
@@ -104,7 +104,7 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
104104
vstr_add_str(&vstr, output_file);
105105
}
106106

107-
mp_raw_code_save_file(&cm, vstr_null_terminated_str(&vstr));
107+
mp_raw_code_save_file(&cm, qstr_from_strn(vstr.buf, vstr.len));
108108
vstr_clear(&vstr);
109109
}
110110

ports/esp8266/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void user_init(void) {
141141
}
142142

143143
#if !MICROPY_VFS
144-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
144+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
145145
mp_raise_OSError(MP_ENOENT);
146146
}
147147

ports/minimal/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void gc_collect(void) {
7373
}
7474
#endif
7575

76-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
76+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
7777
mp_raise_OSError(MP_ENOENT);
7878
}
7979

ports/nrf/main.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,8 @@ int main(int argc, char **argv) {
302302
#if !MICROPY_VFS
303303
#if MICROPY_MBFS
304304
// Use micro:bit filesystem
305-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
306-
return os_mbfs_new_reader(filename);
305+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
306+
return os_mbfs_new_reader(qstr_str(filename));
307307
}
308308

309309
mp_import_stat_t mp_import_stat(const char *path) {
@@ -317,7 +317,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
317317

318318
#else
319319
// use dummy functions - no filesystem available
320-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
320+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
321321
mp_raise_OSError(MP_ENOENT);
322322
}
323323

ports/pic16bit/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void gc_collect(void) {
102102
gc_collect_end();
103103
}
104104

105-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
105+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
106106
mp_raise_OSError(MP_ENOENT);
107107
}
108108

ports/powerpc/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void gc_collect(void) {
111111
gc_dump_info(&mp_plat_print);
112112
}
113113

114-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
114+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
115115
mp_raise_OSError(MP_ENOENT);
116116
}
117117

ports/qemu-arm/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ int main(int argc, char **argv) {
4141
void gc_collect(void) {
4242
}
4343

44-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
44+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
4545
mp_raise_OSError(MP_ENOENT);
4646
}
4747

ports/qemu-arm/test_main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void gc_collect(void) {
3434
gc_collect_end();
3535
}
3636

37-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
37+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
3838
mp_raise_OSError(MP_ENOENT);
3939
}
4040

ports/teensy/lexerfrozen.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ mp_import_stat_t mp_import_stat(const char *path) {
99
return MP_IMPORT_STAT_NO_EXIST;
1010
}
1111

12-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
12+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
1313
mp_raise_OSError(MP_ENOENT);
1414
}

ports/unix/main.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu
129129
const vstr_t *vstr = source;
130130
lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false);
131131
} else if (source_kind == LEX_SRC_FILENAME) {
132-
lex = mp_lexer_new_from_file((const char *)source);
132+
const char *filename = (const char *)source;
133+
lex = mp_lexer_new_from_file(qstr_from_str(filename));
133134
} else { // LEX_SRC_STDIN
134135
lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false);
135136
}

ports/webassembly/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void gc_collect(void) {
124124
}
125125

126126
#if !MICROPY_VFS
127-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
127+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
128128
mp_raise_OSError(MP_ENOENT);
129129
}
130130

ports/zephyr/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ void gc_collect(void) {
189189
}
190190

191191
#if !MICROPY_READER_VFS
192-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
192+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
193193
mp_raise_OSError(ENOENT);
194194
}
195195
#endif

py/builtinevex.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,18 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i
136136
}
137137
#endif
138138

139-
// Extract the source code.
140-
mp_buffer_info_t bufinfo;
141-
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
142139

143140
// create the lexer
144141
// MP_PARSE_SINGLE_INPUT is used to indicate a file input
145142
mp_lexer_t *lex;
146143
if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) {
147-
lex = mp_lexer_new_from_file(bufinfo.buf);
144+
lex = mp_lexer_new_from_file(mp_obj_str_get_qstr(args[0]));
148145
parse_input_kind = MP_PARSE_FILE_INPUT;
149146
} else {
147+
// Extract the source code.
148+
mp_buffer_info_t bufinfo;
149+
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
150+
150151
lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, bufinfo.buf, bufinfo.len, 0);
151152
}
152153

py/builtinimport.c

+15-8
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) {
164164
#endif
165165

166166
#if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY
167-
STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, const char *source_name) {
168-
(void)source_name;
169-
167+
STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, qstr source_name) {
170168
#if MICROPY_PY___FILE__
171-
mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(qstr_from_str(source_name)));
169+
mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
170+
#else
171+
(void)source_name;
172172
#endif
173173

174174
// execute the module in its context
@@ -224,30 +224,37 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) {
224224
if (frozen_type == MP_FROZEN_MPY) {
225225
const mp_frozen_module_t *frozen = modref;
226226
module_obj->constants = frozen->constants;
227-
do_execute_raw_code(module_obj, frozen->rc, file_str + frozen_path_prefix_len);
227+
#if MICROPY_PY___FILE__
228+
qstr frozen_file_qstr = qstr_from_str(file_str + frozen_path_prefix_len);
229+
#else
230+
qstr frozen_file_qstr = MP_QSTRnull;
231+
#endif
232+
do_execute_raw_code(module_obj, frozen->rc, frozen_file_qstr);
228233
return;
229234
}
230235
#endif
231236
}
232237

233238
#endif // MICROPY_MODULE_FROZEN
234239

240+
qstr file_qstr = qstr_from_str(file_str);
241+
235242
// If we support loading .mpy files then check if the file extension is of
236243
// the correct format and, if so, load and execute the file.
237244
#if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD
238245
if (file_str[file->len - 3] == 'm') {
239246
mp_compiled_module_t cm;
240247
cm.context = module_obj;
241-
mp_raw_code_load_file(file_str, &cm);
242-
do_execute_raw_code(cm.context, cm.rc, file_str);
248+
mp_raw_code_load_file(file_qstr, &cm);
249+
do_execute_raw_code(cm.context, cm.rc, file_qstr);
243250
return;
244251
}
245252
#endif
246253

247254
// If we can compile scripts then load the file and compile and execute it.
248255
#if MICROPY_ENABLE_COMPILER
249256
{
250-
mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
257+
mp_lexer_t *lex = mp_lexer_new_from_file(file_qstr);
251258
do_load_from_lexer(module_obj, lex);
252259
return;
253260
}

py/lexer.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -879,10 +879,10 @@ mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len
879879

880880
#if MICROPY_READER_POSIX || MICROPY_READER_VFS
881881

882-
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
882+
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
883883
mp_reader_t reader;
884884
mp_reader_new_file(&reader, filename);
885-
return mp_lexer_new(qstr_from_str(filename), reader);
885+
return mp_lexer_new(filename, reader);
886886
}
887887

888888
#if MICROPY_HELPER_LEXER_UNIX

py/lexer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len
191191

192192
// If MICROPY_READER_POSIX or MICROPY_READER_VFS aren't enabled then
193193
// this function must be implemented by the port.
194-
mp_lexer_t *mp_lexer_new_from_file(const char *filename);
194+
mp_lexer_t *mp_lexer_new_from_file(qstr filename);
195195

196196
#if MICROPY_HELPER_LEXER_UNIX
197197
mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd);

py/persistentcode.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ void mp_raw_code_load_mem(const byte *buf, size_t len, mp_compiled_module_t *con
451451

452452
#if MICROPY_HAS_FILE_READER
453453

454-
void mp_raw_code_load_file(const char *filename, mp_compiled_module_t *context) {
454+
void mp_raw_code_load_file(qstr filename, mp_compiled_module_t *context) {
455455
mp_reader_t reader;
456456
mp_reader_new_file(&reader, filename);
457457
mp_raw_code_load(&reader, context);
@@ -638,12 +638,12 @@ STATIC void fd_print_strn(void *env, const char *str, size_t len) {
638638
(void)ret;
639639
}
640640

641-
void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename) {
641+
void mp_raw_code_save_file(mp_compiled_module_t *cm, qstr filename) {
642642
MP_THREAD_GIL_EXIT();
643-
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
643+
int fd = open(qstr_str(filename), O_WRONLY | O_CREAT | O_TRUNC, 0644);
644644
MP_THREAD_GIL_ENTER();
645645
if (fd < 0) {
646-
mp_raise_OSError_with_filename(errno, filename);
646+
mp_raise_OSError_with_filename(errno, qstr_str(filename));
647647
}
648648
mp_print_t fd_print = {(void *)(intptr_t)fd, fd_print_strn};
649649
mp_raw_code_save(cm, &fd_print);

py/persistentcode.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ enum {
113113

114114
void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *ctx);
115115
void mp_raw_code_load_mem(const byte *buf, size_t len, mp_compiled_module_t *ctx);
116-
void mp_raw_code_load_file(const char *filename, mp_compiled_module_t *ctx);
116+
void mp_raw_code_load_file(qstr filename, mp_compiled_module_t *ctx);
117117

118118
void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print);
119-
void mp_raw_code_save_file(mp_compiled_module_t *cm, const char *filename);
119+
void mp_raw_code_save_file(mp_compiled_module_t *cm, qstr filename);
120120

121121
void mp_native_relocate(void *reloc, uint8_t *text, uintptr_t reloc_text);
122122

py/reader.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,12 @@ void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) {
134134

135135
#if !MICROPY_VFS_POSIX
136136
// If MICROPY_VFS_POSIX is defined then this function is provided by the VFS layer
137-
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
137+
void mp_reader_new_file(mp_reader_t *reader, qstr filename) {
138138
MP_THREAD_GIL_EXIT();
139-
int fd = open(filename, O_RDONLY, 0644);
139+
int fd = open(qstr_str(filename), O_RDONLY, 0644);
140140
MP_THREAD_GIL_ENTER();
141141
if (fd < 0) {
142-
mp_raise_OSError_with_filename(errno, filename);
142+
mp_raise_OSError_with_filename(errno, qstr_str(filename));
143143
}
144144
mp_reader_new_file_from_fd(reader, fd, true);
145145
}

py/reader.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef struct _mp_reader_t {
4040
} mp_reader_t;
4141

4242
void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len);
43-
void mp_reader_new_file(mp_reader_t *reader, const char *filename);
43+
void mp_reader_new_file(mp_reader_t *reader, qstr filename);
4444
void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd);
4545

4646
#endif // MICROPY_INCLUDED_PY_READER_H

shared/memzip/lexermemzip.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
#include "py/mperrno.h"
66
#include "memzip.h"
77

8-
mp_lexer_t *mp_lexer_new_from_file(const char *filename)
8+
mp_lexer_t *mp_lexer_new_from_file(qstr filename)
99
{
1010
void *data;
1111
size_t len;
1212

13-
if (memzip_locate(filename, &data, &len) != MZ_OK) {
13+
if (memzip_locate(qstr_str(filename), &data, &len) != MZ_OK) {
1414
mp_raise_OSError(MP_ENOENT);
1515
}
1616

17-
return mp_lexer_new_from_str_len(qstr_from_str(filename), (const char *)data, (mp_uint_t)len, 0);
17+
return mp_lexer_new_from_str_len(filename, (const char *)data, (mp_uint_t)len, 0);
1818
}
1919

shared/runtime/pyexec.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
100100
} else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) {
101101
lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source);
102102
} else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) {
103-
lex = mp_lexer_new_from_file(source);
103+
lex = mp_lexer_new_from_file(qstr_from_str(source));
104104
} else {
105105
lex = (mp_lexer_t *)source;
106106
}

tests/micropython/builtin_execfile.py

+6
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,11 @@ def open(self, file, mode):
7070
# Test execfile with a file that does exist.
7171
execfile("/test_mnt/test.py")
7272

73+
# Test that it only works with string arguments.
74+
try:
75+
execfile(b"aaa")
76+
except TypeError:
77+
print("TypeError")
78+
7379
# Unmount the VFS object.
7480
os.umount(fs)

tests/micropython/builtin_execfile.py.exp

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ open /noexist.py rb
33
OSError
44
open /test.py rb
55
123
6+
TypeError
67
umount

0 commit comments

Comments
 (0)