mirror of
https://github.com/curl/curl.git
synced 2025-09-09 21:52:40 +03:00
strparse: switch to curl_off_t as base data type
- add hex and octal parsers to the Curl_str_* family - make curlx_strtoofft use these parsers - remove all use of strtol() and strtoul() in library code - generally use Curl_str_* more than strtoofft, for stricter parsing - supports 64-bit universally, instead of 'long' which differs in size between platforms Extended the unit test 1664 to verify hex and octal parsing. Closes #16336
This commit is contained in:
parent
876db1070b
commit
b4538ec522
|
@ -3,3 +3,5 @@ banfunc strncpy
|
|||
banfunc sscanf
|
||||
banfunc snprintf
|
||||
banfunc vsnprint
|
||||
banfunc strtoul
|
||||
banfunc strtol
|
||||
|
|
|
@ -226,6 +226,7 @@ LIB_CFILES = \
|
|||
splay.c \
|
||||
strcase.c \
|
||||
strdup.c \
|
||||
strequal.c \
|
||||
strerror.c \
|
||||
strparse.c \
|
||||
strtok.c \
|
||||
|
|
23
lib/altsvc.c
23
lib/altsvc.c
|
@ -159,10 +159,10 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line)
|
|||
struct Curl_str srcalpn;
|
||||
struct Curl_str dstalpn;
|
||||
struct Curl_str date;
|
||||
size_t srcport;
|
||||
size_t dstport;
|
||||
size_t persist;
|
||||
size_t prio;
|
||||
curl_off_t srcport;
|
||||
curl_off_t dstport;
|
||||
curl_off_t persist;
|
||||
curl_off_t prio;
|
||||
|
||||
if(Curl_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
|
||||
Curl_str_singlespace(&line) ||
|
||||
|
@ -193,8 +193,8 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line)
|
|||
memcpy(dbuf, date.str, date.len);
|
||||
dbuf[date.len] = 0;
|
||||
expires = Curl_getdate_capped(dbuf);
|
||||
as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn, srcport,
|
||||
dstport);
|
||||
as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn,
|
||||
(size_t)srcport, (size_t)dstport);
|
||||
if(as) {
|
||||
as->expires = expires;
|
||||
as->prio = 0; /* not supported to just set zero */
|
||||
|
@ -465,10 +465,11 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
|
|||
return */
|
||||
static time_t altsvc_debugtime(void *unused)
|
||||
{
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
const char *timestr = getenv("CURL_TIME");
|
||||
(void)unused;
|
||||
if(timestr) {
|
||||
long val = strtol(timestr, NULL, 10);
|
||||
curl_off_t val;
|
||||
Curl_str_number(×tr, &val, TIME_T_MAX);
|
||||
return (time_t)val;
|
||||
}
|
||||
return time(NULL);
|
||||
|
@ -528,7 +529,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
|||
size_t dstlen = 0; /* destination hostname length */
|
||||
const char *value_ptr;
|
||||
char option[32];
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
bool quoted = FALSE;
|
||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||
bool persist = FALSE;
|
||||
|
@ -566,7 +567,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
|||
dstlen = strlen(srchost);
|
||||
}
|
||||
if(*p == ':') {
|
||||
size_t port = 0;
|
||||
curl_off_t port = 0;
|
||||
p++;
|
||||
if(Curl_str_number(&p, &port, 0xffff) || (*p != '\"')) {
|
||||
infof(data, "Unknown alt-svc port number, ignoring.");
|
||||
|
@ -617,7 +618,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
|||
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
|
||||
p++;
|
||||
}
|
||||
if(!Curl_str_number(&value_ptr, &num, SIZE_T_MAX)) {
|
||||
if(!Curl_str_number(&value_ptr, &num, TIME_T_MAX)) {
|
||||
if(strcasecompare("ma", option))
|
||||
maxage = (time_t)num;
|
||||
else if(strcasecompare("persist", option) && (num == 1))
|
||||
|
|
|
@ -742,7 +742,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
|||
Curl_printable_address. The latter returns only numeric scope
|
||||
IDs and the former returns none at all. So the scope ID, if
|
||||
present, is known to be numeric */
|
||||
size_t scope_id;
|
||||
curl_off_t scope_id;
|
||||
if(Curl_str_number((const char **)&scope_ptr, &scope_id, UINT_MAX))
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
si6->sin6_scope_id = (unsigned int)scope_id;
|
||||
|
@ -974,28 +974,28 @@ static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
|
|||
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_DBG_SOCK_WBLOCK");
|
||||
const char *p = getenv("CURL_DBG_SOCK_WBLOCK");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 100))
|
||||
ctx->wblock_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_WPARTIAL");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 100))
|
||||
ctx->wpartial_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_RBLOCK");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 100))
|
||||
ctx->rblock_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_RMAX");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, SIZE_T_MAX))
|
||||
ctx->recv_max = (size_t)l;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "progress.h"
|
||||
#include "select.h"
|
||||
#include "warnless.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -883,11 +884,11 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
|||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
const char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
write_len = CURLMIN(write_len, altsize);
|
||||
curl_off_t altsize;
|
||||
if(!Curl_str_number(&p, &altsize, SIZE_T_MAX))
|
||||
write_len = CURLMIN(write_len, (size_t)altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "strcase.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -682,10 +683,10 @@ static void cpool_close_and_destroy_all(struct cpool *cpool)
|
|||
/* Just for testing, run graceful shutdown */
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
|
||||
const char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l > 0 && l < INT_MAX)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, INT_MAX))
|
||||
timeout_ms = (int)l;
|
||||
}
|
||||
}
|
||||
|
|
31
lib/cookie.c
31
lib/cookie.c
|
@ -80,7 +80,6 @@ Example set of cookies:
|
|||
#include "sendf.h"
|
||||
#include "slist.h"
|
||||
#include "share.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "curl_get_line.h"
|
||||
#include "curl_memrchr.h"
|
||||
|
@ -89,6 +88,7 @@ Example set of cookies:
|
|||
#include "fopen.h"
|
||||
#include "strdup.h"
|
||||
#include "llist.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -708,21 +708,22 @@ parse_cookie_header(struct Curl_easy *data,
|
|||
* client should discard the cookie. A value of zero means the
|
||||
* cookie should be discarded immediately.
|
||||
*/
|
||||
CURLofft offt;
|
||||
int rc;
|
||||
const char *maxage = valuep;
|
||||
offt = curlx_strtoofft((*maxage == '\"') ?
|
||||
&maxage[1] : &maxage[0], NULL, 10,
|
||||
&co->expires);
|
||||
switch(offt) {
|
||||
case CURL_OFFT_FLOW:
|
||||
if(*maxage == '\"')
|
||||
maxage++;
|
||||
rc = Curl_str_number(&maxage, &co->expires, CURL_OFF_T_MAX);
|
||||
|
||||
switch(rc) {
|
||||
case STRE_OVERFLOW:
|
||||
/* overflow, used max value */
|
||||
co->expires = CURL_OFF_T_MAX;
|
||||
break;
|
||||
case CURL_OFFT_INVAL:
|
||||
default:
|
||||
/* negative or otherwise bad, expire */
|
||||
co->expires = 1;
|
||||
break;
|
||||
case CURL_OFFT_OK:
|
||||
case STRE_OK:
|
||||
if(!co->expires)
|
||||
/* already expired */
|
||||
co->expires = 1;
|
||||
|
@ -915,16 +916,8 @@ parse_netscape(struct Cookie *co,
|
|||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
char *endp;
|
||||
const char *p;
|
||||
/* make sure curlx_strtoofft won't read past the current field */
|
||||
for(p = ptr; p < &ptr[len] && ISDIGIT(*p); ++p)
|
||||
;
|
||||
if(p == ptr || p != &ptr[len] ||
|
||||
curlx_strtoofft(ptr, &endp, 10, &co->expires) || endp != &ptr[len])
|
||||
return CERR_RANGE;
|
||||
}
|
||||
if(Curl_str_number(&ptr, &co->expires, CURL_OFF_T_MAX))
|
||||
return CERR_RANGE;
|
||||
break;
|
||||
case 5:
|
||||
co->name = Curl_memdup0(ptr, len);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
|
||||
#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
|
||||
#define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
|
||||
#define ISODIGIT(x) (((x) >= '0') && ((x) <= '7'))
|
||||
#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
|
||||
#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
|
||||
#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <curl/curl.h>
|
||||
#include "curl_range.h"
|
||||
#include "sendf.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* Only include this function if one or more of FTP, FILE are enabled. */
|
||||
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
|
||||
|
@ -37,28 +37,29 @@
|
|||
*/
|
||||
CURLcode Curl_range(struct Curl_easy *data)
|
||||
{
|
||||
curl_off_t from, to;
|
||||
char *ptr;
|
||||
char *ptr2;
|
||||
|
||||
if(data->state.use_range && data->state.range) {
|
||||
CURLofft from_t;
|
||||
CURLofft to_t;
|
||||
from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
|
||||
if(from_t == CURL_OFFT_FLOW)
|
||||
curl_off_t from, to;
|
||||
bool first_num = TRUE;
|
||||
const char *p = data->state.range;
|
||||
if(Curl_str_number(&p, &from, CURL_OFF_T_MAX))
|
||||
first_num = FALSE;
|
||||
|
||||
if(Curl_str_single(&p, '-'))
|
||||
/* no leading dash or after the first number is an error */
|
||||
return CURLE_RANGE_ERROR;
|
||||
while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
|
||||
ptr++;
|
||||
to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
|
||||
if(to_t == CURL_OFFT_FLOW)
|
||||
return CURLE_RANGE_ERROR;
|
||||
if((to_t == CURL_OFFT_INVAL) && !from_t) {
|
||||
|
||||
if(Curl_str_number(&p, &to, CURL_OFF_T_MAX)) {
|
||||
/* no second number */
|
||||
/* X - */
|
||||
data->state.resume_from = from;
|
||||
DEBUGF(infof(data, "RANGE %" FMT_OFF_T " to end of file", from));
|
||||
}
|
||||
else if((from_t == CURL_OFFT_INVAL) && !to_t) {
|
||||
else if(!first_num) {
|
||||
/* -Y */
|
||||
if(!to)
|
||||
/* "-0" is just wrong */
|
||||
return CURLE_RANGE_ERROR;
|
||||
|
||||
data->req.maxdownload = to;
|
||||
data->state.resume_from = -to;
|
||||
DEBUGF(infof(data, "RANGE the last %" FMT_OFF_T " bytes", to));
|
||||
|
|
27
lib/ftp.c
27
lib/ftp.c
|
@ -54,7 +54,6 @@
|
|||
#include "ftplistparser.h"
|
||||
#include "curl_range.h"
|
||||
#include "curl_krb5.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
|
@ -473,7 +472,7 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
|
|||
r += pp->nfinal;
|
||||
|
||||
if(LASTLINE(r)) {
|
||||
size_t status;
|
||||
curl_off_t status;
|
||||
if(!Curl_str_number(&r, &status, 999) && (status == 226)) {
|
||||
/* funny timing situation where we get the final message on the
|
||||
control connection before traffic on the data connection has been
|
||||
|
@ -544,7 +543,7 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
|
|||
static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
|
||||
const char *line, size_t len, int *code)
|
||||
{
|
||||
size_t status;
|
||||
curl_off_t status;
|
||||
(void)data;
|
||||
(void)conn;
|
||||
|
||||
|
@ -929,8 +928,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(ip_end) {
|
||||
const char *portp = strchr(ip_end, ':');
|
||||
if(portp) {
|
||||
size_t start;
|
||||
size_t end;
|
||||
curl_off_t start;
|
||||
curl_off_t end;
|
||||
portp++;
|
||||
if(!Curl_str_number(&portp, &start, 0xffff)) {
|
||||
/* got the first number */
|
||||
|
@ -1767,7 +1766,7 @@ static bool match_pasv_6nums(const char *p,
|
|||
{
|
||||
int i;
|
||||
for(i = 0; i < 6; i++) {
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
if(i) {
|
||||
if(*p != ',')
|
||||
return FALSE;
|
||||
|
@ -1805,11 +1804,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
|||
ptr++;
|
||||
/* |||12345| */
|
||||
sep = ptr[0];
|
||||
/* the ISDIGIT() check here is because strtoul() accepts leading minus
|
||||
etc */
|
||||
if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
|
||||
const char *p = &ptr[3];
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
if(Curl_str_number(&p, &num, 0xffff) || (*p != sep)) {
|
||||
failf(data, "Illegal port number in EPSV reply");
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
|
@ -2297,7 +2294,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
|
|||
for all the digits at the end of the response and parse only those as a
|
||||
number. */
|
||||
char *start = &buf[4];
|
||||
char *fdigit = memchr(start, '\r', len);
|
||||
const char *fdigit = memchr(start, '\r', len);
|
||||
if(fdigit) {
|
||||
fdigit--;
|
||||
if(*fdigit == '\n')
|
||||
|
@ -2307,9 +2304,8 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
|
|||
}
|
||||
else
|
||||
fdigit = start;
|
||||
/* ignores parsing errors, which will make the size remain unknown */
|
||||
(void)curlx_strtoofft(fdigit, NULL, 10, &filesize);
|
||||
|
||||
if(Curl_str_number(&fdigit, &filesize, CURL_OFF_T_MAX))
|
||||
filesize = -1; /* size remain unknown */
|
||||
}
|
||||
else if(ftpcode == 550) { /* "No such file or directory" */
|
||||
/* allow a SIZE failure for (resumed) uploads, when probing what command
|
||||
|
@ -2471,7 +2467,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
|||
* those cases only confuses us.
|
||||
*
|
||||
* Example D above makes this parsing a little tricky */
|
||||
char *bytes;
|
||||
const char *bytes;
|
||||
char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
|
||||
bytes = strstr(buf, " bytes");
|
||||
if(bytes) {
|
||||
|
@ -2493,7 +2489,8 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
|||
if(bytes) {
|
||||
++bytes;
|
||||
/* get the number! */
|
||||
(void)curlx_strtoofft(bytes, NULL, 10, &size);
|
||||
if(Curl_str_number(&bytes, &size, CURL_OFF_T_MAX))
|
||||
size = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -547,7 +547,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
|||
parser->item_length ++;
|
||||
if(c == ' ') {
|
||||
const char *p = &mem[parser->item_offset];
|
||||
size_t hlinks;
|
||||
curl_off_t hlinks;
|
||||
mem[parser->item_offset + parser->item_length - 1] = 0;
|
||||
|
||||
if(!Curl_str_number(&p, &hlinks, LONG_MAX)) {
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
|
||||
#include "urldata.h"
|
||||
#include "getinfo.h"
|
||||
|
||||
#include "vtls/vtls.h"
|
||||
#include "connect.h" /* Curl_getconnectinfo() */
|
||||
#include "progress.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
|
@ -204,9 +204,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
|||
} lptr;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
const char *timestr = getenv("CURL_TIME");
|
||||
if(timestr) {
|
||||
unsigned long val = strtoul(timestr, NULL, 10);
|
||||
curl_off_t val;
|
||||
Curl_str_number(×tr, &val, TIME_T_MAX);
|
||||
switch(info) {
|
||||
case CURLINFO_LOCAL_PORT:
|
||||
*param_longp = (long)val;
|
||||
|
@ -218,7 +219,8 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
|||
/* use another variable for this to allow different values */
|
||||
timestr = getenv("CURL_DEBUG_SIZE");
|
||||
if(timestr) {
|
||||
unsigned long val = strtoul(timestr, NULL, 10);
|
||||
curl_off_t val;
|
||||
Curl_str_number(×tr, &val, LONG_MAX);
|
||||
switch(info) {
|
||||
case CURLINFO_HEADER_SIZE:
|
||||
case CURLINFO_REQUEST_SIZE:
|
||||
|
@ -379,9 +381,11 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
|
|||
curl_off_t *param_offt)
|
||||
{
|
||||
#ifdef DEBUGBUILD
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
const char *timestr = getenv("CURL_TIME");
|
||||
if(timestr) {
|
||||
unsigned long val = strtoul(timestr, NULL, 10);
|
||||
curl_off_t val;
|
||||
Curl_str_number(×tr, &val, CURL_OFF_T_MAX);
|
||||
|
||||
switch(info) {
|
||||
case CURLINFO_TOTAL_TIME_T:
|
||||
case CURLINFO_NAMELOOKUP_TIME_T:
|
||||
|
@ -476,9 +480,11 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
|
|||
double *param_doublep)
|
||||
{
|
||||
#ifdef DEBUGBUILD
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
const char *timestr = getenv("CURL_TIME");
|
||||
if(timestr) {
|
||||
unsigned long val = strtoul(timestr, NULL, 10);
|
||||
curl_off_t val;
|
||||
Curl_str_number(×tr, &val, CURL_OFF_T_MAX);
|
||||
|
||||
switch(info) {
|
||||
case CURLINFO_TOTAL_TIME:
|
||||
case CURLINFO_NAMELOOKUP_TIME:
|
||||
|
|
13
lib/hostip.c
13
lib/hostip.c
|
@ -1134,7 +1134,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
|
|||
if(!hostp->data)
|
||||
continue;
|
||||
if(hostp->data[0] == '-') {
|
||||
size_t num = 0;
|
||||
curl_off_t num = 0;
|
||||
size_t entry_len;
|
||||
size_t hlen = 0;
|
||||
host_end = strchr(&hostp->data[1], ':');
|
||||
|
@ -1173,7 +1173,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
|
|||
const char *addr_begin;
|
||||
const char *addr_end;
|
||||
const char *port_ptr;
|
||||
size_t port = 0;
|
||||
curl_off_t port = 0;
|
||||
const char *end_ptr;
|
||||
bool permanent = TRUE;
|
||||
bool error = TRUE;
|
||||
|
@ -1273,8 +1273,8 @@ err:
|
|||
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
|
||||
|
||||
if(dns) {
|
||||
infof(data, "RESOLVE %.*s:%zd - old addresses discarded",
|
||||
(int)hlen, host_begin, port);
|
||||
infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T
|
||||
" - old addresses discarded", (int)hlen, host_begin, port);
|
||||
/* delete old entry, there are two reasons for this
|
||||
1. old entry may have different addresses.
|
||||
2. even if entry with correct addresses is already in the cache,
|
||||
|
@ -1306,14 +1306,15 @@ err:
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
infof(data, "Added %.*s:%zd:%s to DNS cache%s",
|
||||
infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s",
|
||||
(int)hlen, host_begin, port, addresses,
|
||||
permanent ? "" : " (non-permanent)");
|
||||
#endif
|
||||
|
||||
/* Wildcard hostname */
|
||||
if((hlen == 1) && (host_begin[0] == '*')) {
|
||||
infof(data, "RESOLVE *:%zd using wildcard", port);
|
||||
infof(data, "RESOLVE *:%" CURL_FORMAT_CURL_OFF_T " using wildcard",
|
||||
port);
|
||||
data->state.wildcard_resolve = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
19
lib/hsts.c
19
lib/hsts.c
|
@ -35,7 +35,6 @@
|
|||
#include "curl_get_line.h"
|
||||
#include "strcase.h"
|
||||
#include "sendf.h"
|
||||
#include "strtoofft.h"
|
||||
#include "parsedate.h"
|
||||
#include "fopen.h"
|
||||
#include "rename.h"
|
||||
|
@ -59,13 +58,12 @@
|
|||
time_t deltatime; /* allow for "adjustments" for unit test purposes */
|
||||
static time_t hsts_debugtime(void *unused)
|
||||
{
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
const char *timestr = getenv("CURL_TIME");
|
||||
(void)unused;
|
||||
if(timestr) {
|
||||
curl_off_t val;
|
||||
(void)curlx_strtoofft(timestr, NULL, 10, &val);
|
||||
|
||||
val += (curl_off_t)deltatime;
|
||||
if(!Curl_str_number(×tr, &val, TIME_T_MAX))
|
||||
val += (curl_off_t)deltatime;
|
||||
return (time_t)val;
|
||||
}
|
||||
return time(NULL);
|
||||
|
@ -160,8 +158,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
|
|||
p++;
|
||||
if(strncasecompare("max-age", p, 7)) {
|
||||
bool quoted = FALSE;
|
||||
CURLofft offt;
|
||||
char *endp;
|
||||
int rc;
|
||||
|
||||
if(gotma)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
@ -178,13 +175,13 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
|
|||
p++;
|
||||
quoted = TRUE;
|
||||
}
|
||||
offt = curlx_strtoofft(p, &endp, 10, &expires);
|
||||
if(offt == CURL_OFFT_FLOW)
|
||||
rc = Curl_str_number(&p, &expires, TIME_T_MAX);
|
||||
if(rc == STRE_OVERFLOW)
|
||||
expires = CURL_OFF_T_MAX;
|
||||
else if(offt)
|
||||
else if(rc)
|
||||
/* invalid max-age */
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
p = endp;
|
||||
|
||||
if(quoted) {
|
||||
if(*p != '\"')
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
|
10
lib/http.c
10
lib/http.c
|
@ -86,6 +86,7 @@
|
|||
#include "hsts.h"
|
||||
#include "ws.h"
|
||||
#include "curl_ctype.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -3072,11 +3073,10 @@ static CURLcode http_header(struct Curl_easy *data,
|
|||
|
||||
/* if it truly stopped on a digit */
|
||||
if(ISDIGIT(*ptr)) {
|
||||
if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
|
||||
if(data->state.resume_from == k->offset)
|
||||
/* we asked for a resume and we got it */
|
||||
k->content_range = TRUE;
|
||||
}
|
||||
if(!Curl_str_number(&ptr, &k->offset, CURL_OFF_T_MAX) &&
|
||||
(data->state.resume_from == k->offset))
|
||||
/* we asked for a resume and we got it */
|
||||
k->content_range = TRUE;
|
||||
}
|
||||
else if(k->httpcode < 300)
|
||||
data->state.resume_from = 0; /* get everything */
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
#include "socks.h"
|
||||
#include "imap.h"
|
||||
#include "mime.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strparse.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
|
@ -1156,9 +1156,9 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
|
|||
the continuation data contained within the curly brackets */
|
||||
ptr = memchr(ptr, '{', len);
|
||||
if(ptr) {
|
||||
char *endptr;
|
||||
if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size) &&
|
||||
(endptr - ptr > 1 && *endptr == '}'))
|
||||
ptr++;
|
||||
if(!Curl_str_number(&ptr, &size, CURL_OFF_T_MAX) &&
|
||||
!Curl_str_single(&ptr, '}'))
|
||||
parsed = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -728,7 +728,9 @@ static void _ldap_trace(const char *fmt, ...)
|
|||
|
||||
if(do_trace == -1) {
|
||||
const char *env = getenv("CURL_TRACE");
|
||||
do_trace = (env && strtol(env, NULL, 10) > 0);
|
||||
curl_off_t e = 0;
|
||||
if(!Curl_str_number(&env, &e, INT_MAX))
|
||||
do_trace = e > 0;
|
||||
}
|
||||
if(!do_trace)
|
||||
return;
|
||||
|
|
|
@ -560,7 +560,9 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
|||
#ifdef CURL_OPENLDAP_DEBUG
|
||||
if(do_trace < 0) {
|
||||
const char *env = getenv("CURL_OPENLDAP_TRACE");
|
||||
do_trace = (env && strtol(env, NULL, 10) > 0);
|
||||
curl_off_t e = 0;
|
||||
if(!Curl_str_number(&env, &e, INT_MAX))
|
||||
do_trace = e > 0;
|
||||
}
|
||||
if(do_trace)
|
||||
ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace);
|
||||
|
|
|
@ -420,7 +420,7 @@ static int parsedate(const char *date, time_t *output)
|
|||
date = end;
|
||||
}
|
||||
else {
|
||||
size_t lval;
|
||||
curl_off_t lval;
|
||||
int num_digits = 0;
|
||||
const char *p = date;
|
||||
if(Curl_str_number(&p, &lval, 99999999))
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "sendf.h"
|
||||
#include "transfer.h"
|
||||
#include "url.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -194,11 +195,11 @@ static CURLcode xfer_send(struct Curl_easy *data,
|
|||
/* Allow debug builds to override this logic to force short initial
|
||||
sends */
|
||||
size_t body_len = blen - hds_len;
|
||||
char *p = getenv("CURL_SMALLREQSEND");
|
||||
const char *p = getenv("CURL_SMALLREQSEND");
|
||||
if(p) {
|
||||
size_t body_small = (size_t)strtoul(p, NULL, 10);
|
||||
if(body_small && body_small < body_len)
|
||||
blen = hds_len + body_small;
|
||||
curl_off_t body_small;
|
||||
if(!Curl_str_number(&p, &body_small, body_len))
|
||||
blen = hds_len + (size_t)body_small;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -926,7 +926,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len)
|
|||
CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
|
||||
{
|
||||
if(checkprefix("CSeq:", header)) {
|
||||
size_t CSeq = 0;
|
||||
curl_off_t CSeq = 0;
|
||||
struct RTSP *rtsp = data->req.p.rtsp;
|
||||
const char *p = &header[5];
|
||||
while(ISBLANK(*p))
|
||||
|
@ -1007,7 +1007,7 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport)
|
|||
start++;
|
||||
end = strchr(start, ';');
|
||||
if(checkprefix("interleaved=", start)) {
|
||||
size_t chan1, chan2, chan;
|
||||
curl_off_t chan1, chan2, chan;
|
||||
const char *p = start + 12;
|
||||
if(!Curl_str_number(&p, &chan1, 255)) {
|
||||
unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
|
||||
|
|
|
@ -215,7 +215,7 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
|
|||
only send the response code instead as per Section 4.2. */
|
||||
if(line[3] == ' ' || len == 5) {
|
||||
char tmpline[6];
|
||||
size_t code;
|
||||
curl_off_t code;
|
||||
const char *p = tmpline;
|
||||
result = TRUE;
|
||||
memcpy(tmpline, line, (len == 5 ? 5 : 3));
|
||||
|
|
|
@ -82,65 +82,6 @@ char Curl_raw_tolower(char in)
|
|||
return (char)tolowermap[(unsigned char) in];
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_strequal() is for doing "raw" case insensitive strings. This is meant
|
||||
* to be locale independent and only compare strings we know are safe for
|
||||
* this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
|
||||
* further explanations as to why this function is necessary.
|
||||
*/
|
||||
|
||||
static int casecompare(const char *first, const char *second)
|
||||
{
|
||||
while(*first) {
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
||||
/* get out of the loop as soon as they do not match */
|
||||
return 0;
|
||||
first++;
|
||||
second++;
|
||||
}
|
||||
/* If we are here either the strings are the same or the length is different.
|
||||
We can just test if the "current" character is non-zero for one and zero
|
||||
for the other. Note that the characters may not be exactly the same even
|
||||
if they match, we only want to compare zero-ness. */
|
||||
return !*first == !*second;
|
||||
}
|
||||
|
||||
/* --- public function --- */
|
||||
int curl_strequal(const char *first, const char *second)
|
||||
{
|
||||
if(first && second)
|
||||
/* both pointers point to something then compare them */
|
||||
return casecompare(first, second);
|
||||
|
||||
/* if both pointers are NULL then treat them as equal */
|
||||
return NULL == first && NULL == second;
|
||||
}
|
||||
|
||||
static int ncasecompare(const char *first, const char *second, size_t max)
|
||||
{
|
||||
while(*first && max) {
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
||||
return 0;
|
||||
max--;
|
||||
first++;
|
||||
second++;
|
||||
}
|
||||
if(0 == max)
|
||||
return 1; /* they are equal this far */
|
||||
|
||||
return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
|
||||
}
|
||||
|
||||
/* --- public function --- */
|
||||
int curl_strnequal(const char *first, const char *second, size_t max)
|
||||
{
|
||||
if(first && second)
|
||||
/* both pointers point to something then compare them */
|
||||
return ncasecompare(first, second, max);
|
||||
|
||||
/* if both pointers are NULL then treat them as equal if max is non-zero */
|
||||
return NULL == first && NULL == second && max;
|
||||
}
|
||||
/* Copy an upper case version of the string from src to dest. The
|
||||
* strings may overlap. No more than n characters of the string are copied
|
||||
* (including any NUL) and the destination string will NOT be
|
||||
|
|
88
lib/strequal.c
Normal file
88
lib/strequal.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 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
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "strcase.h"
|
||||
|
||||
/*
|
||||
* curl_strequal() is for doing "raw" case insensitive strings. This is meant
|
||||
* to be locale independent and only compare strings we know are safe for
|
||||
* this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
|
||||
* further explanations as to why this function is necessary.
|
||||
*/
|
||||
|
||||
static int casecompare(const char *first, const char *second)
|
||||
{
|
||||
while(*first) {
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
||||
/* get out of the loop as soon as they do not match */
|
||||
return 0;
|
||||
first++;
|
||||
second++;
|
||||
}
|
||||
/* If we are here either the strings are the same or the length is different.
|
||||
We can just test if the "current" character is non-zero for one and zero
|
||||
for the other. Note that the characters may not be exactly the same even
|
||||
if they match, we only want to compare zero-ness. */
|
||||
return !*first == !*second;
|
||||
}
|
||||
|
||||
static int ncasecompare(const char *first, const char *second, size_t max)
|
||||
{
|
||||
while(*first && max) {
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
||||
return 0;
|
||||
max--;
|
||||
first++;
|
||||
second++;
|
||||
}
|
||||
if(0 == max)
|
||||
return 1; /* they are equal this far */
|
||||
|
||||
return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
|
||||
}
|
||||
|
||||
/* --- public function --- */
|
||||
int curl_strequal(const char *first, const char *second)
|
||||
{
|
||||
if(first && second)
|
||||
/* both pointers point to something then compare them */
|
||||
return casecompare(first, second);
|
||||
|
||||
/* if both pointers are NULL then treat them as equal */
|
||||
return NULL == first && NULL == second;
|
||||
}
|
||||
|
||||
/* --- public function --- */
|
||||
int curl_strnequal(const char *first, const char *second, size_t max)
|
||||
{
|
||||
if(first && second)
|
||||
/* both pointers point to something then compare them */
|
||||
return ncasecompare(first, second, max);
|
||||
|
||||
/* if both pointers are NULL then treat them as equal if max is non-zero */
|
||||
return NULL == first && NULL == second && max;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
***************************************************************************/
|
||||
|
||||
#include "strparse.h"
|
||||
#include "strcase.h"
|
||||
|
||||
/* Get a word until the first DELIM or end of string. At least one byte long.
|
||||
return non-zero on error */
|
||||
|
@ -103,28 +104,64 @@ int Curl_str_singlespace(const char **linep)
|
|||
return Curl_str_single(linep, ' ');
|
||||
}
|
||||
|
||||
/* Get an unsigned number. Leading zeroes are accepted.
|
||||
return non-zero on error */
|
||||
int Curl_str_number(const char **linep, size_t *nump, size_t max)
|
||||
/* given an ASCII hexadecimal character, return the value */
|
||||
#define HEXDIGIT2NUM(x) \
|
||||
(((x) > '9') ? Curl_raw_tolower(x) - 'a' + 10 : x - '0')
|
||||
|
||||
/* given an ASCII character and a given base, return TRUE if valid */
|
||||
#define valid_digit(digit, base) \
|
||||
(((base == 10) && ISDIGIT(digit)) || \
|
||||
((base == 16) && ISXDIGIT(digit)) || \
|
||||
((base == 8) && ISODIGIT(digit)))
|
||||
|
||||
/* given an ASCII character and a given base, return the value */
|
||||
#define num_digit(digit, base) \
|
||||
((base != 16) ? digit - '0' : HEXDIGIT2NUM(digit))
|
||||
|
||||
/* no support for 0x prefix nor leading spaces */
|
||||
static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
|
||||
int base) /* 8, 10 or 16, nothing else */
|
||||
{
|
||||
size_t num = 0;
|
||||
curl_off_t num = 0;
|
||||
DEBUGASSERT(linep && *linep && nump);
|
||||
DEBUGASSERT((base == 8) || (base == 10) || (base == 16));
|
||||
*nump = 0;
|
||||
if(!ISDIGIT(**linep))
|
||||
if(!valid_digit(**linep, base))
|
||||
return STRE_NO_NUM;
|
||||
do {
|
||||
int n = **linep - '0';
|
||||
if(num > ((SIZE_T_MAX - n) / 10))
|
||||
int n = num_digit(**linep, base);
|
||||
if(num > ((CURL_OFF_T_MAX - n) / base))
|
||||
return STRE_OVERFLOW;
|
||||
num = num * 10 + n;
|
||||
num = num * base + n;
|
||||
if(num > max)
|
||||
return STRE_BIG; /** too big */
|
||||
(*linep)++;
|
||||
} while(ISDIGIT(**linep));
|
||||
} while(valid_digit(**linep, base));
|
||||
*nump = num;
|
||||
return STRE_OK;
|
||||
}
|
||||
|
||||
/* Get an unsigned decimal number with no leading space or minus. Leading
|
||||
zeroes are accepted. return non-zero on error */
|
||||
int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max)
|
||||
{
|
||||
return str_num_base(linep, nump, max, 10);
|
||||
}
|
||||
|
||||
/* Get an unsigned hexadecimal number with no leading space or minus and no
|
||||
"0x" support. Leading zeroes are accepted. return non-zero on error */
|
||||
int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max)
|
||||
{
|
||||
return str_num_base(linep, nump, max, 16);
|
||||
}
|
||||
|
||||
/* Get an unsigned octal number with no leading space or minus and no "0"
|
||||
prefix support. Leading zeroes are accepted. return non-zero on error */
|
||||
int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
|
||||
{
|
||||
return str_num_base(linep, nump, max, 8);
|
||||
}
|
||||
|
||||
/* CR or LF
|
||||
return non-zero on error */
|
||||
int Curl_str_newline(const char **linep)
|
||||
|
|
|
@ -62,9 +62,14 @@ int Curl_str_single(const char **linep, char byte);
|
|||
return non-zero on error */
|
||||
int Curl_str_singlespace(const char **linep);
|
||||
|
||||
/* Get an unsigned number
|
||||
return non-zero on error */
|
||||
int Curl_str_number(const char **linep, size_t *nump, size_t max);
|
||||
/* Get an unsigned decimal number. Return non-zero on error */
|
||||
int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max);
|
||||
|
||||
/* Get an unsigned hexadecimal number. Return non-zero on error */
|
||||
int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max);
|
||||
|
||||
/* Get an unsigned octal number. Return non-zero on error */
|
||||
int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max);
|
||||
|
||||
/* Check for CR or LF
|
||||
return non-zero on error */
|
||||
|
|
208
lib/strtoofft.c
208
lib/strtoofft.c
|
@ -22,216 +22,36 @@
|
|||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "strtoofft.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
|
||||
* could use in case strtoll() does not exist... See
|
||||
* https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
|
||||
*/
|
||||
|
||||
#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
|
||||
# ifdef HAVE_STRTOLL
|
||||
# define strtooff strtoll
|
||||
# else
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# if defined(_SAL_VERSION)
|
||||
_Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
|
||||
_In_z_ const char *_String,
|
||||
_Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
|
||||
# else
|
||||
_CRTIMP __int64 __cdecl _strtoi64(const char *_String,
|
||||
char **_EndPtr, int _Radix);
|
||||
# endif
|
||||
# define strtooff _strtoi64
|
||||
# else
|
||||
# define PRIVATE_STRTOOFF 1
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define strtooff strtol
|
||||
#endif
|
||||
|
||||
#ifdef PRIVATE_STRTOOFF
|
||||
|
||||
/* Range tests can be used for alphanum decoding if characters are consecutive,
|
||||
like in ASCII. Else an array is scanned. Determine this condition now. */
|
||||
|
||||
#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
|
||||
|
||||
#define NO_RANGE_TEST
|
||||
|
||||
static const char valchars[] =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
#endif
|
||||
|
||||
static int get_char(char c, int base);
|
||||
|
||||
/**
|
||||
* Custom version of the strtooff function. This extracts a curl_off_t
|
||||
* value from the given input string and returns it.
|
||||
*/
|
||||
static curl_off_t strtooff(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
char *end;
|
||||
bool is_negative = FALSE;
|
||||
bool overflow = FALSE;
|
||||
int i;
|
||||
curl_off_t value = 0;
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
end = (char *)nptr;
|
||||
while(ISBLANK(end[0])) {
|
||||
end++;
|
||||
}
|
||||
|
||||
/* Handle the sign, if any. */
|
||||
if(end[0] == '-') {
|
||||
is_negative = TRUE;
|
||||
end++;
|
||||
}
|
||||
else if(end[0] == '+') {
|
||||
end++;
|
||||
}
|
||||
else if(end[0] == '\0') {
|
||||
/* We had nothing but perhaps some whitespace -- there was no number. */
|
||||
if(endptr) {
|
||||
*endptr = end;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle special beginnings, if present and allowed. */
|
||||
if(end[0] == '0' && end[1] == 'x') {
|
||||
if(base == 16 || base == 0) {
|
||||
end += 2;
|
||||
base = 16;
|
||||
}
|
||||
}
|
||||
else if(end[0] == '0') {
|
||||
if(base == 8 || base == 0) {
|
||||
end++;
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Matching strtol, if the base is 0 and it does not look like
|
||||
* the number is octal or hex, we assume it is base 10.
|
||||
*/
|
||||
if(base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
/* Loop handling digits. */
|
||||
for(i = get_char(end[0], base);
|
||||
i != -1;
|
||||
end++, i = get_char(end[0], base)) {
|
||||
|
||||
if(value > (CURL_OFF_T_MAX - i) / base) {
|
||||
overflow = TRUE;
|
||||
break;
|
||||
}
|
||||
value = base * value + i;
|
||||
}
|
||||
|
||||
if(!overflow) {
|
||||
if(is_negative) {
|
||||
/* Fix the sign. */
|
||||
value *= -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(is_negative)
|
||||
value = CURL_OFF_T_MIN;
|
||||
else
|
||||
value = CURL_OFF_T_MAX;
|
||||
|
||||
errno = ERANGE;
|
||||
}
|
||||
|
||||
if(endptr)
|
||||
*endptr = end;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of c in the given base, or -1 if c cannot
|
||||
* be interpreted properly in that base (i.e., is out of range,
|
||||
* is a null, etc.).
|
||||
*
|
||||
* @param c the character to interpret according to base
|
||||
* @param base the base in which to interpret c
|
||||
*
|
||||
* @return the value of c in base, or -1 if c is not in range
|
||||
*/
|
||||
static int get_char(char c, int base)
|
||||
{
|
||||
#ifndef NO_RANGE_TEST
|
||||
int value = -1;
|
||||
if(c <= '9' && c >= '0') {
|
||||
value = c - '0';
|
||||
}
|
||||
else if(c <= 'Z' && c >= 'A') {
|
||||
value = c - 'A' + 10;
|
||||
}
|
||||
else if(c <= 'z' && c >= 'a') {
|
||||
value = c - 'a' + 10;
|
||||
}
|
||||
#else
|
||||
const char *cp;
|
||||
int value;
|
||||
|
||||
cp = memchr(valchars, c, 10 + 26 + 26);
|
||||
|
||||
if(!cp)
|
||||
return -1;
|
||||
|
||||
value = cp - valchars;
|
||||
|
||||
if(value >= 10 + 26)
|
||||
value -= 26; /* Lowercase. */
|
||||
#endif
|
||||
|
||||
if(value >= base) {
|
||||
value = -1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif /* Only present if we need strtoll, but do not have it. */
|
||||
|
||||
/*
|
||||
* Parse a *positive* up to 64-bit number written in ASCII.
|
||||
* Parse a positive number up to 63-bit number written in ASCII. Skip leading
|
||||
* blanks. No support for prefixes.
|
||||
*/
|
||||
CURLofft curlx_strtoofft(const char *str, char **endp, int base,
|
||||
curl_off_t *num)
|
||||
{
|
||||
char *end = NULL;
|
||||
curl_off_t number;
|
||||
errno = 0;
|
||||
int rc;
|
||||
*num = 0; /* clear by default */
|
||||
DEBUGASSERT(base); /* starting now, avoid base zero */
|
||||
DEBUGASSERT((base == 10) || (base == 16));
|
||||
|
||||
while(*str && ISBLANK(*str))
|
||||
str++;
|
||||
if(('-' == *str) || (ISSPACE(*str))) {
|
||||
if(endp)
|
||||
*endp = (char *)str; /* did not actually move */
|
||||
return CURL_OFFT_INVAL; /* nothing parsed */
|
||||
}
|
||||
number = strtooff(str, &end, base);
|
||||
|
||||
rc = base == 10 ?
|
||||
Curl_str_number(&str, &number, CURL_OFF_T_MAX) :
|
||||
Curl_str_hex(&str, &number, CURL_OFF_T_MAX);
|
||||
|
||||
if(endp)
|
||||
*endp = end;
|
||||
if(errno == ERANGE)
|
||||
/* overflow/underflow */
|
||||
*endp = (char *)str;
|
||||
if(rc == STRE_OVERFLOW)
|
||||
/* overflow */
|
||||
return CURL_OFFT_FLOW;
|
||||
else if(str == end)
|
||||
else if(rc)
|
||||
/* nothing parsed */
|
||||
return CURL_OFFT_INVAL;
|
||||
|
||||
|
|
|
@ -26,22 +26,6 @@
|
|||
|
||||
#include "curl_setup.h"
|
||||
|
||||
/*
|
||||
* Determine which string to integral data type conversion function we use
|
||||
* to implement string conversion to our curl_off_t integral data type.
|
||||
*
|
||||
* Notice that curl_off_t might be 64 or 32 bits wide, and that it might use
|
||||
* an underlying data type which might be 'long', 'int64_t', 'long long' or
|
||||
* '__int64' and more remotely other data types.
|
||||
*
|
||||
* On systems where the size of curl_off_t is greater than the size of 'long'
|
||||
* the conversion function to use is strtoll() if it is available, otherwise,
|
||||
* we emulate its functionality with our own clone.
|
||||
*
|
||||
* On systems where the size of curl_off_t is smaller or equal than the size
|
||||
* of 'long' the conversion function to use is strtol().
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CURL_OFFT_OK, /* parsed fine */
|
||||
CURL_OFFT_FLOW, /* over or underflow */
|
||||
|
|
|
@ -864,8 +864,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
|
|||
/* Window Size */
|
||||
if(strncasecompare(option, "WS", 2)) {
|
||||
const char *p = arg;
|
||||
size_t x = 0;
|
||||
size_t y = 0;
|
||||
curl_off_t x = 0;
|
||||
curl_off_t y = 0;
|
||||
if(Curl_str_number(&p, &x, 0xffff) ||
|
||||
Curl_str_single(&p, 'x') ||
|
||||
Curl_str_number(&p, &y, 0xffff)) {
|
||||
|
|
13
lib/tftp.c
13
lib/tftp.c
|
@ -331,7 +331,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
|
|||
infof(data, "got option=(%s) value=(%s)", option, value);
|
||||
|
||||
if(checkprefix(TFTP_OPTION_BLKSIZE, option)) {
|
||||
size_t blksize;
|
||||
curl_off_t blksize;
|
||||
if(Curl_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
|
||||
failf(data, "%s (%d)", "blksize is larger than max supported",
|
||||
TFTP_BLKSIZE_MAX);
|
||||
|
@ -350,8 +350,8 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
|
|||
/* could realloc pkt buffers here, but the spec does not call out
|
||||
* support for the server requesting a bigger blksize than the client
|
||||
* requests */
|
||||
failf(data, "server requested blksize larger than allocated (%zd)",
|
||||
blksize);
|
||||
failf(data, "server requested blksize larger than allocated (%"
|
||||
CURL_FORMAT_CURL_OFF_T ")", blksize);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
|
||||
|
@ -360,16 +360,17 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
|
|||
state->blksize, state->requested_blksize);
|
||||
}
|
||||
else if(checkprefix(TFTP_OPTION_TSIZE, option)) {
|
||||
size_t tsize = 0;
|
||||
curl_off_t tsize = 0;
|
||||
/* tsize should be ignored on upload: Who cares about the size of the
|
||||
remote file? */
|
||||
if(!data->state.upload &&
|
||||
!Curl_str_number(&value, &tsize, SIZE_T_MAX)) {
|
||||
!Curl_str_number(&value, &tsize, CURL_OFF_T_MAX)) {
|
||||
if(!tsize) {
|
||||
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
infof(data, "tsize parsed from OACK (%zd)", tsize);
|
||||
infof(data, "tsize parsed from OACK (%" CURL_FORMAT_CURL_OFF_T ")",
|
||||
tsize);
|
||||
Curl_pgrsSetDownloadSize(data, tsize);
|
||||
}
|
||||
}
|
||||
|
|
12
lib/url.c
12
lib/url.c
|
@ -1681,7 +1681,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
|
|||
|
||||
if(!uc && zoneid) {
|
||||
const char *p = zoneid;
|
||||
size_t scope;
|
||||
curl_off_t scope;
|
||||
if(!Curl_str_number(&p, &scope, UINT_MAX))
|
||||
/* A plain number, use it directly as a scope id. */
|
||||
conn->scope_id = (unsigned int)scope;
|
||||
|
@ -1919,7 +1919,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
size_t port;
|
||||
curl_off_t port;
|
||||
bool valid = TRUE;
|
||||
if(data->set.use_port && data->state.allow_port)
|
||||
port = data->set.use_port;
|
||||
|
@ -2258,7 +2258,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
|
|||
(void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
|
||||
|
||||
if(portptr) {
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
const char *p = portptr;
|
||||
if(!Curl_str_number(&p, &num, 0xffff))
|
||||
port = (int)num;
|
||||
|
@ -2902,7 +2902,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
|
|||
*host_portno = '\0'; /* cut off number from hostname */
|
||||
host_portno++;
|
||||
if(*host_portno) {
|
||||
size_t portparse;
|
||||
curl_off_t portparse;
|
||||
const char *p = host_portno;
|
||||
if(Curl_str_number(&p, &portparse, 0xffff)) {
|
||||
failf(data, "No valid port number in connect to host string (%s)",
|
||||
|
@ -2981,9 +2981,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
|
|||
/* check whether the URL's port matches */
|
||||
char *ptr_next = strchr(ptr, ':');
|
||||
if(ptr_next) {
|
||||
size_t port_to_match;
|
||||
curl_off_t port_to_match;
|
||||
if(!Curl_str_number(&ptr, &port_to_match, 0xffff) &&
|
||||
(port_to_match == (size_t)conn->remote_port))
|
||||
(port_to_match == (curl_off_t)conn->remote_port))
|
||||
port_match = TRUE;
|
||||
ptr = ptr_next + 1;
|
||||
}
|
||||
|
|
74
lib/urlapi.c
74
lib/urlapi.c
|
@ -468,7 +468,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
|
|||
portptr = strchr(hostname, ':');
|
||||
|
||||
if(portptr) {
|
||||
size_t port;
|
||||
curl_off_t port;
|
||||
size_t keep = portptr - hostname;
|
||||
|
||||
/* Browser behavior adaptation. If there is a colon with no digits after,
|
||||
|
@ -489,7 +489,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
|
|||
u->portnum = (unsigned short) port;
|
||||
/* generate a new port number string to get rid of leading zeroes etc */
|
||||
free(u->port);
|
||||
u->port = aprintf("%zd", port);
|
||||
u->port = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
|
||||
if(!u->port)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ static int ipv4_normalize(struct dynbuf *host)
|
|||
bool done = FALSE;
|
||||
int n = 0;
|
||||
const char *c = Curl_dyn_ptr(host);
|
||||
unsigned long parts[4] = {0, 0, 0, 0};
|
||||
unsigned int parts[4] = {0, 0, 0, 0};
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(*c == '[')
|
||||
|
@ -604,22 +604,24 @@ static int ipv4_normalize(struct dynbuf *host)
|
|||
|
||||
errno = 0; /* for strtoul */
|
||||
while(!done) {
|
||||
char *endp = NULL;
|
||||
unsigned long l;
|
||||
if(!ISDIGIT(*c))
|
||||
/* most importantly this does not allow a leading plus or minus */
|
||||
return HOST_NAME;
|
||||
l = strtoul(c, &endp, 0);
|
||||
if(errno)
|
||||
return HOST_NAME;
|
||||
#if SIZEOF_LONG > 4
|
||||
/* a value larger than 32 bits */
|
||||
if(l > UINT_MAX)
|
||||
return HOST_NAME;
|
||||
#endif
|
||||
int rc;
|
||||
curl_off_t l;
|
||||
if(*c == '0') {
|
||||
c++;
|
||||
if(*c == 'x') {
|
||||
c++; /* skip the prefix */
|
||||
rc = Curl_str_hex(&c, &l, UINT_MAX);
|
||||
}
|
||||
else
|
||||
rc = Curl_str_octal(&c, &l, UINT_MAX);
|
||||
}
|
||||
else
|
||||
rc = Curl_str_number(&c, &l, UINT_MAX);
|
||||
|
||||
parts[n] = l;
|
||||
c = endp;
|
||||
if(rc)
|
||||
return HOST_NAME;
|
||||
|
||||
parts[n] = (unsigned int)l;
|
||||
|
||||
switch(*c) {
|
||||
case '.':
|
||||
|
@ -643,30 +645,30 @@ static int ipv4_normalize(struct dynbuf *host)
|
|||
Curl_dyn_reset(host);
|
||||
|
||||
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
|
||||
(unsigned int)(parts[0] >> 24),
|
||||
(unsigned int)((parts[0] >> 16) & 0xff),
|
||||
(unsigned int)((parts[0] >> 8) & 0xff),
|
||||
(unsigned int)(parts[0] & 0xff));
|
||||
(parts[0] >> 24),
|
||||
((parts[0] >> 16) & 0xff),
|
||||
((parts[0] >> 8) & 0xff),
|
||||
(parts[0] & 0xff));
|
||||
break;
|
||||
case 1: /* a.b -- 8.24 bits */
|
||||
if((parts[0] > 0xff) || (parts[1] > 0xffffff))
|
||||
return HOST_NAME;
|
||||
Curl_dyn_reset(host);
|
||||
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
|
||||
(unsigned int)(parts[0]),
|
||||
(unsigned int)((parts[1] >> 16) & 0xff),
|
||||
(unsigned int)((parts[1] >> 8) & 0xff),
|
||||
(unsigned int)(parts[1] & 0xff));
|
||||
(parts[0]),
|
||||
((parts[1] >> 16) & 0xff),
|
||||
((parts[1] >> 8) & 0xff),
|
||||
(parts[1] & 0xff));
|
||||
break;
|
||||
case 2: /* a.b.c -- 8.8.16 bits */
|
||||
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
|
||||
return HOST_NAME;
|
||||
Curl_dyn_reset(host);
|
||||
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
|
||||
(unsigned int)(parts[0]),
|
||||
(unsigned int)(parts[1]),
|
||||
(unsigned int)((parts[2] >> 8) & 0xff),
|
||||
(unsigned int)(parts[2] & 0xff));
|
||||
(parts[0]),
|
||||
(parts[1]),
|
||||
((parts[2] >> 8) & 0xff),
|
||||
(parts[2] & 0xff));
|
||||
break;
|
||||
case 3: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
|
||||
|
@ -674,10 +676,10 @@ static int ipv4_normalize(struct dynbuf *host)
|
|||
return HOST_NAME;
|
||||
Curl_dyn_reset(host);
|
||||
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
|
||||
(unsigned int)(parts[0]),
|
||||
(unsigned int)(parts[1]),
|
||||
(unsigned int)(parts[2]),
|
||||
(unsigned int)(parts[3]));
|
||||
(parts[0]),
|
||||
(parts[1]),
|
||||
(parts[2]),
|
||||
(parts[3]));
|
||||
break;
|
||||
}
|
||||
if(result)
|
||||
|
@ -1745,11 +1747,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
|||
return CURLUE_BAD_PORT_NUMBER;
|
||||
else {
|
||||
char *tmp;
|
||||
size_t port;
|
||||
curl_off_t port;
|
||||
if(Curl_str_number(&part, &port, 0xffff) || *part)
|
||||
/* weirdly provided number, not good! */
|
||||
return CURLUE_BAD_PORT_NUMBER;
|
||||
tmp = aprintf("%zd", port);
|
||||
tmp = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
|
||||
if(!tmp)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
free(u->port);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
banfunc strerror
|
||||
banfunc strncpy
|
||||
banfunc sscanf
|
||||
banfunc strtoul
|
||||
banfunc strtol
|
||||
|
|
|
@ -81,10 +81,10 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
|
|||
#endif
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_DBG_QUIC_WBLOCK");
|
||||
const char *p = getenv("CURL_DBG_QUIC_WBLOCK");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 100))
|
||||
qctx->wblock_percent = (int)l;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2871,9 +2871,12 @@ static void sftp_quote_stat(struct Curl_easy *data)
|
|||
|
||||
/* Now set the new attributes... */
|
||||
if(strncasecompare(cmd, "chgrp", 5)) {
|
||||
sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
|
||||
const char *p = sshc->quote_path1;
|
||||
curl_off_t gid;
|
||||
(void)Curl_str_number(&p, &gid, UINT_MAX);
|
||||
sshc->quote_attrs->gid = (uint32_t)gid;
|
||||
if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
|
||||
!sshc->acceptfail) {
|
||||
!sshc->acceptfail) {
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
failf(data, "Syntax error: chgrp gid not a number");
|
||||
|
@ -2885,10 +2888,9 @@ static void sftp_quote_stat(struct Curl_easy *data)
|
|||
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
|
||||
}
|
||||
else if(strncasecompare(cmd, "chmod", 5)) {
|
||||
mode_t perms;
|
||||
perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
|
||||
/* permissions are octal */
|
||||
if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
|
||||
curl_off_t perms;
|
||||
const char *p = sshc->quote_path1;
|
||||
if(Curl_str_octal(&p, &perms, 07777)) {
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
failf(data, "Syntax error: chmod permissions not a number");
|
||||
|
@ -2897,13 +2899,15 @@ static void sftp_quote_stat(struct Curl_easy *data)
|
|||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
||||
return;
|
||||
}
|
||||
sshc->quote_attrs->permissions = perms;
|
||||
sshc->quote_attrs->permissions = (mode_t)perms;
|
||||
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
|
||||
}
|
||||
else if(strncasecompare(cmd, "chown", 5)) {
|
||||
sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
|
||||
const char *p = sshc->quote_path1;
|
||||
curl_off_t uid;
|
||||
(void)Curl_str_number(&p, &uid, UINT_MAX);
|
||||
if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
|
||||
!sshc->acceptfail) {
|
||||
!sshc->acceptfail) {
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
failf(data, "Syntax error: chown uid not a number");
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
#include "select.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_path.h"
|
||||
|
||||
#include "strparse.h"
|
||||
#include <curl_base64.h> /* for base64 encoding/decoding */
|
||||
#include <curl_sha256.h>
|
||||
|
||||
|
@ -1368,7 +1368,10 @@ sftp_quote_stat(struct Curl_easy *data,
|
|||
|
||||
/* Now set the new attributes... */
|
||||
if(strncasecompare(cmd, "chgrp", 5)) {
|
||||
sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
|
||||
const char *p = sshc->quote_path1;
|
||||
curl_off_t gid;
|
||||
(void)Curl_str_number(&p, &gid, ULONG_MAX);
|
||||
sshp->quote_attrs.gid = (unsigned long)gid;
|
||||
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
|
||||
if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
|
||||
!sshc->acceptfail) {
|
||||
|
@ -1377,17 +1380,22 @@ sftp_quote_stat(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
else if(strncasecompare(cmd, "chmod", 5)) {
|
||||
sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
|
||||
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
|
||||
curl_off_t perms;
|
||||
const char *p = sshc->quote_path1;
|
||||
/* permissions are octal */
|
||||
if(sshp->quote_attrs.permissions == 0 &&
|
||||
!ISDIGIT(sshc->quote_path1[0])) {
|
||||
if(Curl_str_octal(&p, &perms, 07777)) {
|
||||
failf(data, "Syntax error: chmod permissions not a number");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sshp->quote_attrs.permissions = (unsigned long)perms;
|
||||
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
|
||||
}
|
||||
else if(strncasecompare(cmd, "chown", 5)) {
|
||||
sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
|
||||
const char *p = sshc->quote_path1;
|
||||
curl_off_t uid;
|
||||
(void)Curl_str_number(&p, &uid, ULONG_MAX);
|
||||
sshp->quote_attrs.uid = (unsigned long)uid;
|
||||
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
|
||||
if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
|
||||
!sshc->acceptfail) {
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "sendf.h"
|
||||
#include "progress.h"
|
||||
#include "curl_path.h"
|
||||
#include "strtoofft.h"
|
||||
#include "transfer.h"
|
||||
#include "speedcheck.h"
|
||||
#include "select.h"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
banfunc strerror
|
||||
banfunc strncpy
|
||||
banfunc sscanf
|
||||
banfunc strtoul
|
||||
banfunc strtol
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "multiif.h"
|
||||
#include "version_win32.h"
|
||||
#include "rand.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "curl_memory.h"
|
||||
|
@ -344,9 +345,9 @@ static const struct algo algs[]= {
|
|||
};
|
||||
|
||||
static int
|
||||
get_alg_id_by_name(char *name)
|
||||
get_alg_id_by_name(const char *name)
|
||||
{
|
||||
char *nameEnd = strchr(name, ':');
|
||||
const char *nameEnd = strchr(name, ':');
|
||||
size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name);
|
||||
int i;
|
||||
|
||||
|
@ -363,12 +364,13 @@ static CURLcode
|
|||
set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
|
||||
ALG_ID *algIds)
|
||||
{
|
||||
char *startCur = ciphers;
|
||||
const char *startCur = ciphers;
|
||||
int algCount = 0;
|
||||
while(startCur && (0 != *startCur) && (algCount < NUM_CIPHERS)) {
|
||||
long alg = strtol(startCur, 0, 0);
|
||||
if(!alg)
|
||||
curl_off_t alg;
|
||||
if(Curl_str_number(&startCur, &alg, INT_MAX) || !alg)
|
||||
alg = get_alg_id_by_name(startCur);
|
||||
|
||||
if(alg)
|
||||
algIds[algCount++] = (ALG_ID)alg;
|
||||
else if(!strncmp(startCur, "USE_STRONG_CRYPTO",
|
||||
|
|
15
lib/ws.c
15
lib/ws.c
|
@ -39,6 +39,7 @@
|
|||
#include "transfer.h"
|
||||
#include "select.h"
|
||||
#include "nonblock.h"
|
||||
#include "strparse.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
@ -778,12 +779,11 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
|
|||
data->conn->proto.ws = ws;
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_WS_CHUNK_SIZE");
|
||||
const char *p = getenv("CURL_WS_CHUNK_SIZE");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l > 0 && l <= (1*1024*1024)) {
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 1*1024*1024))
|
||||
chunk_size = (size_t)l;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1032,12 +1032,11 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
|
|||
/* Simulate a blocking send after this chunk has been sent */
|
||||
bool eagain_next = FALSE;
|
||||
size_t chunk_egain = 0;
|
||||
char *p = getenv("CURL_WS_CHUNK_EAGAIN");
|
||||
const char *p = getenv("CURL_WS_CHUNK_EAGAIN");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l > 0 && l <= (1*1024*1024)) {
|
||||
curl_off_t l;
|
||||
if(!Curl_str_number(&p, &l, 1*1024*1024))
|
||||
chunk_egain = (size_t)l;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -152,6 +152,8 @@ rem
|
|||
for /f "delims=" %%r in ('dir /b ..\src\*.rc') do call :element %1 src "%%r" %3
|
||||
) else if "!var!" == "CURL_SRC_X_C_FILES" (
|
||||
call :element %1 lib "strtoofft.c" %3
|
||||
call :element %1 lib "strparse.c" %3
|
||||
call :element %1 lib "strcase.c" %3
|
||||
call :element %1 lib "timediff.c" %3
|
||||
call :element %1 lib "nonblock.c" %3
|
||||
call :element %1 lib "warnless.c" %3
|
||||
|
@ -163,6 +165,8 @@ rem
|
|||
call :element %1 lib "config-win32.h" %3
|
||||
call :element %1 lib "curl_setup.h" %3
|
||||
call :element %1 lib "strtoofft.h" %3
|
||||
call :element %1 lib "strparse.h" %3
|
||||
call :element %1 lib "strcase.h" %3
|
||||
call :element %1 lib "timediff.h" %3
|
||||
call :element %1 lib "nonblock.h" %3
|
||||
call :element %1 lib "warnless.h" %3
|
||||
|
|
|
@ -42,6 +42,8 @@ CURLX_CFILES = \
|
|||
../lib/dynbuf.c \
|
||||
../lib/nonblock.c \
|
||||
../lib/strtoofft.c \
|
||||
../lib/strparse.c \
|
||||
../lib/strcase.c \
|
||||
../lib/timediff.c \
|
||||
../lib/version_win32.c \
|
||||
../lib/warnless.c
|
||||
|
@ -53,6 +55,8 @@ CURLX_HFILES = \
|
|||
../lib/dynbuf.h \
|
||||
../lib/nonblock.h \
|
||||
../lib/strtoofft.h \
|
||||
../lib/strparse.h \
|
||||
../lib/strcase.h \
|
||||
../lib/timediff.h \
|
||||
../lib/version_win32.h \
|
||||
../lib/warnless.h
|
||||
|
|
|
@ -97,9 +97,9 @@ Curl_str_number
|
|||
10: (" 123") 8, [0] line 0
|
||||
11: ("") 8, [0] line 0
|
||||
Curl_str_number / max
|
||||
0: ("9223372036854775808") 0, [9223372036854775808] line 19
|
||||
1: ("9223372036854775809") 0, [9223372036854775809] line 19
|
||||
2: ("18446744073709551615") 0, [18446744073709551615] line 20
|
||||
0: ("9223372036854775807") 0, [9223372036854775807] line 19
|
||||
1: ("9223372036854775808") 7, [0] line 18
|
||||
2: ("18446744073709551615") 7, [0] line 19
|
||||
3: ("18446744073709551616") 7, [0] line 19
|
||||
4: ("18446744073709551617") 7, [0] line 19
|
||||
Curl_str_newline
|
||||
|
@ -115,6 +115,38 @@ Curl_str_newline
|
|||
8: ("
|
||||
") 0, line 1
|
||||
9: ("") 6, line 0
|
||||
Curl_str_hex
|
||||
0: ("1") 0, [1] line 1
|
||||
1: ("1000") 0, [4096] line 4
|
||||
2: ("1234") 0, [4660] line 4
|
||||
3: ("1235") 0, [4661] line 4
|
||||
4: ("1236") 1, [0] line 3
|
||||
5: ("01234") 0, [4660] line 5
|
||||
6: ("00000000000000000000000000001234") 0, [4660] line 32
|
||||
7: ("0123 345") 0, [291] line 4
|
||||
8: ("0123O345") 0, [291] line 4
|
||||
9: ("-12") 8, [0] line 0
|
||||
10: (" 123") 8, [0] line 0
|
||||
11: ("") 8, [0] line 0
|
||||
Curl_str_octal
|
||||
0: ("1") 0, [1] line 1
|
||||
1: ("1000") 0, [512] line 4
|
||||
2: ("1234") 0, [668] line 4
|
||||
3: ("1235") 0, [669] line 4
|
||||
4: ("1236") 1, [0] line 3
|
||||
5: ("01234") 0, [668] line 5
|
||||
6: ("00000000000000000000000000001234") 0, [668] line 32
|
||||
7: ("0123 345") 0, [83] line 4
|
||||
8: ("0123O345") 0, [83] line 4
|
||||
9: ("-12") 8, [0] line 0
|
||||
10: (" 123") 8, [0] line 0
|
||||
11: ("") 8, [0] line 0
|
||||
Curl_str_octal / max
|
||||
0: ("777777777777777777777") 0, [9223372036854775807] line 21
|
||||
1: ("1000000000000000000000") 7, [0] line 21
|
||||
Curl_str_hex / max
|
||||
0: ("7FFFFFFFFFFFFFFF") 0, [9223372036854775807] line 16
|
||||
1: ("8000000000000000") 7, [0] line 15
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
|
@ -29,6 +29,8 @@ CURLX_SRCS = \
|
|||
../../lib/mprintf.c \
|
||||
../../lib/nonblock.c \
|
||||
../../lib/strtoofft.c \
|
||||
../../lib/strparse.c \
|
||||
../../lib/strequal.c \
|
||||
../../lib/warnless.c \
|
||||
../../lib/timediff.c \
|
||||
../../lib/dynbuf.c \
|
||||
|
@ -41,10 +43,12 @@ CURLX_HDRS = \
|
|||
../../lib/curlx.h \
|
||||
../../lib/nonblock.h \
|
||||
../../lib/strtoofft.h \
|
||||
../../lib/strcase.h \
|
||||
../../lib/warnless.h \
|
||||
../../lib/timediff.h \
|
||||
../../lib/curl_ctype.h \
|
||||
../../lib/dynbuf.h \
|
||||
../../lib/strcase.h \
|
||||
../../lib/strdup.h \
|
||||
../../lib/curl_get_line.h \
|
||||
../../lib/curl_multibyte.h
|
||||
|
|
|
@ -196,7 +196,7 @@ UNITTEST_START
|
|||
};
|
||||
printf("Curl_str_number\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_number(&line, &num, 1235);
|
||||
|
@ -206,10 +206,10 @@ UNITTEST_START
|
|||
}
|
||||
|
||||
{
|
||||
/* SIZE_T_MAX is typically 18446744073709551615 */
|
||||
/* CURL_OFF_T is typically 9223372036854775807 */
|
||||
static const char *nums[] = {
|
||||
"9223372036854775808", /* 2^63 */
|
||||
"9223372036854775809", /* 2^63 + 1 */
|
||||
"9223372036854775807", /* 2^63 -1 */
|
||||
"9223372036854775808", /* 2^63 */
|
||||
"18446744073709551615", /* 2^64 - 1 */
|
||||
"18446744073709551616", /* 2^64 */
|
||||
"18446744073709551617", /* 2^64 + 1 */
|
||||
|
@ -217,11 +217,11 @@ UNITTEST_START
|
|||
};
|
||||
printf("Curl_str_number / max\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
size_t num;
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_number(&line, &num, SIZE_T_MAX);
|
||||
printf("%u: (\"%s\") %d, [%zu] line %d\n",
|
||||
int rc = Curl_str_number(&line, &num, CURL_OFF_T_MAX);
|
||||
printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
|
||||
i, orgline, rc, num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
@ -250,5 +250,95 @@ UNITTEST_START
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
static const char *nums[] = {
|
||||
"1",
|
||||
"1000",
|
||||
"1234",
|
||||
"1235",
|
||||
"1236",
|
||||
"01234",
|
||||
"00000000000000000000000000001234",
|
||||
"0123 345",
|
||||
"0123O345",
|
||||
"-12",
|
||||
" 123",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_hex\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_hex(&line, &num, 0x1235);
|
||||
printf("%u: (\"%s\") %d, [%u] line %d\n",
|
||||
i, orgline, rc, (int)num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
static const char *nums[] = {
|
||||
"1",
|
||||
"1000",
|
||||
"1234",
|
||||
"1235",
|
||||
"1236",
|
||||
"01234",
|
||||
"00000000000000000000000000001234",
|
||||
"0123 345",
|
||||
"0123O345",
|
||||
"-12",
|
||||
" 123",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_octal\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_octal(&line, &num, 01235);
|
||||
printf("%u: (\"%s\") %d, [%u] line %d\n",
|
||||
i, orgline, rc, (int)num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* CURL_OFF_T is typically 2^63-1 */
|
||||
static const char *nums[] = {
|
||||
"777777777777777777777", /* 2^63 -1 */
|
||||
"1000000000000000000000", /* 2^63 */
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_octal / max\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_octal(&line, &num, CURL_OFF_T_MAX);
|
||||
printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
|
||||
i, orgline, rc, num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* CURL_OFF_T is typically 2^63-1 */
|
||||
static const char *nums[] = {
|
||||
"7FFFFFFFFFFFFFFF", /* 2^63 -1 */
|
||||
"8000000000000000", /* 2^63 */
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_hex / max\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
curl_off_t num;
|
||||
const char *line = nums[i];
|
||||
const char *orgline = line;
|
||||
int rc = Curl_str_hex(&line, &num, CURL_OFF_T_MAX);
|
||||
printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
|
||||
i, orgline, rc, num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
UNITTEST_STOP
|
||||
|
|
|
@ -692,6 +692,8 @@ CURL_LIBCURL_LIBNAME=$(LIB_NAME_IMP)
|
|||
CURL_FROM_LIBCURL=\
|
||||
$(CURL_DIROBJ)\nonblock.obj \
|
||||
$(CURL_DIROBJ)\strtoofft.obj \
|
||||
$(CURL_DIROBJ)\strparse.obj \
|
||||
$(CURL_DIROBJ)\strcase.obj \
|
||||
$(CURL_DIROBJ)\warnless.obj \
|
||||
$(CURL_DIROBJ)\curl_get_line.obj \
|
||||
$(CURL_DIROBJ)\curl_multibyte.obj \
|
||||
|
@ -718,6 +720,10 @@ $(CURL_DIROBJ)\nonblock.obj: ../lib/nonblock.c
|
|||
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/nonblock.c
|
||||
$(CURL_DIROBJ)\strtoofft.obj: ../lib/strtoofft.c
|
||||
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strtoofft.c
|
||||
$(CURL_DIROBJ)\strparse.obj: ../lib/strparse.c
|
||||
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strparse.c
|
||||
$(CURL_DIROBJ)\strcase.obj: ../lib/strcase.c
|
||||
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strcase.c
|
||||
$(CURL_DIROBJ)\warnless.obj: ../lib/warnless.c
|
||||
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/warnless.c
|
||||
$(CURL_DIROBJ)\curl_get_line.obj: ../lib/curl_get_line.c
|
||||
|
|
Loading…
Reference in New Issue
Block a user