Commit 5385450a authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

curl: prevent binary output spewed to terminal

... unless "--output -" is used. Binary detection is done by simply
checking for a binary zero in early data.

Added test 1425 1426 to verify.

Closes #1512
parent ce2cc568
Loading
Loading
Loading
Loading
+0 −6
Original line number Original line Diff line number Diff line
@@ -140,7 +140,6 @@
 18.4 simultaneous parallel transfers
 18.4 simultaneous parallel transfers
 18.5 provide formpost headers
 18.5 provide formpost headers
 18.6 warning when setting an option
 18.6 warning when setting an option
 18.7 warning when sending binary output to terminal
 18.8 offer color-coded HTTP header output
 18.8 offer color-coded HTTP header output
 18.9 Choose the name of file in braces for complex URLs
 18.9 Choose the name of file in braces for complex URLs
 18.10 improve how curl works in a windows console window
 18.10 improve how curl works in a windows console window
@@ -933,11 +932,6 @@ that doesn't exist on the server, just like --ftp-create-dirs.
 This can be useful to tell when support for a particular feature hasn't been
 This can be useful to tell when support for a particular feature hasn't been
 compiled into the library.
 compiled into the library.


18.7 warning when sending binary output to terminal

 Provide a way that prompts the user for confirmation before binary data is
 sent to the terminal, much in the style 'less' does it.

18.8 offer color-coded HTTP header output
18.8 offer color-coded HTTP header output


 By offering different color output on the header name and the header
 By offering different color output on the header name and the header
+27 −6
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *                             \___|\___/|_| \_\_____|
 *
 *
 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 *
 * This software is licensed as described in the file COPYING, which
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * you should have received as part of this distribution. The terms
@@ -77,6 +77,8 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
  size_t rc;
  size_t rc;
  struct OutStruct *outs = userdata;
  struct OutStruct *outs = userdata;
  struct OperationConfig *config = outs->config;
  struct OperationConfig *config = outs->config;
  size_t bytes = sz * nmemb;
  bool isatty = config->global->isatty;


  /*
  /*
   * Once that libcurl has called back tool_write_cb() the returned value
   * Once that libcurl has called back tool_write_cb() the returned value
@@ -84,21 +86,29 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
   * point returning a value different from sz*nmemb indicates failure.
   * point returning a value different from sz*nmemb indicates failure.
   */
   */
  const size_t failure = (sz && nmemb) ? 0 : 1;
  const size_t failure = bytes ? 0 : 1;


  if(!config)
  if(!config)
    return failure;
    return failure;


#ifdef DEBUGBUILD
#ifdef DEBUGBUILD
  {
    char *tty = curlx_getenv("CURL_ISATTY");
    if(tty) {
      isatty = TRUE;
      curl_free(tty);
    }
  }

  if(config->include_headers) {
  if(config->include_headers) {
    if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
    if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
      warnf(config->global, "Header data size exceeds single call write "
      warnf(config->global, "Header data size exceeds single call write "
            "limit!\n");
            "limit!\n");
      return failure;
      return failure;
    }
    }
  }
  }
  else {
  else {
    if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
    if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
      warnf(config->global, "Data size exceeds single call write limit!\n");
      warnf(config->global, "Data size exceeds single call write limit!\n");
      return failure;
      return failure;
    }
    }
@@ -137,11 +147,22 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
  if(!outs->stream && !tool_create_output_file(outs))
  if(!outs->stream && !tool_create_output_file(outs))
    return failure;
    return failure;


  if(isatty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
    /* binary output to terminal? */
    if(memchr(buffer, 0, bytes)) {
      warnf(config->global, "Binary output can mess up your terminal. "
            "Use \"--output -\" to tell curl to output it to your terminal "
            "anyway, or consider \"--output <FILE>\" to save to a file.\n");
      config->synthetic_error = ERR_BINARY_TERMINAL;
      return failure;
    }
  }

  rc = fwrite(buffer, sz, nmemb, outs->stream);
  rc = fwrite(buffer, sz, nmemb, outs->stream);


  if((sz * nmemb) == rc)
  if(bytes == rc)
    /* we added this amount of data to the output */
    /* we added this amount of data to the output */
    outs->bytes += (sz * nmemb);
    outs->bytes += bytes;


  if(config->readbusy) {
  if(config->readbusy) {
    config->readbusy = FALSE;
    config->readbusy = FALSE;
+9 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,12 @@


#include "tool_metalink.h"
#include "tool_metalink.h"


typedef enum {
  ERR_NONE,
  ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */
  ERR_LAST
} curl_error;

struct GlobalConfig;
struct GlobalConfig;


struct OperationConfig {
struct OperationConfig {
@@ -141,6 +147,7 @@ struct OperationConfig {
  bool insecure_ok;         /* set TRUE to allow insecure SSL connects */
  bool insecure_ok;         /* set TRUE to allow insecure SSL connects */
  bool proxy_insecure_ok;   /* set TRUE to allow insecure SSL connects
  bool proxy_insecure_ok;   /* set TRUE to allow insecure SSL connects
                               for proxy */
                               for proxy */
  bool terminal_binary_ok;
  bool verifystatus;
  bool verifystatus;
  bool create_dirs;
  bool create_dirs;
  bool ftp_create_dirs;
  bool ftp_create_dirs;
@@ -236,6 +243,8 @@ struct OperationConfig {
  double expect100timeout;
  double expect100timeout;
  bool suppress_connect_headers;  /* suppress proxy CONNECT response headers
  bool suppress_connect_headers;  /* suppress proxy CONNECT response headers
                                     from user callbacks */
                                     from user callbacks */
  curl_error synthetic_error;     /* if non-zero, it overrides any libcurl
                                     error */
  struct GlobalConfig *global;
  struct GlobalConfig *global;
  struct OperationConfig *prev;
  struct OperationConfig *prev;
  struct OperationConfig *next;   /* Always last in the struct */
  struct OperationConfig *next;   /* Always last in the struct */
+1 −1
Original line number Original line Diff line number Diff line
@@ -1554,7 +1554,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
        config->proxy_insecure_ok = toggle;
        config->proxy_insecure_ok = toggle;
        break;
        break;


      case '9':
      case '9': /* --proxy-tlsv1 */
        /* TLS version 1 for proxy */
        /* TLS version 1 for proxy */
        config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
        config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
        break;
        break;
+1 −1
Original line number Original line Diff line number Diff line
@@ -252,7 +252,7 @@ static const struct helptxt helptext[] = {
   "Use HTTP NTLM authentication"},
   "Use HTTP NTLM authentication"},
  {"    --ntlm-wb",
  {"    --ntlm-wb",
   "Use HTTP NTLM authentication with winbind"},
   "Use HTTP NTLM authentication with winbind"},
  {"    --oauth2-bearer",
  {"    --oauth2-bearer <token>",
   "OAuth 2 Bearer Token"},
   "OAuth 2 Bearer Token"},
  {"-o, --output <file>",
  {"-o, --output <file>",
   "Write to file instead of stdout"},
   "Write to file instead of stdout"},
Loading