py/repl: Don't read past the end of import_str.

asan considers that memcmp(p, q, N) is permitted to access N bytes at each
of p and q, even for values of p and q that have a difference earlier.
Accessing additional values is frequently done in practice, reading 4 or
more bytes from each input at a time for efficiency, so when completing
"non_exist<TAB>" in the repl, this causes a diagnostic:

    ==16938==ERROR: AddressSanitizer: global-buffer-overflow on
    address 0x555555cd8dc8 at pc 0x7ffff726457b bp 0x7fffffffda20 sp 0x7fff
    READ of size 9 at 0x555555cd8dc8 thread T0
        #0 0x7ffff726457a  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xb857a)
        #1 0x555555b0e82a in mp_repl_autocomplete ../../py/repl.c:301
        #2 0x555555c89585 in readline_process_char ../../lib/mp-readline/re
        #3 0x555555c8ac6e in readline ../../lib/mp-readline/readline.c:513
        #4 0x555555b8dcbd in do_repl /home/jepler/src/micropython/ports/uni
        #5 0x555555b90859 in main_ /home/jepler/src/micropython/ports/unix/
        #6 0x555555b90a3a in main /home/jepler/src/micropython/ports/unix/m
        #7 0x7ffff619a09a in __libc_start_main ../csu/libc-start.c:308
        #8 0x55555595fd69 in _start (/home/jepler/src/micropython/ports/uni

    0x555555cd8dc8 is located 0 bytes to the right of global variable
    'import_str' defined in '../../py/repl.c:285:23' (0x555555cd8dc0) of
    size 8
      'import_str' is ascii string 'import '

Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
Jeff Epler 2021-05-10 16:22:33 -05:00 committed by Damien George
parent 9a74546f8d
commit d67f4115b4

View File

@ -297,7 +297,7 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
if (q_first == 0) { if (q_first == 0) {
// If there're no better alternatives, and if it's first word // If there're no better alternatives, and if it's first word
// in the line, try to complete "import". // in the line, try to complete "import".
if (s_start == org_str && s_len > 0) { if (s_start == org_str && s_len > 0 && s_len < sizeof(import_str) - 1) {
if (memcmp(s_start, import_str, s_len) == 0) { if (memcmp(s_start, import_str, s_len) == 0) {
*compl_str = import_str + s_len; *compl_str = import_str + s_len;
return sizeof(import_str) - 1 - s_len; return sizeof(import_str) - 1 - s_len;