summaryrefslogtreecommitdiff
path: root/utf8.c
diff options
context:
space:
mode:
authorschwarze@openbsd.org <schwarze@openbsd.org>2016-05-30 12:57:21 +0000
committerDarren Tucker <dtucker@zip.com.au>2016-06-06 11:27:38 +1000
commitcd9e1eabeb4137182200035ab6fa4522f8d24044 (patch)
treea4428fb623a0698643942b14222740abd5e8f423 /utf8.c
parentac284a355f8065eaef2a16f446f3c44cdd17371d (diff)
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
Diffstat (limited to 'utf8.c')
-rw-r--r--utf8.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/utf8.c b/utf8.c
index caf789cee..18ee53858 100644
--- a/utf8.c
+++ b/utf8.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: utf8.c,v 1.2 2016/05/30 12:05:56 schwarze Exp $ */ 1/* $OpenBSD: utf8.c,v 1.3 2016/05/30 12:57:21 schwarze Exp $ */
2/* 2/*
3 * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> 3 * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
4 * 4 *
@@ -33,6 +33,7 @@
33#include "utf8.h" 33#include "utf8.h"
34 34
35static int dangerous_locale(void); 35static int dangerous_locale(void);
36static int grow_dst(char **, size_t *, size_t, char **, size_t);
36static int vasnmprintf(char **, size_t, int *, const char *, va_list); 37static int vasnmprintf(char **, size_t, int *, const char *, va_list);
37 38
38 39
@@ -53,6 +54,25 @@ dangerous_locale(void) {
53 return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8"); 54 return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8");
54} 55}
55 56
57static int
58grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need)
59{
60 char *tp;
61 size_t tsz;
62
63 if (*dp + need < *dst + *sz)
64 return 0;
65 tsz = *sz + 128;
66 if (tsz > maxsz)
67 tsz = maxsz;
68 if ((tp = realloc(*dst, tsz)) == NULL)
69 return -1;
70 *dp = tp + (*dp - *dst);
71 *dst = tp;
72 *sz = tsz;
73 return 0;
74}
75
56/* 76/*
57 * The following two functions limit the number of bytes written, 77 * The following two functions limit the number of bytes written,
58 * including the terminating '\0', to sz. Unless wp is NULL, 78 * 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)
74 char *dp; /* Pointer into dst. */ 94 char *dp; /* Pointer into dst. */
75 char *tp; /* Temporary pointer for dst. */ 95 char *tp; /* Temporary pointer for dst. */
76 size_t sz; /* Number of bytes allocated for dst. */ 96 size_t sz; /* Number of bytes allocated for dst. */
77 size_t tsz; /* Temporary size while extending dst. */
78 wchar_t wc; /* Wide character at sp. */ 97 wchar_t wc; /* Wide character at sp. */
79 int len; /* Number of bytes in the character at sp. */ 98 int len; /* Number of bytes in the character at sp. */
80 int ret; /* Number of bytes needed to format src. */ 99 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)
85 if ((ret = vasprintf(&src, fmt, ap)) <= 0) 104 if ((ret = vasprintf(&src, fmt, ap)) <= 0)
86 goto fail; 105 goto fail;
87 106
88 sz = strlen(src); 107 sz = strlen(src) + 1;
89 if ((dst = malloc(sz)) == NULL) { 108 if ((dst = malloc(sz)) == NULL) {
90 free(src); 109 free(src);
91 goto fail; 110 goto fail;
@@ -130,6 +149,11 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
130 total_width > max_width - width)) 149 total_width > max_width - width))
131 print = 0; 150 print = 0;
132 if (print) { 151 if (print) {
152 if (grow_dst(&dst, &sz, maxsz,
153 &dp, len) == -1) {
154 ret = -1;
155 break;
156 }
133 total_width += width; 157 total_width += width;
134 memcpy(dp, sp, len); 158 memcpy(dp, sp, len);
135 dp += len; 159 dp += len;
@@ -147,18 +171,10 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
147 total_width > max_width - 4)) 171 total_width > max_width - 4))
148 print = 0; 172 print = 0;
149 if (print) { 173 if (print) {
150 if (dp + 4 >= dst + sz) { 174 if (grow_dst(&dst, &sz, maxsz,
151 tsz = sz + 128; 175 &dp, 4) == -1) {
152 if (tsz > maxsz) 176 ret = -1;
153 tsz = maxsz; 177 break;
154 tp = realloc(dst, tsz);
155 if (tp == NULL) {
156 ret = -1;
157 break;
158 }
159 dp = tp + (dp - dst);
160 dst = tp;
161 sz = tsz;
162 } 178 }
163 tp = vis(dp, *sp, VIS_OCTAL | VIS_ALL, 0); 179 tp = vis(dp, *sp, VIS_OCTAL | VIS_ALL, 0);
164 width = tp - dp; 180 width = tp - dp;