mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
Fix calculation of space needed for parsed words in tab completion.
Yesterday in commit d854118c8, I had a serious brain fade leading me to underestimate the number of words that the tab-completion logic could divide a line into. On input such as "(((((", each character will get seen as a separate word, which means we do indeed sometimes need more space for the words than for the original line. Fix that.
This commit is contained in:
parent
6f8cb1e234
commit
f5a4370aea
@ -3652,41 +3652,39 @@ get_previous_words(int point, char **buffer, int *nwords)
|
|||||||
{
|
{
|
||||||
char **previous_words;
|
char **previous_words;
|
||||||
char *buf;
|
char *buf;
|
||||||
int buflen;
|
char *outptr;
|
||||||
int words_found = 0;
|
int words_found = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a writable buffer including both preceding and current lines
|
* If we have anything in tab_completion_query_buf, paste it together with
|
||||||
* of the query, up to "point" which is where the currently completable
|
* rl_line_buffer to construct the full query. Otherwise we can just use
|
||||||
* word begins. Because our definition of "word" is such that a non-word
|
* rl_line_buffer as the input string.
|
||||||
* character must end each word, we can use this buffer to return the word
|
|
||||||
* data as-is, by placing a '\0' after each word.
|
|
||||||
*/
|
*/
|
||||||
buflen = point + 1;
|
if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
|
||||||
if (tab_completion_query_buf)
|
|
||||||
buflen += tab_completion_query_buf->len + 1;
|
|
||||||
*buffer = buf = pg_malloc(buflen);
|
|
||||||
i = 0;
|
|
||||||
if (tab_completion_query_buf)
|
|
||||||
{
|
{
|
||||||
memcpy(buf, tab_completion_query_buf->data,
|
i = tab_completion_query_buf->len;
|
||||||
tab_completion_query_buf->len);
|
buf = pg_malloc(point + i + 2);
|
||||||
i += tab_completion_query_buf->len;
|
memcpy(buf, tab_completion_query_buf->data, i);
|
||||||
buf[i++] = '\n';
|
buf[i++] = '\n';
|
||||||
|
memcpy(buf + i, rl_line_buffer, point);
|
||||||
|
i += point;
|
||||||
|
buf[i] = '\0';
|
||||||
|
/* Readjust point to reference appropriate offset in buf */
|
||||||
|
point = i;
|
||||||
}
|
}
|
||||||
memcpy(buf + i, rl_line_buffer, point);
|
else
|
||||||
i += point;
|
buf = rl_line_buffer;
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
/* Readjust point to reference appropriate offset in buf */
|
|
||||||
point = i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate array of word start points. There can be at most length/2 + 1
|
* Allocate an array of string pointers and a buffer to hold the strings
|
||||||
* words in the buffer.
|
* themselves. The worst case is that the line contains only
|
||||||
|
* non-whitespace WORD_BREAKS characters, making each one a separate word.
|
||||||
|
* This is usually much more space than we need, but it's cheaper than
|
||||||
|
* doing a separate malloc() for each word.
|
||||||
*/
|
*/
|
||||||
previous_words = (char **) pg_malloc((point / 2 + 1) * sizeof(char *));
|
previous_words = (char **) pg_malloc(point * sizeof(char *));
|
||||||
|
*buffer = outptr = (char *) pg_malloc(point * 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First we look for a non-word char before the current point. (This is
|
* First we look for a non-word char before the current point. (This is
|
||||||
@ -3752,14 +3750,20 @@ get_previous_words(int point, char **buffer, int *nwords)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the word located at start to end inclusive */
|
/* Return the word located at start to end inclusive */
|
||||||
previous_words[words_found] = &buf[start];
|
previous_words[words_found++] = outptr;
|
||||||
buf[end + 1] = '\0';
|
i = end - start + 1;
|
||||||
words_found++;
|
memcpy(outptr, &buf[start], i);
|
||||||
|
outptr += i;
|
||||||
|
*outptr++ = '\0';
|
||||||
|
|
||||||
/* Continue searching */
|
/* Continue searching */
|
||||||
point = start - 1;
|
point = start - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release parsing input workspace, if we made one above */
|
||||||
|
if (buf != rl_line_buffer)
|
||||||
|
free(buf);
|
||||||
|
|
||||||
*nwords = words_found;
|
*nwords = words_found;
|
||||||
return previous_words;
|
return previous_words;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user