Skip to content

Commit

Permalink
paramhlp: fix CRLF-stripping files with "-d @file"
Browse files Browse the repository at this point in the history
All CR and LF bytes should be stripped, as documented, and all other
bytes are inluded in the data. Starting now, it also excludes null bytes
as they would otherwise also cut the data short.

Reported-by: Simon K
Fixes #13063
Closes #13064
  • Loading branch information
bagder committed Mar 7, 2024
1 parent ed97fe0 commit 923f7f8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 14 deletions.
4 changes: 2 additions & 2 deletions docs/cmdline-opts/data.md
Expand Up @@ -40,8 +40,8 @@ data pieces specified are merged with a separating &-symbol. Thus, using
If you start the data with the letter @, the rest should be a filename to read
the data from, or - if you want curl to read the data from stdin. Posting data
from a file named 'foobar' would thus be done with --data @foobar. When --data
is told to read from a file like that, carriage returns and newlines are
stripped out. If you do not want the @ character to have a special
is told to read from a file like that, carriage returns, newlines and null
bytes are stripped out. If you do not want the @ character to have a special
interpretation use --data-raw instead.

The data for this option is passed on to the server exactly as provided on the
Expand Down
63 changes: 51 additions & 12 deletions src/tool_paramhlp.c
Expand Up @@ -63,6 +63,33 @@ struct getout *new_getout(struct OperationConfig *config)
return node;
}

#define ISCRLF(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0'))

/* memcrlf() has two modes. Both operate on a given memory area with
a specified size.
countcrlf FALSE - return number of bytes from the start that DO NOT include
any CR or LF or NULL
countcrlf TRUE - return number of bytes from the start that are ONLY CR or
LF or NULL.
*/
static size_t memcrlf(char *orig,
bool countcrlf, /* TRUE if we count CRLF, FALSE
if we count non-CRLF */
size_t max)
{
char *ptr = orig;
size_t total = max;
for(ptr = orig; max; max--, ptr++) {
bool crlf = ISCRLF(*ptr);
if(countcrlf ^ crlf)
return ptr - orig;
}
return total; /* no delimiter found */
}

#define MAX_FILE2STRING (256*1024*1024) /* big enough ? */

ParameterError file2string(char **bufp, FILE *file)
Expand All @@ -71,18 +98,30 @@ ParameterError file2string(char **bufp, FILE *file)
DEBUGASSERT(MAX_FILE2STRING < INT_MAX); /* needs to fit in an int later */
curlx_dyn_init(&dyn, MAX_FILE2STRING);
if(file) {
char buffer[256];

while(fgets(buffer, sizeof(buffer), file)) {
char *ptr = strchr(buffer, '\r');
if(ptr)
*ptr = '\0';
ptr = strchr(buffer, '\n');
if(ptr)
*ptr = '\0';
if(curlx_dyn_add(&dyn, buffer))
return PARAM_NO_MEM;
}
do {
char buffer[4096];
char *ptr;
size_t nread = fread(buffer, 1, sizeof(buffer), file);
if(ferror(file)) {
curlx_dyn_free(&dyn);
*bufp = NULL;
return PARAM_READ_ERROR;
}
ptr = buffer;
while(nread) {
size_t nlen = memcrlf(ptr, FALSE, nread);
if(curlx_dyn_addn(&dyn, ptr, nlen))
return PARAM_NO_MEM;
nread -= nlen;

if(nread) {
ptr += nlen;
nlen = memcrlf(ptr, TRUE, nread);
ptr += nlen;
nread -= nlen;
}
}
} while(!feof(file));
}
*bufp = curlx_dyn_ptr(&dyn);
return PARAM_OK;
Expand Down

0 comments on commit 923f7f8

Please sign in to comment.