1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

Use strbuf to store results in prompts_t.

UBsan pointed out another memcpy from NULL (again with length 0) in
the prompts_t system. When I looked at it, I realised that firstly
prompt_ensure_result_size was an early not-so-good implementation of
sgrowarray_nm that would benefit from being replaced with a call to
the real one, and secondly, the whole system for storing prompt
results should really have been replaced with strbufs with the no-move
option, because that's doing all the same jobs better.

So, now each prompt_t holds a strbuf in place of its previous manually
managed string. prompt_ensure_result_size is gone (the console
prompt-reading functions use strbuf_append, and everything else just
adds to the strbuf in the usual marshal.c way). New functions exist to
retrieve a prompt_t's result, either by reference or copied.
This commit is contained in:
Simon Tatham
2020-01-21 20:19:47 +00:00
parent 5891142aee
commit cd6bc14f04
10 changed files with 80 additions and 107 deletions

View File

@ -566,7 +566,6 @@ int console_get_userpass_input(prompts_t *p)
for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) {
struct termios oldmode, newmode;
int len;
prompt_t *pr = p->prompts[curr_prompt];
tcgetattr(infd, &oldmode);
@ -580,19 +579,21 @@ int console_get_userpass_input(prompts_t *p)
console_write(outfp, ptrlen_from_asciz(pr->prompt));
len = 0;
bool failed = false;
while (1) {
int ret;
size_t toread = 65536;
size_t prev_result_len = pr->result->len;
void *ptr = strbuf_append(pr->result, toread);
int ret = read(infd, ptr, toread);
prompt_ensure_result_size(pr, len * 5 / 4 + 512);
ret = read(infd, pr->result + len, pr->resultsize - len - 1);
if (ret <= 0) {
len = -1;
failed = true;
break;
}
len += ret;
if (pr->result[len - 1] == '\n') {
len--;
strbuf_shrink_to(pr->result, prev_result_len + ret);
if (pr->result->s[pr->result->len - 1] == '\n') {
strbuf_shrink_by(pr->result, 1);
break;
}
}
@ -602,12 +603,10 @@ int console_get_userpass_input(prompts_t *p)
if (!pr->echo)
console_write(outfp, PTRLEN_LITERAL("\n"));
if (len < 0) {
if (failed) {
console_close(outfp, infd);
return 0; /* failure due to read error */
}
pr->result[len] = '\0';
}
console_close(outfp, infd);

View File

@ -338,7 +338,7 @@ static char *askpass_tty(const char *prompt)
free_prompts(p);
return NULL;
} else {
char *passphrase = dupstr(p->prompts[0]->result);
char *passphrase = prompt_get_result(p->prompts[0]);
free_prompts(p);
return passphrase;
}