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
This commit is contained in:
Daniel Stenberg 2017-06-16 11:30:36 +02:00
parent ce2cc568f8
commit 5385450afd
10 changed files with 47 additions and 17 deletions

View file

@ -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;