diff options
-rw-r--r-- | utf8.c | 46 |
1 files changed, 31 insertions, 15 deletions
@@ -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 | ||
35 | static int dangerous_locale(void); | 35 | static int dangerous_locale(void); |
36 | static int grow_dst(char **, size_t *, size_t, char **, size_t); | ||
36 | static int vasnmprintf(char **, size_t, int *, const char *, va_list); | 37 | static 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 | ||
57 | static int | ||
58 | grow_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; |