diff options
author | Ron Yorston <rmy@pobox.com> | 2021-08-15 13:46:35 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-08-15 14:32:09 +0100 |
commit | 39affac891d2683cf6c09901d2c3cf69bf2c95fa (patch) | |
tree | 2fc3a5c9f13289ec8541dfb94bcbc2b582c12f59 /coreutils | |
parent | fb46f0422517cba6d566131054117738e826424c (diff) | |
download | busybox-w32-39affac891d2683cf6c09901d2c3cf69bf2c95fa.tar.gz busybox-w32-39affac891d2683cf6c09901d2c3cf69bf2c95fa.tar.bz2 busybox-w32-39affac891d2683cf6c09901d2c3cf69bf2c95fa.zip |
printf: improved error handling
The printf applet is NOFORK and is used to implement the printf
command in ash. It should therefore be careful about handling
memory allocation failures.
If vasprintf() or realloc() fail the applet now carries on as best
it can. This may result in some lost output but at least the shell
will survive.
Saves 32 bytes.
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/printf.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index b5b1c6576..cc26ecd03 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -166,15 +166,29 @@ static void my_flush(void) | |||
166 | buflen = bufmax = 0; | 166 | buflen = bufmax = 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | static int my_putchar(int ch) | 169 | static void copy_to_buffer(const char *str, int len) |
170 | { | 170 | { |
171 | if (buflen + 1 >= bufmax) { | 171 | char *newbuf; |
172 | bufmax += 256; | 172 | |
173 | buffer = xrealloc(buffer, bufmax); | 173 | if (buflen + len >= bufmax) { |
174 | bufmax += 256 + len; | ||
175 | if ((newbuf = realloc(buffer, bufmax)) == NULL) { | ||
176 | my_flush(); | ||
177 | return; | ||
178 | } | ||
179 | buffer = newbuf; | ||
174 | } | 180 | } |
175 | buffer[buflen++] = ch; | 181 | memcpy(buffer + buflen, str, len); |
176 | if (buflen > 40 && ch == '\n') | 182 | buflen += len; |
183 | |||
184 | if (buflen > 40 && buffer[buflen-1] == '\n') | ||
177 | my_flush(); | 185 | my_flush(); |
186 | } | ||
187 | |||
188 | static int my_putchar(int ch) | ||
189 | { | ||
190 | char str[1] = { (char)ch }; | ||
191 | copy_to_buffer(str, 1); | ||
178 | return ch; | 192 | return ch; |
179 | } | 193 | } |
180 | 194 | ||
@@ -188,20 +202,10 @@ static int my_printf(const char *format, ...) | |||
188 | len = vasprintf(&str, format, list); | 202 | len = vasprintf(&str, format, list); |
189 | va_end(list); | 203 | va_end(list); |
190 | 204 | ||
191 | if (len < 0) | 205 | if (len >= 0) { |
192 | bb_die_memory_exhausted(); | 206 | copy_to_buffer(str, len); |
193 | 207 | free(str); | |
194 | if (buflen + len >= bufmax) { | ||
195 | bufmax += 256 + len; | ||
196 | buffer = xrealloc(buffer, bufmax); | ||
197 | } | 208 | } |
198 | memcpy(buffer + buflen, str, len); | ||
199 | buflen += len; | ||
200 | free(str); | ||
201 | |||
202 | if (buflen > 40 && buffer[buflen-1] == '\n') | ||
203 | my_flush(); | ||
204 | |||
205 | return len; | 209 | return len; |
206 | } | 210 | } |
207 | 211 | ||