mirror of
https://github.com/curl/curl.git
synced 2025-09-13 23:52:42 +03:00
lib: convert Curl_get_line to use dynbuf
Create the line in a dynbuf. Aborts the reading of the file on errors. Avoids having to always allocate maximum amount from the start. Avoids direct malloc. Closes #12846
This commit is contained in:
parent
8f40b30c31
commit
142ac257b3
18
lib/altsvc.c
18
lib/altsvc.c
|
@ -209,7 +209,6 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
|
||||||
static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
char *line = NULL;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
/* we need a private copy of the file name so that the altsvc cache file
|
/* we need a private copy of the file name so that the altsvc cache file
|
||||||
|
@ -221,11 +220,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||||
|
|
||||||
fp = fopen(file, FOPEN_READTEXT);
|
fp = fopen(file, FOPEN_READTEXT);
|
||||||
if(fp) {
|
if(fp) {
|
||||||
line = malloc(MAX_ALTSVC_LINE);
|
struct dynbuf buf;
|
||||||
if(!line)
|
Curl_dyn_init(&buf, MAX_ALTSVC_LINE);
|
||||||
goto fail;
|
while(Curl_get_line(&buf, fp)) {
|
||||||
while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
|
char *lineptr = Curl_dyn_ptr(&buf);
|
||||||
char *lineptr = line;
|
|
||||||
while(*lineptr && ISBLANK(*lineptr))
|
while(*lineptr && ISBLANK(*lineptr))
|
||||||
lineptr++;
|
lineptr++;
|
||||||
if(*lineptr == '#')
|
if(*lineptr == '#')
|
||||||
|
@ -234,16 +232,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||||
|
|
||||||
altsvc_add(asi, lineptr);
|
altsvc_add(asi, lineptr);
|
||||||
}
|
}
|
||||||
free(line); /* free the line buffer */
|
Curl_dyn_free(&buf); /* free the line buffer */
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail:
|
|
||||||
Curl_safefree(asi->filename);
|
|
||||||
free(line);
|
|
||||||
fclose(fp);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
29
lib/cookie.c
29
lib/cookie.c
|
@ -1205,7 +1205,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||||
bool newsession)
|
bool newsession)
|
||||||
{
|
{
|
||||||
struct CookieInfo *c;
|
struct CookieInfo *c;
|
||||||
char *line = NULL;
|
|
||||||
FILE *handle = NULL;
|
FILE *handle = NULL;
|
||||||
|
|
||||||
if(!inc) {
|
if(!inc) {
|
||||||
|
@ -1241,16 +1240,14 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||||
|
|
||||||
c->running = FALSE; /* this is not running, this is init */
|
c->running = FALSE; /* this is not running, this is init */
|
||||||
if(fp) {
|
if(fp) {
|
||||||
|
struct dynbuf buf;
|
||||||
line = malloc(MAX_COOKIE_LINE);
|
Curl_dyn_init(&buf, MAX_COOKIE_LINE);
|
||||||
if(!line)
|
while(Curl_get_line(&buf, fp)) {
|
||||||
goto fail;
|
char *lineptr = Curl_dyn_ptr(&buf);
|
||||||
while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
|
|
||||||
char *lineptr = line;
|
|
||||||
bool headerline = FALSE;
|
bool headerline = FALSE;
|
||||||
if(checkprefix("Set-Cookie:", line)) {
|
if(checkprefix("Set-Cookie:", lineptr)) {
|
||||||
/* This is a cookie line, get it! */
|
/* This is a cookie line, get it! */
|
||||||
lineptr = &line[11];
|
lineptr += 11;
|
||||||
headerline = TRUE;
|
headerline = TRUE;
|
||||||
while(*lineptr && ISBLANK(*lineptr))
|
while(*lineptr && ISBLANK(*lineptr))
|
||||||
lineptr++;
|
lineptr++;
|
||||||
|
@ -1258,7 +1255,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||||
|
|
||||||
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
|
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
|
||||||
}
|
}
|
||||||
free(line); /* free the line buffer */
|
Curl_dyn_free(&buf); /* free the line buffer */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove expired cookies from the hash. We must make sure to run this
|
* Remove expired cookies from the hash. We must make sure to run this
|
||||||
|
@ -1274,18 +1271,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||||
c->running = TRUE; /* now, we're running */
|
c->running = TRUE; /* now, we're running */
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
fail:
|
|
||||||
free(line);
|
|
||||||
/*
|
|
||||||
* Only clean up if we allocated it here, as the original could still be in
|
|
||||||
* use by a share handle.
|
|
||||||
*/
|
|
||||||
if(!inc)
|
|
||||||
Curl_cookie_cleanup(c);
|
|
||||||
if(handle)
|
|
||||||
fclose(handle);
|
|
||||||
return NULL; /* out of memory */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -33,14 +33,16 @@
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_get_line() makes sure to only return complete whole lines that fit in
|
* Curl_get_line() makes sure to only return complete whole lines that end
|
||||||
* 'len' bytes and end with a newline.
|
* newlines.
|
||||||
*/
|
*/
|
||||||
char *Curl_get_line(char *buf, int len, FILE *input)
|
int Curl_get_line(struct dynbuf *buf, FILE *input)
|
||||||
{
|
{
|
||||||
bool partial = FALSE;
|
CURLcode result;
|
||||||
|
char buffer[128];
|
||||||
|
Curl_dyn_reset(buf);
|
||||||
while(1) {
|
while(1) {
|
||||||
char *b = fgets(buf, len, input);
|
char *b = fgets(buffer, sizeof(buffer), input);
|
||||||
|
|
||||||
if(b) {
|
if(b) {
|
||||||
size_t rlen = strlen(b);
|
size_t rlen = strlen(b);
|
||||||
|
@ -48,39 +50,28 @@ char *Curl_get_line(char *buf, int len, FILE *input)
|
||||||
if(!rlen)
|
if(!rlen)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(b[rlen-1] == '\n') {
|
result = Curl_dyn_addn(buf, b, rlen);
|
||||||
/* b is \n terminated */
|
if(result)
|
||||||
if(partial) {
|
/* too long line or out of memory */
|
||||||
partial = FALSE;
|
return 0; /* error */
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
else if(feof(input)) {
|
|
||||||
if(partial)
|
|
||||||
/* Line is already too large to return, ignore rest */
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(rlen + 1 < (size_t) len) {
|
else if(b[rlen-1] == '\n')
|
||||||
/* b is EOF terminated, insert missing \n */
|
/* end of the line */
|
||||||
b[rlen] = '\n';
|
return 1; /* all good */
|
||||||
b[rlen + 1] = '\0';
|
|
||||||
return b;
|
else if(feof(input)) {
|
||||||
}
|
/* append a newline */
|
||||||
else
|
result = Curl_dyn_addn(buf, "\n", 1);
|
||||||
/* Maximum buffersize reached + EOF
|
if(result)
|
||||||
* This line is impossible to add a \n to so we'll ignore it
|
/* too long line or out of memory */
|
||||||
*/
|
return 0; /* error */
|
||||||
break;
|
return 1; /* all good */
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* Maximum buffersize reached */
|
|
||||||
partial = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* if not disabled */
|
#endif /* if not disabled */
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/* get_line() makes sure to only return complete whole lines that fit in 'len'
|
#include "dynbuf.h"
|
||||||
* bytes and end with a newline. */
|
|
||||||
char *Curl_get_line(char *buf, int len, FILE *input);
|
/* Curl_get_line() returns complete lines that end with a newline. */
|
||||||
|
int Curl_get_line(struct dynbuf *buf, FILE *input);
|
||||||
|
|
||||||
#endif /* HEADER_CURL_GET_LINE_H */
|
#endif /* HEADER_CURL_GET_LINE_H */
|
||||||
|
|
17
lib/hsts.c
17
lib/hsts.c
|
@ -511,7 +511,6 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
|
||||||
static CURLcode hsts_load(struct hsts *h, const char *file)
|
static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
char *line = NULL;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
/* we need a private copy of the file name so that the hsts cache file
|
/* we need a private copy of the file name so that the hsts cache file
|
||||||
|
@ -523,11 +522,10 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||||
|
|
||||||
fp = fopen(file, FOPEN_READTEXT);
|
fp = fopen(file, FOPEN_READTEXT);
|
||||||
if(fp) {
|
if(fp) {
|
||||||
line = malloc(MAX_HSTS_LINE);
|
struct dynbuf buf;
|
||||||
if(!line)
|
Curl_dyn_init(&buf, MAX_HSTS_LINE);
|
||||||
goto fail;
|
while(Curl_get_line(&buf, fp)) {
|
||||||
while(Curl_get_line(line, MAX_HSTS_LINE, fp)) {
|
char *lineptr = Curl_dyn_ptr(&buf);
|
||||||
char *lineptr = line;
|
|
||||||
while(*lineptr && ISBLANK(*lineptr))
|
while(*lineptr && ISBLANK(*lineptr))
|
||||||
lineptr++;
|
lineptr++;
|
||||||
if(*lineptr == '#')
|
if(*lineptr == '#')
|
||||||
|
@ -536,15 +534,10 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
|
||||||
|
|
||||||
hsts_add(h, lineptr);
|
hsts_add(h, lineptr);
|
||||||
}
|
}
|
||||||
free(line); /* free the line buffer */
|
Curl_dyn_free(&buf); /* free the line buffer */
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail:
|
|
||||||
Curl_safefree(h->filename);
|
|
||||||
fclose(fp);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
10
lib/netrc.c
10
lib/netrc.c
|
@ -53,6 +53,8 @@ enum host_lookup_state {
|
||||||
#define NETRC_FAILED -1
|
#define NETRC_FAILED -1
|
||||||
#define NETRC_SUCCESS 0
|
#define NETRC_SUCCESS 0
|
||||||
|
|
||||||
|
#define MAX_NETRC_LINE 4096
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns zero on success.
|
* Returns zero on success.
|
||||||
*/
|
*/
|
||||||
|
@ -80,13 +82,14 @@ static int parsenetrc(const char *host,
|
||||||
file = fopen(netrcfile, FOPEN_READTEXT);
|
file = fopen(netrcfile, FOPEN_READTEXT);
|
||||||
if(file) {
|
if(file) {
|
||||||
bool done = FALSE;
|
bool done = FALSE;
|
||||||
char netrcbuffer[4096];
|
struct dynbuf buf;
|
||||||
int netrcbuffsize = (int)sizeof(netrcbuffer);
|
Curl_dyn_init(&buf, MAX_NETRC_LINE);
|
||||||
|
|
||||||
while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
|
while(!done && Curl_get_line(&buf, file)) {
|
||||||
char *tok;
|
char *tok;
|
||||||
char *tok_end;
|
char *tok_end;
|
||||||
bool quoted;
|
bool quoted;
|
||||||
|
char *netrcbuffer = Curl_dyn_ptr(&buf);
|
||||||
if(state == MACDEF) {
|
if(state == MACDEF) {
|
||||||
if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
|
if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
|
||||||
state = NOTHING;
|
state = NOTHING;
|
||||||
|
@ -245,6 +248,7 @@ static int parsenetrc(const char *host,
|
||||||
} /* while Curl_get_line() */
|
} /* while Curl_get_line() */
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
Curl_dyn_free(&buf);
|
||||||
if(!retcode) {
|
if(!retcode) {
|
||||||
/* success */
|
/* success */
|
||||||
if(login_alloc) {
|
if(login_alloc) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ static const char *filecontents[] = {
|
||||||
"LINE1\n"
|
"LINE1\n"
|
||||||
C4096 "SOME EXTRA TEXT",
|
C4096 "SOME EXTRA TEXT",
|
||||||
|
|
||||||
/* First and third line should be read */
|
/* Only first should be read */
|
||||||
"LINE1\n"
|
"LINE1\n"
|
||||||
C4096 "SOME EXTRA TEXT\n"
|
C4096 "SOME EXTRA TEXT\n"
|
||||||
"LINE3\n",
|
"LINE3\n",
|
||||||
|
@ -84,11 +84,13 @@ static const char *filecontents[] = {
|
||||||
|
|
||||||
UNITTEST_START
|
UNITTEST_START
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int rc = 0;
|
||||||
for(i = 0; i < NUMTESTS; i++) {
|
for(i = 0; i < NUMTESTS; i++) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[4096];
|
struct dynbuf buf;
|
||||||
int len = 4096;
|
int len = 4096;
|
||||||
char *line;
|
char *line;
|
||||||
|
Curl_dyn_init(&buf, len);
|
||||||
|
|
||||||
fp = fopen(arg, "wb");
|
fp = fopen(arg, "wb");
|
||||||
abort_unless(fp != NULL, "Cannot open testfile");
|
abort_unless(fp != NULL, "Cannot open testfile");
|
||||||
|
@ -101,65 +103,73 @@ UNITTEST_START
|
||||||
fprintf(stderr, "Test %zd...", i);
|
fprintf(stderr, "Test %zd...", i);
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 0:
|
case 0:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\n", line),
|
fail_unless(line && !strcmp("LINE1\n", line),
|
||||||
"First line failed (1)");
|
"First line failed (1)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE2 NEWLINE\n", line),
|
fail_unless(line && !strcmp("LINE2 NEWLINE\n", line),
|
||||||
"Second line failed (1)");
|
"Second line failed (1)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
abort_unless(line == NULL, "Missed EOF (1)");
|
abort_unless(!Curl_dyn_len(&buf), "Missed EOF (1)");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\n", line),
|
fail_unless(line && !strcmp("LINE1\n", line),
|
||||||
"First line failed (2)");
|
"First line failed (2)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE2 NONEWLINE\n", line),
|
fail_unless(line && !strcmp("LINE2 NONEWLINE\n", line),
|
||||||
"Second line failed (2)");
|
"Second line failed (2)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
abort_unless(line == NULL, "Missed EOF (2)");
|
abort_unless(!Curl_dyn_len(&buf), "Missed EOF (2)");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\n", line),
|
fail_unless(line && !strcmp("LINE1\n", line),
|
||||||
"First line failed (3)");
|
"First line failed (3)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
fail_unless(line == NULL,
|
fail_unless(!Curl_dyn_len(&buf),
|
||||||
"Did not detect max read on EOF (3)");
|
"Did not detect max read on EOF (3)");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\n", line),
|
fail_unless(line && !strcmp("LINE1\n", line),
|
||||||
"First line failed (4)");
|
"First line failed (4)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
fail_unless(line == NULL,
|
fail_unless(!Curl_dyn_len(&buf),
|
||||||
"Did not ignore partial on EOF (4)");
|
"Did not ignore partial on EOF (4)");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\n", line),
|
fail_unless(line && !strcmp("LINE1\n", line),
|
||||||
"First line failed (5)");
|
"First line failed (5)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
fail_unless(line && !strcmp("LINE3\n", line),
|
fail_unless(!Curl_dyn_len(&buf),
|
||||||
"Third line failed (5)");
|
"Did not bail out on too long line");
|
||||||
line = Curl_get_line(buf, len, fp);
|
|
||||||
abort_unless(line == NULL, "Missed EOF (5)");
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
|
line = Curl_dyn_ptr(&buf);
|
||||||
fail_unless(line && !strcmp("LINE1\x1aTEST\n", line),
|
fail_unless(line && !strcmp("LINE1\x1aTEST\n", line),
|
||||||
"Missed/Misinterpreted ^Z (6)");
|
"Missed/Misinterpreted ^Z (6)");
|
||||||
line = Curl_get_line(buf, len, fp);
|
rc = Curl_get_line(&buf, fp);
|
||||||
abort_unless(line == NULL, "Missed EOF (6)");
|
abort_unless(!Curl_dyn_len(&buf), "Missed EOF (6)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort_unless(1, "Unknown case");
|
abort_unless(1, "Unknown case");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Curl_dyn_free(&buf);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fprintf(stderr, "OK\n");
|
fprintf(stderr, "OK\n");
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
UNITTEST_STOP
|
UNITTEST_STOP
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
|
Loading…
Reference in New Issue
Block a user