From 39affac891d2683cf6c09901d2c3cf69bf2c95fa Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 15 Aug 2021 13:46:35 +0100 Subject: 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. --- coreutils/printf.c | 42 +++++++++++++++++++++++------------------- 1 file 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) buflen = bufmax = 0; } -static int my_putchar(int ch) +static void copy_to_buffer(const char *str, int len) { - if (buflen + 1 >= bufmax) { - bufmax += 256; - buffer = xrealloc(buffer, bufmax); + char *newbuf; + + if (buflen + len >= bufmax) { + bufmax += 256 + len; + if ((newbuf = realloc(buffer, bufmax)) == NULL) { + my_flush(); + return; + } + buffer = newbuf; } - buffer[buflen++] = ch; - if (buflen > 40 && ch == '\n') + memcpy(buffer + buflen, str, len); + buflen += len; + + if (buflen > 40 && buffer[buflen-1] == '\n') my_flush(); +} + +static int my_putchar(int ch) +{ + char str[1] = { (char)ch }; + copy_to_buffer(str, 1); return ch; } @@ -188,20 +202,10 @@ static int my_printf(const char *format, ...) len = vasprintf(&str, format, list); va_end(list); - if (len < 0) - bb_die_memory_exhausted(); - - if (buflen + len >= bufmax) { - bufmax += 256 + len; - buffer = xrealloc(buffer, bufmax); + if (len >= 0) { + copy_to_buffer(str, len); + free(str); } - memcpy(buffer + buflen, str, len); - buflen += len; - free(str); - - if (buflen > 40 && buffer[buflen-1] == '\n') - my_flush(); - return len; } -- cgit v1.2.3-55-g6feb