In parse_token_word(), RESIZE_MALLOCED_BUFFER() was used in such a way as to ensure that there is always enough room for the final '\0' character and for a potential unquoted CTLESC or CTLNUL character (which causes an additional CTLESC to be appended to `token').
Now, by introducing a call to RESIZE_MALLOCED_BUFFER() before the extra CTLESC is appended to the `token' array, and by moving the last call to RESIZE_MALLOCED_BUFFER() from below to above the last token character assignment, this contorted connection between allocation and assignment has been reduced to a rule that is more familiar: Ensure space is allocated before attempting an assignment to that space. As an added benefit, the last RESIZE_MALLOCED_BUFFER() condition has been automatically relaxed now that a potentially unquoted CTLESC or CTLNUL character need not be speculated about; this particular benefit has been extended to the other invocations of RESIZE_MALLOCED_BUFFER() by reducing the `room' argument by 1 (in fact, this argument can now be interpreted as "the number of characters that will be immediately appended to `token'", which is a much more natural and transparent understanding). Signed-off-by: Michael Witten <mfwit...@gmail.com> --- parse.y | 36 +++++++++++++++++++++--------------- 1 files changed, 21 insertions(+), 15 deletions(-) diff --git a/parse.y b/parse.y index 38c4330..a12c4d0 100644 --- a/parse.y +++ b/parse.y @@ -4382,7 +4382,7 @@ read_token_word (character) pop_delimiter (dstack); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + RESIZE_MALLOCED_BUFFER (token, token_index, 1 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); token[token_index++] = character; strcpy (token + token_index, ttok); @@ -4408,7 +4408,7 @@ read_token_word (character) pop_delimiter (dstack); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + RESIZE_MALLOCED_BUFFER (token, token_index, 1 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); token[token_index++] = character; strcpy (token + token_index, ttok); @@ -4431,7 +4431,7 @@ read_token_word (character) pop_delimiter (dstack); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3, + RESIZE_MALLOCED_BUFFER (token, token_index, 2 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); token[token_index++] = character; @@ -4473,7 +4473,7 @@ read_token_word (character) ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3, + RESIZE_MALLOCED_BUFFER (token, token_index, 2 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); token[token_index++] = character; @@ -4524,7 +4524,7 @@ read_token_word (character) ttrans = ttok; } - RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 1, + RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); strcpy (token + token_index, ttrans); @@ -4541,7 +4541,7 @@ read_token_word (character) ttok = (char *)xmalloc (3); ttok[0] = ttok[1] = '$'; ttok[2] = '\0'; - RESIZE_MALLOCED_BUFFER (token, token_index, 3, + RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); strcpy (token + token_index, ttok); @@ -4566,7 +4566,7 @@ read_token_word (character) ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + RESIZE_MALLOCED_BUFFER (token, token_index, 1 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); token[token_index++] = character; @@ -4584,7 +4584,7 @@ read_token_word (character) { ttok = parse_compound_assignment (&ttoklen); - RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4, + RESIZE_MALLOCED_BUFFER (token, token_index, 3 + ttoklen, token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); @@ -4621,17 +4621,21 @@ read_token_word (character) got_character: if (character == CTLESC || character == CTLNUL) - token[token_index++] = CTLESC; + { + RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size, + TOKEN_DEFAULT_GROW_SIZE); + + token[token_index++] = CTLESC; + } + else + got_escaped_character: + RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size, + TOKEN_DEFAULT_GROW_SIZE); - got_escaped_character: - - all_digit_token &= DIGIT (character); - dollar_present |= character == '$'; - - token[token_index++] = character; - - RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size, - TOKEN_DEFAULT_GROW_SIZE); + token[token_index++] = character; + + all_digit_token &= DIGIT (character); + dollar_present |= character == '$'; next_character: if (character == '\n' && SHOULD_PROMPT ()) @@ -4646,6 +4650,8 @@ read_token_word (character) got_token: + /* The previous calls to RESIZE_MALLOCED_BUFFER() ensure that there + is enough space for the final null character. */ token[token_index] = '\0'; /* Check to see what thing we should return. If the last_read_token -- 1.7.4.22.g14b16.dirty