diff --git a/strace.c b/strace.c index f1f634ba..64e90e71 100644 --- a/strace.c +++ b/strace.c @@ -222,14 +222,34 @@ static void die(void) static void verror_msg(int err_no, const char *fmt, va_list p) { + char *msg; + fflush(NULL); - fprintf(stderr, "%s: ", progname); - vfprintf(stderr, fmt, p); - if (err_no) - fprintf(stderr, ": %s\n", strerror(err_no)); - else - putc('\n', stderr); - fflush(stderr); + + /* We want to print entire message with single fprintf to ensure + * message integrity if stderr is shared with other programs. + * Thus we use vasprintf + single fprintf. + */ + msg = NULL; + vasprintf(&msg, fmt, p); + if (msg) { + if (err_no) + fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no)); + else + fprintf(stderr, "%s: %s\n", progname, msg); + free(msg); + } else { + /* malloc in vasprintf failed, try it without malloc */ + fprintf(stderr, "%s: ", progname); + vfprintf(stderr, fmt, p); + if (err_no) + fprintf(stderr, ": %s\n", strerror(err_no)); + else + putc('\n', stderr); + } + /* We don't switch stderr to buffered, thus fprintf(stderr) + * always flushes its output and this is not necessary: */ + /* fflush(stderr); */ } void error_msg(const char *fmt, ...)