diff options
author | schwarze@openbsd.org <schwarze@openbsd.org> | 2016-05-30 12:05:56 +0000 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2016-06-06 11:27:38 +1000 |
commit | ac284a355f8065eaef2a16f446f3c44cdd17371d (patch) | |
tree | de00e4236e35e385771974e7daedec02a4064f0f /utf8.c | |
parent | 0e059cdf5fd86297546c63fa8607c24059118832 (diff) |
upstream commit
Fix two rare edge cases: 1. If vasprintf() returns < 0,
do not access a NULL pointer in snmprintf(), and do not free() the pointer
returned from vasprintf() because on some systems other than OpenBSD, it
might be a bogus pointer. 2. If vasprintf() returns == 0, return 0 and ""
rather than -1 and NULL.
Besides, free(dst) is pointless after failure (not a bug).
One half OK martijn@, the other half OK deraadt@;
committing quickly before people get hurt.
Upstream-ID: b7bcd2e82fc168a8eff94e41f5db336ed986fed0
Diffstat (limited to 'utf8.c')
-rw-r--r-- | utf8.c | 28 |
1 files changed, 18 insertions, 10 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: utf8.c,v 1.1 2016/05/25 23:48:45 schwarze Exp $ */ | 1 | /* $OpenBSD: utf8.c,v 1.2 2016/05/30 12:05:56 schwarze Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> | 3 | * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> |
4 | * | 4 | * |
@@ -81,13 +81,15 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap) | |||
81 | int width; /* Display width of the character wc. */ | 81 | int width; /* Display width of the character wc. */ |
82 | int total_width, max_width, print; | 82 | int total_width, max_width, print; |
83 | 83 | ||
84 | src = dst = NULL; | 84 | src = NULL; |
85 | if (vasprintf(&src, fmt, ap) <= 0) | 85 | if ((ret = vasprintf(&src, fmt, ap)) <= 0) |
86 | goto fail; | 86 | goto fail; |
87 | 87 | ||
88 | sz = strlen(src); | 88 | sz = strlen(src); |
89 | if ((dst = malloc(sz)) == NULL) | 89 | if ((dst = malloc(sz)) == NULL) { |
90 | free(src); | ||
90 | goto fail; | 91 | goto fail; |
92 | } | ||
91 | 93 | ||
92 | if (maxsz > INT_MAX) | 94 | if (maxsz > INT_MAX) |
93 | maxsz = INT_MAX; | 95 | maxsz = INT_MAX; |
@@ -191,12 +193,15 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap) | |||
191 | return ret; | 193 | return ret; |
192 | 194 | ||
193 | fail: | 195 | fail: |
194 | free(src); | ||
195 | free(dst); | ||
196 | *str = NULL; | ||
197 | if (wp != NULL) | 196 | if (wp != NULL) |
198 | *wp = 0; | 197 | *wp = 0; |
199 | return -1; | 198 | if (ret == 0) { |
199 | *str = src; | ||
200 | return 0; | ||
201 | } else { | ||
202 | *str = NULL; | ||
203 | return -1; | ||
204 | } | ||
200 | } | 205 | } |
201 | 206 | ||
202 | int | 207 | int |
@@ -209,8 +214,11 @@ snmprintf(char *str, size_t sz, int *wp, const char *fmt, ...) | |||
209 | va_start(ap, fmt); | 214 | va_start(ap, fmt); |
210 | ret = vasnmprintf(&cp, sz, wp, fmt, ap); | 215 | ret = vasnmprintf(&cp, sz, wp, fmt, ap); |
211 | va_end(ap); | 216 | va_end(ap); |
212 | (void)strlcpy(str, cp, sz); | 217 | if (cp != NULL) { |
213 | free(cp); | 218 | (void)strlcpy(str, cp, sz); |
219 | free(cp); | ||
220 | } else | ||
221 | *str = '\0'; | ||
214 | return ret; | 222 | return ret; |
215 | } | 223 | } |
216 | 224 | ||