Merge branch 'jk/vreport-sanitize'
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:56 +0000 (13:14 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:56 +0000 (13:14 -0800)
An error message with an ASCII control character like '\r' in it
can alter the message to hide its early part, which is problematic
when a remote side gives such an error message that the local side
will relay with a "remote: " prefix.

* jk/vreport-sanitize:
vreport: sanitize ASCII control chars
Revert "vreportf: avoid intermediate buffer"

1  2 
usage.c
diff --combined usage.c
index 17f52c1b5ce631eed1cdf3447d80e7223a2e6f01,50a6ccee44cd793242cc8dc4a447c3c130f447fd..ad6d2910fb58e2f27a52646bd79a0442e689517f
+++ b/usage.c
@@@ -7,21 -7,19 +7,19 @@@
  #include "cache.h"
  
  static FILE *error_handle;
- static int tweaked_error_buffering;
  
  void vreportf(const char *prefix, const char *err, va_list params)
  {
+       char msg[4096];
        FILE *fh = error_handle ? error_handle : stderr;
+       char *p;
  
-       fflush(fh);
-       if (!tweaked_error_buffering) {
-               setvbuf(fh, NULL, _IOLBF, 0);
-               tweaked_error_buffering = 1;
+       vsnprintf(msg, sizeof(msg), err, params);
+       for (p = msg; *p; p++) {
+               if (iscntrl(*p) && *p != '\t' && *p != '\n')
+                       *p = '?';
        }
-       fputs(prefix, fh);
-       vfprintf(fh, err, params);
-       fputc('\n', fh);
+       fprintf(fh, "%s%s\n", prefix, msg);
  }
  
  static NORETURN void usage_builtin(const char *err, va_list params)
@@@ -70,21 -68,6 +68,21 @@@ void set_error_routine(void (*routine)(
        error_routine = routine;
  }
  
 +void (*get_error_routine(void))(const char *err, va_list params)
 +{
 +      return error_routine;
 +}
 +
 +void set_warn_routine(void (*routine)(const char *warn, va_list params))
 +{
 +      warn_routine = routine;
 +}
 +
 +void (*get_warn_routine(void))(const char *warn, va_list params)
 +{
 +      return warn_routine;
 +}
 +
  void set_die_is_recursing_routine(int (*routine)(void))
  {
        die_is_recursing = routine;
@@@ -93,7 -76,6 +91,6 @@@
  void set_error_handle(FILE *fh)
  {
        error_handle = fh;
-       tweaked_error_buffering = 0;
  }
  
  void NORETURN usagef(const char *err, ...)
@@@ -124,11 -106,19 +121,11 @@@ void NORETURN die(const char *err, ...
        va_end(params);
  }
  
 -void NORETURN die_errno(const char *fmt, ...)
 +static const char *fmt_with_err(char *buf, int n, const char *fmt)
  {
 -      va_list params;
 -      char fmt_with_err[1024];
        char str_error[256], *err;
        int i, j;
  
 -      if (die_is_recursing()) {
 -              fputs("fatal: recursion detected in die_errno handler\n",
 -                      stderr);
 -              exit(128);
 -      }
 -
        err = strerror(errno);
        for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
                if ((str_error[j++] = err[i++]) != '%')
                }
        }
        str_error[j] = 0;
 -      snprintf(fmt_with_err, sizeof(fmt_with_err), "%s: %s", fmt, str_error);
 +      snprintf(buf, n, "%s: %s", fmt, str_error);
 +      return buf;
 +}
 +
 +void NORETURN die_errno(const char *fmt, ...)
 +{
 +      char buf[1024];
 +      va_list params;
 +
 +      if (die_is_recursing()) {
 +              fputs("fatal: recursion detected in die_errno handler\n",
 +                      stderr);
 +              exit(128);
 +      }
  
        va_start(params, fmt);
 -      die_routine(fmt_with_err, params);
 +      die_routine(fmt_with_err(buf, sizeof(buf), fmt), params);
        va_end(params);
  }
  
 +#undef error_errno
 +int error_errno(const char *fmt, ...)
 +{
 +      char buf[1024];
 +      va_list params;
 +
 +      va_start(params, fmt);
 +      error_routine(fmt_with_err(buf, sizeof(buf), fmt), params);
 +      va_end(params);
 +      return -1;
 +}
 +
  #undef error
  int error(const char *err, ...)
  {
        return -1;
  }
  
 +void warning_errno(const char *warn, ...)
 +{
 +      char buf[1024];
 +      va_list params;
 +
 +      va_start(params, warn);
 +      warn_routine(fmt_with_err(buf, sizeof(buf), warn), params);
 +      va_end(params);
 +}
 +
  void warning(const char *warn, ...)
  {
        va_list params;