diff options
-rw-r--r-- | libbb/verror_msg.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 0ef2a311f..22c30357b 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -20,6 +20,7 @@ const char *msg_eol = "\n"; void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) { char *msg, *msg1; + char stack_msg[80]; int applet_len, strerr_len, msgeol_len, used; if (!logmode) @@ -28,6 +29,27 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) if (!s) /* nomsg[_and_die] uses NULL fmt */ s = ""; /* some libc don't like printf(NULL) */ + applet_len = strlen(applet_name) + 2; /* "applet: " */ + strerr_len = strerr ? strlen(strerr) : 0; + msgeol_len = strlen(msg_eol); + + /* This costs ~90 bytes of code, but avoids costly + * malloc()[in vasprintf]+realloc()+memmove()+free() in 99% of cases. + * ~40% speedup. + */ + if ((int)sizeof(stack_msg) - applet_len > 0) { + va_list p2; + + /* It is not portable to use va_list twice, need to va_copy it */ + va_copy(p2, p); + used = vsnprintf(stack_msg + applet_len, (int)sizeof(stack_msg) - applet_len, s, p2); + va_end(p2); + msg = stack_msg; + used += applet_len; + if (used < (int)sizeof(stack_msg) - 3 - msgeol_len - strerr_len) + goto add_pfx_and_sfx; + } + used = vasprintf(&msg, s, p); if (used < 0) return; @@ -37,9 +59,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) * This is needed for e.g. httpd logging, when multiple * children can produce log messages simultaneously. */ - applet_len = strlen(applet_name) + 2; /* "applet: " */ - strerr_len = strerr ? strlen(strerr) : 0; - msgeol_len = strlen(msg_eol); /* can't use xrealloc: it calls error_msg on failure, * that may result in a recursion */ /* +3 is for ": " before strerr and for terminating NUL */ @@ -52,6 +71,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) /* TODO: maybe use writev instead of memmoving? Need full_writev? */ memmove(msg + applet_len, msg, used); used += applet_len; + add_pfx_and_sfx: strcpy(msg, applet_name); msg[applet_len - 2] = ':'; msg[applet_len - 1] = ' '; @@ -76,7 +96,8 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) syslog(syslog_level, "%s", msg + applet_len); } #endif - free(msg); + if (msg != stack_msg) + free(msg); } #ifdef VERSION_WITH_WRITEV |