From 61d50f717721acda3207835afb7f50a528815a8a Mon Sep 17 00:00:00 2001 From: Jim Monte Date: Mon, 27 May 2019 21:59:52 +0200 Subject: [PATCH] [PATCH #49] Ensured no buffer overrun for long script strings and improved efficiency of building string --- src/frontend/cpitf.c | 69 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c index 9d07e6fdf..b34a1d33e 100644 --- a/src/frontend/cpitf.c +++ b/src/frontend/cpitf.c @@ -395,23 +395,69 @@ cp_oddcomm(char *s, wordlist *wl) FILE *fp; if ((fp = inp_pathopen(s, "r")) != NULL) { + /* Buffer for building string, unless unusually long */ char buf[BSIZE_SP]; - wordlist *setarg; + char *p_buf_active; /* buffer in use */ + static const char header[] = "argc = %d argv = ( "; + + /* Bound on initial length: Header - 2 for %d - 1 for null + + * + 2 for closing ')' and '\0' + bound on length of int + * as string */ + size_t n_byte_data = + sizeof header / sizeof *header + 3 * sizeof(int) - 1; + (void) fclose(fp); - (void) sprintf(buf, "argc = %d argv = ( ", wl_length(wl)); - while (wl) { - (void) strcat(buf, wl->wl_word); - (void) strcat(buf, " "); - wl = wl->wl_next; + + /* Step through word list finding length */ + { + wordlist *wl1; + for (wl1 = wl; wl1 != (wordlist *) NULL; wl1 = wl1->wl_next) { + n_byte_data += strlen(wl1->wl_word) + 1; + } } - (void) strcat(buf, ")"); - setarg = cp_lexer(buf); + + /* Use fixed buffer unless it is too small */ + if (n_byte_data <= sizeof buf / sizeof *buf) { + p_buf_active = buf; + } + else { + p_buf_active = TMALLOC(char, n_byte_data); + } + + /* Step through word list again to build string */ + { + char *p_dst = p_buf_active; + p_dst += sprintf(p_dst, header, wl_length(wl)); + for ( ; wl != (wordlist *) NULL; wl = wl->wl_next) { + const char *p_src = wl->wl_word; + for ( ; ; p_src++) { /* copy source string */ + const char ch_src = *p_src; + if (ch_src == '\0') { + *p_dst++ = ' '; + break; + } + *p_dst++ = ch_src; + } /* end of loop copying source string */ + } /* end of loop over words in list */ + + /* Add ')' and terminate string */ + *p_dst++ = ')'; + *p_dst = '\0'; + } /* end of block building string */ + + wordlist *setarg = cp_lexer(p_buf_active); + + /* Free buffer allocation if made */ + if (p_buf_active != buf) { + txfree(p_buf_active); + } + com_set(setarg); wl_free(setarg); inp_source(s); cp_remvar("argc"); cp_remvar("argv"); - return (TRUE); + return TRUE; } if (wl && eq(wl->wl_word, "=")) { @@ -422,4 +468,7 @@ cp_oddcomm(char *s, wordlist *wl) } return (FALSE); -} +} /* end of function cp_oddcomm */ + + +