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 Diff line number Diff line
@@ -140,7 +140,6 @@
 18.4 simultaneous parallel transfers
 18.5 provide formpost headers
 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.9 Choose the name of file in braces for complex URLs
 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
 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

 By offering different color output on the header name and the header
+27 −6
Original line number 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
 * 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;
  struct OutStruct *outs = userdata;
  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
@@ -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
   * 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)
    return failure;

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

  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 "
            "limit!\n");
      return failure;
    }
  }
  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");
      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))
    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);

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

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

#include "tool_metalink.h"

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

struct GlobalConfig;

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

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