aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-08-15 13:46:35 +0100
committerRon Yorston <rmy@pobox.com>2021-08-15 14:32:09 +0100
commit39affac891d2683cf6c09901d2c3cf69bf2c95fa (patch)
tree2fc3a5c9f13289ec8541dfb94bcbc2b582c12f59
parentfb46f0422517cba6d566131054117738e826424c (diff)
downloadbusybox-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.
-rw-r--r--coreutils/printf.c42
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
169static int my_putchar(int ch) 169static 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
188static 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