upstream: switch percent_expand() to use sshbuf instead of a limited

fixed buffer; ok markus@

OpenBSD-Commit-ID: 3f9ef20bca5ef5058b48c1cac67c53b9a1d15711
This commit is contained in:
djm@openbsd.org 2019-08-16 06:13:15 +00:00 committed by Damien Miller
parent 9ab5b94747
commit e3b6c966b7

39
misc.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.139 2019/06/28 13:35:04 deraadt Exp $ */ /* $OpenBSD: misc.c,v 1.140 2019/08/16 06:13:15 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -1049,13 +1049,18 @@ char *
percent_expand(const char *string, ...) percent_expand(const char *string, ...)
{ {
#define EXPAND_MAX_KEYS 16 #define EXPAND_MAX_KEYS 16
u_int num_keys, i, j; u_int num_keys, i;
struct { struct {
const char *key; const char *key;
const char *repl; const char *repl;
} keys[EXPAND_MAX_KEYS]; } keys[EXPAND_MAX_KEYS];
char buf[4096]; struct sshbuf *buf;
va_list ap; va_list ap;
int r;
char *ret;
if ((buf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Gather keys */ /* Gather keys */
va_start(ap, string); va_start(ap, string);
@ -1072,14 +1077,13 @@ percent_expand(const char *string, ...)
va_end(ap); va_end(ap);
/* Expand string */ /* Expand string */
*buf = '\0';
for (i = 0; *string != '\0'; string++) { for (i = 0; *string != '\0'; string++) {
if (*string != '%') { if (*string != '%') {
append: append:
buf[i++] = *string; if ((r = sshbuf_put_u8(buf, *string)) != 0) {
if (i >= sizeof(buf)) fatal("%s: sshbuf_put_u8: %s",
fatal("%s: string too long", __func__); __func__, ssh_err(r));
buf[i] = '\0'; }
continue; continue;
} }
string++; string++;
@ -1088,18 +1092,23 @@ percent_expand(const char *string, ...)
goto append; goto append;
if (*string == '\0') if (*string == '\0')
fatal("%s: invalid format", __func__); fatal("%s: invalid format", __func__);
for (j = 0; j < num_keys; j++) { for (i = 0; i < num_keys; i++) {
if (strchr(keys[j].key, *string) != NULL) { if (strchr(keys[i].key, *string) != NULL) {
i = strlcat(buf, keys[j].repl, sizeof(buf)); if ((r = sshbuf_put(buf, keys[i].repl,
if (i >= sizeof(buf)) strlen(keys[i].repl))) != 0) {
fatal("%s: string too long", __func__); fatal("%s: sshbuf_put: %s",
__func__, ssh_err(r));
}
break; break;
} }
} }
if (j >= num_keys) if (i >= num_keys)
fatal("%s: unknown key %%%c", __func__, *string); fatal("%s: unknown key %%%c", __func__, *string);
} }
return (xstrdup(buf)); if ((ret = sshbuf_dup_string(buf)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
sshbuf_free(buf);
return ret;
#undef EXPAND_MAX_KEYS #undef EXPAND_MAX_KEYS
} }