From b0edec61ac2eeb3bb5c787639ea0cecaa71ea79d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 10 May 2014 17:48:46 +0100 Subject: [PATCH] stmhal: Improve handling of out-of-memory in REPL. Addresses issue #558, but it's likely that other out-of-memory errors could crash the pyboard. Reason is that qstrs use m_new and can raise an exception within the parser. --- stmhal/pyexec.c | 12 ++++++++++-- stmhal/readline.c | 19 ++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c index 166f0a6d15..45928427e1 100644 --- a/stmhal/pyexec.c +++ b/stmhal/pyexec.c @@ -163,7 +163,11 @@ raw_repl_reset: } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0); - parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false); + if (lex == NULL) { + printf("MemoryError\n"); + } else { + parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false); + } // indicate end of output with EOF character stdout_tx_str("\004"); @@ -239,7 +243,11 @@ friendly_repl_reset: } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0); - parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true); + if (lex == NULL) { + printf("MemoryError\n"); + } else { + parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true); + } } } diff --git a/stmhal/readline.c b/stmhal/readline.c index fa04f8a49d..d40bd4219b 100644 --- a/stmhal/readline.c +++ b/stmhal/readline.c @@ -55,11 +55,13 @@ void readline_init(void) { memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char*)); } -STATIC char *str_dup(const char *str) { +STATIC char *str_dup_maybe(const char *str) { uint32_t len = strlen(str); - char *s2 = m_new(char, len + 1); - memcpy(s2, str, len); - s2[len] = 0; + char *s2 = m_new_maybe(char, len + 1); + if (s2 == NULL) { + return NULL; + } + memcpy(s2, str, len + 1); return s2; } @@ -92,10 +94,13 @@ int readline(vstr_t *line, const char *prompt) { if (line->len > orig_line_len && (readline_hist[0] == NULL || strcmp(readline_hist[0], line->buf + orig_line_len) != 0)) { // a line which is not empty and different from the last one // so update the history - for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { - readline_hist[i] = readline_hist[i - 1]; + char *most_recent_hist = str_dup_maybe(line->buf + orig_line_len); + if (most_recent_hist != NULL) { + for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { + readline_hist[i] = readline_hist[i - 1]; + } + readline_hist[0] = most_recent_hist; } - readline_hist[0] = str_dup(line->buf + orig_line_len); } return 0; } else if (c == 27) {