lib: use Curl_str_number() for parsing decimal numbers

Instead of strtoul() and strtol() calls.

Easier API with better integer overflow detection and built-in max check
that now comes automatic everywhere this is used.

Closes #16319
This commit is contained in:
Daniel Stenberg 2025-02-13 08:45:43 +01:00
parent 130b6891c8
commit b696fc129b
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
16 changed files with 180 additions and 202 deletions

View File

@ -528,8 +528,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
size_t dstlen = 0; /* destination hostname length */
const char *value_ptr;
char option[32];
unsigned long num;
char *end_ptr;
size_t num;
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
@ -567,21 +566,14 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
dstlen = strlen(srchost);
}
if(*p == ':') {
unsigned long port = 0;
size_t port = 0;
p++;
if(ISDIGIT(*p))
/* a port number */
port = strtoul(p, &end_ptr, 10);
else
end_ptr = (char *)p; /* not left uninitialized */
if(!port || port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
if(Curl_str_number(&p, &port, 0xffff) || (*p != '\"')) {
infof(data, "Unknown alt-svc port number, ignoring.");
valid = FALSE;
}
else {
dstport = curlx_ultous(port);
p = end_ptr;
}
else
dstport = (unsigned short)port;
}
if(*p++ != '\"')
break;
@ -625,8 +617,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
p++;
}
num = strtoul(value_ptr, &end_ptr, 10);
if((end_ptr != value_ptr) && (num < ULONG_MAX)) {
if(!Curl_str_number(&value_ptr, &num, SIZE_T_MAX)) {
if(strcasecompare("ma", option))
maxage = (time_t)num;
else if(strcasecompare("persist", option) && (num == 1))

View File

@ -83,6 +83,7 @@
#include "share.h"
#include "strdup.h"
#include "version_win32.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -741,10 +742,9 @@ 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 */
unsigned long scope_id = strtoul(scope_ptr, NULL, 10);
if(scope_id > UINT_MAX)
size_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;
}
#endif

View File

@ -73,6 +73,7 @@
#include "http_proxy.h"
#include "socks.h"
#include "strdup.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -464,7 +465,7 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
if(response) {
infof(data, "Ctrl conn has data while waiting for data conn");
if(pp->overflow > 3) {
char *r = Curl_dyn_ptr(&pp->recvbuf);
const char *r = Curl_dyn_ptr(&pp->recvbuf);
DEBUGASSERT((pp->overflow + pp->nfinal) <=
Curl_dyn_len(&pp->recvbuf));
@ -472,8 +473,8 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
r += pp->nfinal;
if(LASTLINE(r)) {
int status = curlx_sltosi(strtol(r, NULL, 10));
if(status == 226) {
size_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
noticed. Leave the 226 in there and use this as a trigger to read
@ -541,13 +542,14 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
}
static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
char *line, size_t len, int *code)
const char *line, size_t len, int *code)
{
size_t status;
(void)data;
(void)conn;
if((len > 3) && LASTLINE(line)) {
*code = curlx_sltosi(strtol(line, NULL, 10));
if((len > 3) && LASTLINE(line) && !Curl_str_number(&line, &status, 999)) {
*code = (int)status;
return TRUE;
}
@ -925,13 +927,20 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
/* parse the port */
if(ip_end) {
char *port_sep = NULL;
char *port_start = strchr(ip_end, ':');
if(port_start) {
port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
port_sep = strchr(port_start, '-');
if(port_sep) {
port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
const char *portp = strchr(ip_end, ':');
if(portp) {
size_t start;
size_t end;
portp++;
if(!Curl_str_number(&portp, &start, 0xffff)) {
/* got the first number */
port_min = (unsigned short)start;
if(!Curl_str_single(&portp, '-')) {
/* got the dash */
if(!Curl_str_number(&portp, &end, 0xffff))
/* got the second number */
port_max = (unsigned short)end;
}
}
else
port_max = port_min;
@ -1758,20 +1767,15 @@ static bool match_pasv_6nums(const char *p,
{
int i;
for(i = 0; i < 6; i++) {
unsigned long num;
char *endp;
size_t num;
if(i) {
if(*p != ',')
return FALSE;
p++;
}
if(!ISDIGIT(*p))
return FALSE;
num = strtoul(p, &endp, 10);
if(num > 255)
if(Curl_str_number(&p, &num, 0xff))
return FALSE;
array[i] = (unsigned int)num;
p = endp;
}
return TRUE;
}
@ -1804,20 +1808,16 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
/* the ISDIGIT() check here is because strtoul() accepts leading minus
etc */
if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
char *endp;
unsigned long num = strtoul(&ptr[3], &endp, 10);
if(*endp != sep)
ptr = NULL;
else if(num > 0xffff) {
const char *p = &ptr[3];
size_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;
}
if(ptr) {
ftpc->newport = (unsigned short)(num & 0xffff);
ftpc->newhost = strdup(control_address(conn));
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
}
ftpc->newport = (unsigned short)num;
ftpc->newhost = strdup(control_address(conn));
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
}
else
ptr = NULL;

View File

@ -50,9 +50,12 @@
#include "ftp.h"
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "curl_memory.h"
#include "multiif.h"
/* The last #include file should be: */
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
typedef enum {
@ -543,13 +546,13 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
case PL_UNIX_HLINKS_NUMBER:
parser->item_length ++;
if(c == ' ') {
char *p;
long int hlinks;
const char *p = &mem[parser->item_offset];
size_t hlinks;
mem[parser->item_offset + parser->item_length - 1] = 0;
hlinks = strtol(mem + parser->item_offset, &p, 10);
if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
if(!Curl_str_number(&p, &hlinks, LONG_MAX)) {
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
parser->file_data->info.hardlinks = hlinks;
parser->file_data->info.hardlinks = (long)hlinks;
}
parser->item_length = 0;
parser->item_offset = 0;

View File

@ -58,6 +58,8 @@
#include "warnless.h"
#include "strcase.h"
#include "easy_lock.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -1122,7 +1124,7 @@ void Curl_hostcache_clean(struct Curl_easy *data,
CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct curl_slist *hostp;
char *host_end;
const char *host_end;
/* Default is no wildcard found */
data->state.wildcard_resolve = FALSE;
@ -1132,15 +1134,15 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(!hostp->data)
continue;
if(hostp->data[0] == '-') {
unsigned long num = 0;
size_t num = 0;
size_t entry_len;
size_t hlen = 0;
host_end = strchr(&hostp->data[1], ':');
if(host_end) {
hlen = host_end - &hostp->data[1];
num = strtoul(++host_end, NULL, 10);
if(!hlen || (num > 0xffff))
host_end++;
if(Curl_str_number(&host_end, &num, 0xffff))
host_end = NULL;
}
if(!host_end) {
@ -1166,15 +1168,14 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
size_t entry_len;
char address[64];
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char *addresses = NULL;
const char *addresses = NULL;
#endif
char *addr_begin;
char *addr_end;
char *port_ptr;
int port = 0;
char *end_ptr;
const char *addr_begin;
const char *addr_end;
const char *port_ptr;
size_t port = 0;
const char *end_ptr;
bool permanent = TRUE;
unsigned long tmp_port;
bool error = TRUE;
char *host_begin = hostp->data;
size_t hlen = 0;
@ -1189,11 +1190,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
hlen = host_end - host_begin;
port_ptr = host_end + 1;
tmp_port = strtoul(port_ptr, &end_ptr, 10);
if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
if(Curl_str_number(&port_ptr, &port, 0xffff) ||
(*port_ptr != ':'))
goto err;
end_ptr = port_ptr;
port = (int)tmp_port;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
addresses = end_ptr + 1;
#endif
@ -1234,7 +1235,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
}
#endif
ai = Curl_str2addr(address, port);
ai = Curl_str2addr(address, (int)port);
if(!ai) {
infof(data, "Resolve address '%s' found illegal", address);
goto err;
@ -1262,7 +1263,7 @@ err:
}
/* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(host_begin, hlen, port,
entry_len = create_hostcache_id(host_begin, hlen, (int)port,
entry_id, sizeof(entry_id));
if(data->share)
@ -1272,7 +1273,7 @@ err:
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %.*s:%d - old addresses discarded",
infof(data, "RESOLVE %.*s:%zd - old addresses discarded",
(int)hlen, host_begin, port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
@ -1289,7 +1290,8 @@ err:
}
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, host_begin, hlen, port, permanent);
dns = Curl_cache_addr(data, head, host_begin, hlen, (int)port,
permanent);
if(dns) {
/* release the returned reference; the cache itself will keep the
* entry alive: */
@ -1304,14 +1306,14 @@ err:
return CURLE_OUT_OF_MEMORY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%d:%s to DNS cache%s",
infof(data, "Added %.*s:%zd:%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 *:%d using wildcard", port);
infof(data, "RESOLVE *:%zd using wildcard", port);
data->state.wildcard_resolve = TRUE;
}
}

View File

@ -242,7 +242,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
* response which can be processed by the response handler.
*/
static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
char *line, size_t len, int *resp)
const char *line, size_t len, int *resp)
{
struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;

View File

@ -83,6 +83,7 @@
#include "strcase.h"
#include "warnless.h"
#include "parsedate.h"
#include "strparse.h"
/*
* parsedate()
@ -411,7 +412,7 @@ static int parsedate(const char *date, time_t *output)
}
else if(ISDIGIT(*date)) {
/* a digit */
int val;
unsigned int val;
char *end;
if((secnum == -1) &&
match_time(date, &hournum, &minnum, &secnum, &end)) {
@ -419,29 +420,18 @@ static int parsedate(const char *date, time_t *output)
date = end;
}
else {
long lval;
int error;
int old_errno;
old_errno = errno;
errno = 0;
lval = strtol(date, &end, 10);
error = errno;
if(errno != old_errno)
errno = old_errno;
if(error)
size_t lval;
int num_digits = 0;
const char *p = date;
if(Curl_str_number(&p, &lval, 99999999))
return PARSEDATE_FAIL;
#if LONG_MAX != INT_MAX
if((lval > (long)INT_MAX) || (lval < (long)INT_MIN))
return PARSEDATE_FAIL;
#endif
val = curlx_sltosi(lval);
/* we know num_digits cannot be larger than 8 */
num_digits = (int)(p - date);
val = (unsigned int)lval;
if((tzoff == -1) &&
((end - date) == 4) &&
(num_digits == 4) &&
(val <= 1400) &&
(indate < date) &&
((date[-1] == '+' || date[-1] == '-'))) {
@ -461,10 +451,10 @@ static int parsedate(const char *date, time_t *output)
tzoff = date[-1]=='+' ? -tzoff : tzoff;
}
if(((end - date) == 8) &&
(yearnum == -1) &&
(monnum == -1) &&
(mdaynum == -1)) {
else if((num_digits == 8) &&
(yearnum == -1) &&
(monnum == -1) &&
(mdaynum == -1)) {
/* 8 digits, no year, month or day yet. This is YYYYMMDD */
found = TRUE;
yearnum = val/10000;
@ -496,7 +486,7 @@ static int parsedate(const char *date, time_t *output)
if(!found)
return PARSEDATE_FAIL;
date = end;
date = p;
}
}

View File

@ -69,7 +69,7 @@ struct pingpong {
CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
char *ptr, size_t len, int *code);
const char *ptr, size_t len, int *code);
};
#define PINGPONG_SETUP(pp,s,e) \

View File

@ -244,7 +244,7 @@ static bool pop3_is_multiline(const char *cmdline)
* types and allowed SASL mechanisms.
*/
static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
char *line, size_t len, int *resp)
const char *line, size_t len, int *resp)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)data;

View File

@ -40,6 +40,7 @@
#include "connect.h"
#include "cfilters.h"
#include "strdup.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -925,21 +926,17 @@ 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)) {
long CSeq = 0;
char *endp;
size_t CSeq = 0;
struct RTSP *rtsp = data->req.p.rtsp;
const char *p = &header[5];
while(ISBLANK(*p))
p++;
CSeq = strtol(p, &endp, 10);
if(p != endp) {
struct RTSP *rtsp = data->req.p.rtsp;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
else {
if(Curl_str_number(&p, &CSeq, LONG_MAX)) {
failf(data, "Unable to read the CSeq header: [%s]", header);
return CURLE_RTSP_CSEQ_ERROR;
}
rtsp->CSeq_recv = (long)CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = (long)CSeq; /* update the handle */
}
else if(checkprefix("Session:", header)) {
const char *start, *end;
@ -1010,25 +1007,21 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport)
start++;
end = strchr(start, ';');
if(checkprefix("interleaved=", start)) {
long chan1, chan2, chan;
char *endp;
size_t chan1, chan2, chan;
const char *p = start + 12;
chan1 = strtol(p, &endp, 10);
if(p != endp && chan1 >= 0 && chan1 <= 255) {
if(!Curl_str_number(&p, &chan1, 255)) {
unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
chan2 = chan1;
if(*endp == '-') {
p = endp + 1;
chan2 = strtol(p, &endp, 10);
if(p == endp || chan2 < 0 || chan2 > 255) {
if(!Curl_str_single(&p, '-')) {
if(Curl_str_number(&p, &chan2, 255)) {
infof(data, "Unable to read the interleaved parameter from "
"Transport header: [%s]", transport);
chan2 = chan1;
}
}
for(chan = chan1; chan <= chan2; chan++) {
long idx = chan / 8;
long off = chan % 8;
int idx = (int)chan / 8;
int off = (int)chan % 8;
rtp_channel_mask[idx] |= (unsigned char)(1 << off);
}
}

View File

@ -80,6 +80,8 @@
#include "curl_sasl.h"
#include "warnless.h"
#include "idn.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -197,7 +199,7 @@ static const struct SASLproto saslsmtp = {
* supported authentication mechanisms.
*/
static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
char *line, size_t len, int *resp)
const char *line, size_t len, int *resp)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
bool result = FALSE;
@ -213,11 +215,14 @@ 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;
const char *p = tmpline;
result = TRUE;
memset(tmpline, '\0', sizeof(tmpline));
memcpy(tmpline, line, (len == 5 ? 5 : 3));
*resp = curlx_sltosi(strtol(tmpline, NULL, 10));
tmpline[len == 5 ? 5 : 3 ] = 0;
if(Curl_str_number(&p, &code, len == 5 ? 99999 : 999))
return FALSE;
*resp = (int) code;
/* Make sure real server never sends internal value */
if(*resp == 1)

View File

@ -58,6 +58,7 @@
#include "select.h"
#include "strcase.h"
#include "warnless.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -862,22 +863,20 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
case 2:
/* Window Size */
if(strncasecompare(option, "WS", 2)) {
char *p;
unsigned long x = strtoul(arg, &p, 10);
unsigned long y = 0;
if(x && (x <= 0xffff) && Curl_raw_tolower(*p) == 'x') {
p++;
y = strtoul(p, NULL, 10);
if(y && (y <= 0xffff)) {
tn->subopt_wsx = (unsigned short)x;
tn->subopt_wsy = (unsigned short)y;
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
}
}
if(!y) {
const char *p = arg;
size_t x = 0;
size_t y = 0;
if(Curl_str_number(&p, &x, 0xffff) ||
Curl_str_single(&p, 'x') ||
Curl_str_number(&p, &y, 0xffff)) {
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
}
else {
tn->subopt_wsx = (unsigned short)x;
tn->subopt_wsy = (unsigned short)y;
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
}
}
else
result = CURLE_UNKNOWN_OPTION;

View File

@ -62,6 +62,7 @@
#include "speedcheck.h"
#include "select.h"
#include "escape.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -135,9 +136,9 @@ struct tftp_state_data {
struct Curl_sockaddr_storage remote_addr;
curl_socklen_t remote_addrlen;
int rbytes;
int sbytes;
int blksize;
int requested_blksize;
size_t sbytes;
unsigned int blksize;
unsigned int requested_blksize;
unsigned short block;
struct tftp_packet rpacket;
struct tftp_packet spacket;
@ -330,19 +331,16 @@ 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)) {
long blksize;
blksize = strtol(value, NULL, 10);
if(!blksize) {
failf(data, "invalid blocksize value in OACK packet");
return CURLE_TFTP_ILLEGAL;
}
if(blksize > TFTP_BLKSIZE_MAX) {
size_t blksize;
if(Curl_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
failf(data, "%s (%d)", "blksize is larger than max supported",
TFTP_BLKSIZE_MAX);
return CURLE_TFTP_ILLEGAL;
}
if(!blksize) {
failf(data, "invalid blocksize value in OACK packet");
return CURLE_TFTP_ILLEGAL;
}
else if(blksize < TFTP_BLKSIZE_MIN) {
failf(data, "%s (%d)", "blksize is smaller than min supported",
TFTP_BLKSIZE_MIN);
@ -352,28 +350,26 @@ 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, "%s (%ld)",
"server requested blksize larger than allocated", blksize);
failf(data, "server requested blksize larger than allocated (%zd)",
blksize);
return CURLE_TFTP_ILLEGAL;
}
state->blksize = (int)blksize;
infof(data, "%s (%d) %s (%d)", "blksize parsed from OACK",
state->blksize, "requested", state->requested_blksize);
infof(data, "blksize parsed from OACK (%d) requested (%d)",
state->blksize, state->requested_blksize);
}
else if(checkprefix(TFTP_OPTION_TSIZE, option)) {
long tsize = 0;
tsize = strtol(value, NULL, 10);
infof(data, "%s (%ld)", "tsize parsed from OACK", tsize);
size_t tsize = 0;
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
if(!data->state.upload) {
if(!data->state.upload &&
!Curl_str_number(&value, &tsize, SIZE_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);
Curl_pgrsSetDownloadSize(data, tsize);
}
}
@ -776,7 +772,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
&cb, &eos);
if(result)
return result;
state->sbytes += (int)cb;
state->sbytes += cb;
bufptr += cb;
} while(state->sbytes < state->blksize && cb);

View File

@ -119,7 +119,7 @@
#include "altsvc.h"
#include "dynbuf.h"
#include "headers.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -1680,9 +1680,9 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
#endif
if(!uc && zoneid) {
char *endp;
unsigned long scope = strtoul(zoneid, &endp, 10);
if(!*endp && (scope < UINT_MAX))
const char *p = zoneid;
size_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;
#if defined(HAVE_IF_NAMETOINDEX)
@ -1919,10 +1919,17 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
else {
unsigned long port = strtoul(data->state.up.port, NULL, 10);
conn->primary.remote_port = conn->remote_port =
(data->set.use_port && data->state.allow_port) ?
data->set.use_port : curlx_ultous(port);
size_t port;
bool valid = TRUE;
if(data->set.use_port && data->state.allow_port)
port = data->set.use_port;
else {
const char *p = data->state.up.port;
if(Curl_str_number(&p, &port, 0xffff))
valid = FALSE;
}
if(valid)
conn->primary.remote_port = conn->remote_port = (unsigned short)port;
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
@ -2251,7 +2258,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
(void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
port = (int)strtol(portptr, NULL, 10);
size_t num;
const char *p = portptr;
if(!Curl_str_number(&p, &num, 0xffff))
port = (int)num;
free(portptr);
}
else {
@ -2889,19 +2899,18 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
/* Get port number off server.com:1080 */
host_portno = strchr(portptr, ':');
if(host_portno) {
char *endp = NULL;
*host_portno = '\0'; /* cut off number from hostname */
host_portno++;
if(*host_portno) {
long portparse = strtol(host_portno, &endp, 10);
if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
size_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)",
host_portno);
result = CURLE_SETOPT_OPTION_SYNTAX;
goto error;
}
else
port = (int)portparse; /* we know it will fit */
port = (int)portparse; /* we know it will fit */
}
}
@ -2972,12 +2981,11 @@ 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) {
char *endp = NULL;
long port_to_match = strtol(ptr, &endp, 10);
if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
size_t port_to_match;
if(!Curl_str_number(&ptr, &port_to_match, 0xffff) &&
(port_to_match == (size_t)conn->remote_port))
port_match = TRUE;
ptr = ptr_next + 1;
}
ptr = ptr_next + 1;
}
}
}

View File

@ -34,6 +34,7 @@
#include "inet_ntop.h"
#include "strdup.h"
#include "idn.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -445,7 +446,7 @@ out:
UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
char *portptr;
const char *portptr;
char *hostname = Curl_dyn_ptr(host);
/*
* Find the end of an IPv6 address on the ']' ending bracket.
@ -467,8 +468,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
portptr = strchr(hostname, ':');
if(portptr) {
char *rest = NULL;
unsigned long port;
size_t port;
size_t keep = portptr - hostname;
/* Browser behavior adaptation. If there is a colon with no digits after,
@ -483,19 +483,13 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
if(!ISDIGIT(*portptr))
return CURLUE_BAD_PORT_NUMBER;
errno = 0;
port = strtoul(portptr, &rest, 10); /* Port number must be decimal */
if(errno || (port > 0xffff) || *rest)
if(Curl_str_number(&portptr, &port, 0xffff) || *portptr)
return CURLUE_BAD_PORT_NUMBER;
u->portnum = (unsigned short) port;
/* generate a new port number string to get rid of leading zeroes etc */
free(u->port);
u->port = aprintf("%ld", port);
u->port = aprintf("%zd", port);
if(!u->port)
return CURLUE_OUT_OF_MEMORY;
}
@ -1751,14 +1745,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_BAD_PORT_NUMBER;
else {
char *tmp;
char *endp;
unsigned long port;
errno = 0;
port = strtoul(part, &endp, 10); /* must be decimal */
if(errno || (port > 0xffff) || *endp)
size_t port;
if(Curl_str_number(&part, &port, 0xffff) || *part)
/* weirdly provided number, not good! */
return CURLUE_BAD_PORT_NUMBER;
tmp = strdup(part);
tmp = aprintf("%zd", port);
if(!tmp)
return CURLUE_OUT_OF_MEMORY;
free(u->port);

View File

@ -93,9 +93,9 @@ Curl_str_number
6: ("00000000000000000000000000001234") 0, [1234] line 32
7: ("0123 345") 0, [123] line 4
8: ("0123O345") 0, [123] line 4
9: ("-12") 0, [0] line 0
10: (" 123") 0, [0] line 0
11: ("") 0, [0] line 0
9: ("-12") 8, [0] line 0
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