mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-12-22 10:00:14 +00:00
upstream commit
Even when only writing an unescaped character, the dst buffer may need to grow, or it would be overrun; issue found by tb@ with malloc.conf(5) 'C'. While here, reserve an additional byte for the terminating NUL up front such that we don't have to realloc() later just for that. OK tb@ Upstream-ID: 30ebcc0c097c4571b16f0a78b44969f170db0cff
This commit is contained in:
parent
ac284a355f
commit
cd9e1eabeb
46
utf8.c
46
utf8.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: utf8.c,v 1.2 2016/05/30 12:05:56 schwarze Exp $ */
|
||||
/* $OpenBSD: utf8.c,v 1.3 2016/05/30 12:57:21 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
@ -33,6 +33,7 @@
|
||||
#include "utf8.h"
|
||||
|
||||
static int dangerous_locale(void);
|
||||
static int grow_dst(char **, size_t *, size_t, char **, size_t);
|
||||
static int vasnmprintf(char **, size_t, int *, const char *, va_list);
|
||||
|
||||
|
||||
@ -53,6 +54,25 @@ dangerous_locale(void) {
|
||||
return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8");
|
||||
}
|
||||
|
||||
static int
|
||||
grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need)
|
||||
{
|
||||
char *tp;
|
||||
size_t tsz;
|
||||
|
||||
if (*dp + need < *dst + *sz)
|
||||
return 0;
|
||||
tsz = *sz + 128;
|
||||
if (tsz > maxsz)
|
||||
tsz = maxsz;
|
||||
if ((tp = realloc(*dst, tsz)) == NULL)
|
||||
return -1;
|
||||
*dp = tp + (*dp - *dst);
|
||||
*dst = tp;
|
||||
*sz = tsz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following two functions limit the number of bytes written,
|
||||
* including the terminating '\0', to sz. Unless wp is NULL,
|
||||
@ -74,7 +94,6 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
|
||||
char *dp; /* Pointer into dst. */
|
||||
char *tp; /* Temporary pointer for dst. */
|
||||
size_t sz; /* Number of bytes allocated for dst. */
|
||||
size_t tsz; /* Temporary size while extending dst. */
|
||||
wchar_t wc; /* Wide character at sp. */
|
||||
int len; /* Number of bytes in the character at sp. */
|
||||
int ret; /* Number of bytes needed to format src. */
|
||||
@ -85,7 +104,7 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
|
||||
if ((ret = vasprintf(&src, fmt, ap)) <= 0)
|
||||
goto fail;
|
||||
|
||||
sz = strlen(src);
|
||||
sz = strlen(src) + 1;
|
||||
if ((dst = malloc(sz)) == NULL) {
|
||||
free(src);
|
||||
goto fail;
|
||||
@ -130,6 +149,11 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
|
||||
total_width > max_width - width))
|
||||
print = 0;
|
||||
if (print) {
|
||||
if (grow_dst(&dst, &sz, maxsz,
|
||||
&dp, len) == -1) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
total_width += width;
|
||||
memcpy(dp, sp, len);
|
||||
dp += len;
|
||||
@ -147,18 +171,10 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
|
||||
total_width > max_width - 4))
|
||||
print = 0;
|
||||
if (print) {
|
||||
if (dp + 4 >= dst + sz) {
|
||||
tsz = sz + 128;
|
||||
if (tsz > maxsz)
|
||||
tsz = maxsz;
|
||||
tp = realloc(dst, tsz);
|
||||
if (tp == NULL) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
dp = tp + (dp - dst);
|
||||
dst = tp;
|
||||
sz = tsz;
|
||||
if (grow_dst(&dst, &sz, maxsz,
|
||||
&dp, 4) == -1) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
tp = vis(dp, *sp, VIS_OCTAL | VIS_ALL, 0);
|
||||
width = tp - dp;
|
||||
|
Loading…
Reference in New Issue
Block a user