mirror of
https://github.com/curl/curl.git
synced 2026-04-14 21:31:42 +03:00
lib: unify conversions to/from hex
Curl_hexbyte - output a byte as a two-digit ASCII hex number Curl_hexval - convert an ASCII hex digit to its binary value ... instead of duplicating similar code and hexdigit strings in numerous places. Closes #16888
This commit is contained in:
parent
1d84d683bb
commit
0c6e63a1be
8 changed files with 69 additions and 71 deletions
43
lib/escape.c
43
lib/escape.c
|
|
@ -35,6 +35,8 @@ struct Curl_easy;
|
|||
#include "warnless.h"
|
||||
#include "escape.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"
|
||||
|
|
@ -82,10 +84,8 @@ char *curl_easy_escape(CURL *data, const char *string,
|
|||
}
|
||||
else {
|
||||
/* encode it */
|
||||
const char hex[] = "0123456789ABCDEF";
|
||||
char out[3]={'%'};
|
||||
out[1] = hex[in >> 4];
|
||||
out[2] = hex[in & 0xf];
|
||||
unsigned char out[3]={'%'};
|
||||
Curl_hexbyte(&out[1], in, FALSE);
|
||||
if(Curl_dyn_addn(&d, out, 3))
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -94,16 +94,6 @@ char *curl_easy_escape(CURL *data, const char *string,
|
|||
return Curl_dyn_ptr(&d);
|
||||
}
|
||||
|
||||
static const unsigned char hextable[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
|
||||
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
|
||||
0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
|
||||
};
|
||||
|
||||
/* the input is a single hex digit */
|
||||
#define onehex2dec(x) hextable[x - '0']
|
||||
|
||||
/*
|
||||
* Curl_urldecode() URL decodes the given string.
|
||||
*
|
||||
|
|
@ -144,8 +134,8 @@ CURLcode Curl_urldecode(const char *string, size_t length,
|
|||
if(('%' == in) && (alloc > 2) &&
|
||||
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
|
||||
/* this is two hexadecimal digits following a '%' */
|
||||
in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
|
||||
|
||||
in = (unsigned char)((Curl_hexval(string[1]) << 4) |
|
||||
Curl_hexval(string[2]));
|
||||
string += 3;
|
||||
alloc -= 3;
|
||||
}
|
||||
|
|
@ -219,13 +209,12 @@ void curl_free(void *p)
|
|||
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
|
||||
unsigned char *out, size_t olen) /* output buffer size */
|
||||
{
|
||||
const char *hex = "0123456789abcdef";
|
||||
DEBUGASSERT(src && len && (olen >= 3));
|
||||
if(src && len && (olen >= 3)) {
|
||||
while(len-- && (olen >= 3)) {
|
||||
*out++ = (unsigned char)hex[(*src & 0xF0) >> 4];
|
||||
*out++ = (unsigned char)hex[*src & 0x0F];
|
||||
Curl_hexbyte(out, *src, TRUE);
|
||||
++src;
|
||||
out += 2;
|
||||
olen -= 2;
|
||||
}
|
||||
*out = 0;
|
||||
|
|
@ -233,3 +222,19 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
|
|||
else if(olen)
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
/* Curl_hexbyte
|
||||
*
|
||||
* Output a single unsigned char as a two-digit hex number, lowercase or
|
||||
* uppercase
|
||||
*/
|
||||
void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */
|
||||
unsigned char val,
|
||||
bool lowercase)
|
||||
{
|
||||
const unsigned char uhex[] = "0123456789ABCDEF";
|
||||
const unsigned char lhex[] = "0123456789abcdef";
|
||||
const unsigned char *t = lowercase ? lhex : uhex;
|
||||
dest[0] = t[val >> 4];
|
||||
dest[1] = t[val & 0x0F];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,4 +41,8 @@ CURLcode Curl_urldecode(const char *string, size_t length,
|
|||
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
|
||||
unsigned char *out, size_t olen); /* output buffer size */
|
||||
|
||||
void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */
|
||||
unsigned char val,
|
||||
bool lowercase);
|
||||
|
||||
#endif /* HEADER_CURL_ESCAPE_H */
|
||||
|
|
|
|||
|
|
@ -537,8 +537,7 @@ static CURLcode canon_string(const char *q, size_t len,
|
|||
result = Curl_dyn_addn(dq, "%25", 3);
|
||||
break;
|
||||
default: {
|
||||
const char hex[] = "0123456789ABCDEF";
|
||||
char out[3]={'%'};
|
||||
unsigned char out[3]={'%'};
|
||||
|
||||
if(!found_equals) {
|
||||
/* if found_equals is NULL assuming, been in path */
|
||||
|
|
@ -557,8 +556,7 @@ static CURLcode canon_string(const char *q, size_t len,
|
|||
}
|
||||
}
|
||||
/* URL encode */
|
||||
out[1] = hex[((unsigned char)*q) >> 4];
|
||||
out[2] = hex[*q & 0xf];
|
||||
Curl_hexbyte(&out[1], *q, FALSE);
|
||||
result = Curl_dyn_addn(dq, out, 3);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
#include "curl_ctype.h"
|
||||
#include "strparse.h"
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
|
||||
|
|
@ -99,7 +101,6 @@ curlx_inet_pton(int af, const char *src, void *dst)
|
|||
static int
|
||||
inet_pton4(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
unsigned char tmp[INADDRSZ], *tp;
|
||||
|
||||
|
|
@ -108,12 +109,8 @@ inet_pton4(const char *src, unsigned char *dst)
|
|||
tp = tmp;
|
||||
*tp = 0;
|
||||
while((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
pch = strchr(digits, ch);
|
||||
if(pch) {
|
||||
unsigned int val = (unsigned int)(*tp * 10) +
|
||||
(unsigned int)(pch - digits);
|
||||
if(ISDIGIT(ch)) {
|
||||
unsigned int val = (*tp * 10) + (ch - '0');
|
||||
|
||||
if(saw_digit && *tp == 0)
|
||||
return 0;
|
||||
|
|
@ -157,8 +154,6 @@ inet_pton4(const char *src, unsigned char *dst)
|
|||
static int
|
||||
inet_pton6(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *curtok;
|
||||
int ch, saw_xdigit;
|
||||
|
|
@ -175,15 +170,9 @@ inet_pton6(const char *src, unsigned char *dst)
|
|||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while((ch = *src++) != '\0') {
|
||||
const char *xdigits;
|
||||
const char *pch;
|
||||
|
||||
pch = strchr((xdigits = xdigits_l), ch);
|
||||
if(!pch)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if(pch) {
|
||||
if(ISXDIGIT(ch)) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
val |= Curl_hexval(ch);
|
||||
if(++saw_xdigit > 4)
|
||||
return 0;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -139,25 +139,23 @@ int Curl_str_singlespace(const char **linep)
|
|||
|
||||
/* given an ASCII character and max ascii, return TRUE if valid */
|
||||
#define valid_digit(x,m) \
|
||||
(((x) >= '0') && ((x) <= m) && hexasciitable[(x)-'0'])
|
||||
(((x) >= '0') && ((x) <= m) && Curl_hexasciitable[(x)-'0'])
|
||||
|
||||
/* We use 16 for the zero index (and the necessary bitwise AND in the loop)
|
||||
to be able to have a non-zero value there to make valid_digit() able to
|
||||
use the info */
|
||||
const unsigned char Curl_hexasciitable[] = {
|
||||
16, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 0x30: 0 - 9 */
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
10, 11, 12, 13, 14, 15, /* 0x41: A - F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
10, 11, 12, 13, 14, 15 /* 0x61: a - f */
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
{
|
||||
/* We use 16 for the zero index (and the necessary bitwise AND in the loop)
|
||||
to be able to have a non-zero value there to make valid_digit() able to
|
||||
use the info */
|
||||
static const unsigned char hexasciitable[] = {
|
||||
16, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 0x30: 0 - 9 */
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
10, 11, 12, 13, 14, 15, /* 0x41: A - F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
10, 11, 12, 13, 14, 15 /* 0x61: a - f */
|
||||
};
|
||||
|
||||
curl_off_t num = 0;
|
||||
const char *p;
|
||||
int m = (base == 10) ? '9' : /* the largest digit possible */
|
||||
|
|
@ -172,7 +170,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
|
|||
if(max < base) {
|
||||
/* special-case low max scenario because check needs to be different */
|
||||
do {
|
||||
int n = hexasciitable[*p++ - '0'] & 0x0f;
|
||||
int n = Curl_hexval(*p++);
|
||||
num = num * base + n;
|
||||
if(num > max)
|
||||
return STRE_OVERFLOW;
|
||||
|
|
@ -180,7 +178,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
|
|||
}
|
||||
else {
|
||||
do {
|
||||
int n = hexasciitable[*p++ - '0'] & 0x0f;
|
||||
int n = Curl_hexval(*p++);
|
||||
if(num > ((max - n) / base))
|
||||
return STRE_OVERFLOW;
|
||||
num = num * base + n;
|
||||
|
|
|
|||
|
|
@ -102,6 +102,13 @@ int Curl_str_cspn(const char **linep, struct Curl_str *out, const char *cspn);
|
|||
void Curl_str_trimblanks(struct Curl_str *out);
|
||||
void Curl_str_passblanks(const char **linep);
|
||||
|
||||
/* given a hexadecimal letter, return the binary value. '0' returns 0, 'a'
|
||||
returns 10. THIS ONLY WORKS ON VALID HEXADECIMAL LETTER INPUT. Verify
|
||||
before calling this!
|
||||
*/
|
||||
extern const unsigned char Curl_hexasciitable[];
|
||||
#define Curl_hexval(x) (unsigned char)(Curl_hexasciitable[(x) - '0'] & 0x0f)
|
||||
|
||||
#define curlx_str_number(x,y,z) Curl_str_number(x,y,z)
|
||||
#define curlx_str_octal(x,y,z) Curl_str_octal(x,y,z)
|
||||
#define curlx_str_single(x,y) Curl_str_single(x,y)
|
||||
|
|
|
|||
11
lib/urlapi.c
11
lib/urlapi.c
|
|
@ -129,7 +129,6 @@ static const char *find_host_sep(const char *url)
|
|||
#define cc2cu(x) ((x) == CURLE_TOO_LARGE ? CURLUE_TOO_LARGE : \
|
||||
CURLUE_OUT_OF_MEMORY)
|
||||
|
||||
static const char hexdigits[] = "0123456789abcdef";
|
||||
/* urlencode_str() writes data into an output dynbuf and URL-encodes the
|
||||
* spaces in the source URL accordingly.
|
||||
*
|
||||
|
|
@ -164,9 +163,8 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
|
|||
result = Curl_dyn_addn(o, "+", 1);
|
||||
}
|
||||
else if((*iptr < ' ') || (*iptr >= 0x7f)) {
|
||||
char out[3]={'%'};
|
||||
out[1] = hexdigits[*iptr >> 4];
|
||||
out[2] = hexdigits[*iptr & 0xf];
|
||||
unsigned char out[3]={'%'};
|
||||
Curl_hexbyte(&out[1], *iptr, TRUE);
|
||||
result = Curl_dyn_addn(o, out, 3);
|
||||
}
|
||||
else {
|
||||
|
|
@ -1824,9 +1822,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
|||
return cc2cu(result);
|
||||
}
|
||||
else {
|
||||
char out[3]={'%'};
|
||||
out[1] = hexdigits[*i >> 4];
|
||||
out[2] = hexdigits[*i & 0xf];
|
||||
unsigned char out[3]={'%'};
|
||||
Curl_hexbyte(&out[1], *i, TRUE);
|
||||
result = Curl_dyn_addn(&enc, out, 3);
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "keylog.h"
|
||||
#include <curl/curl.h>
|
||||
#include "escape.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
|
|
@ -114,10 +115,9 @@ Curl_tls_keylog_write(const char *label,
|
|||
const unsigned char client_random[CLIENT_RANDOM_SIZE],
|
||||
const unsigned char *secret, size_t secretlen)
|
||||
{
|
||||
const char *hex = "0123456789ABCDEF";
|
||||
size_t pos, i;
|
||||
char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
|
||||
2 * SECRET_MAXLEN + 1 + 1];
|
||||
unsigned char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
|
||||
2 * SECRET_MAXLEN + 1 + 1];
|
||||
|
||||
if(!keylog_file_fp) {
|
||||
return FALSE;
|
||||
|
|
@ -134,22 +134,22 @@ Curl_tls_keylog_write(const char *label,
|
|||
|
||||
/* Client Random */
|
||||
for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
|
||||
line[pos++] = hex[client_random[i] >> 4];
|
||||
line[pos++] = hex[client_random[i] & 0xF];
|
||||
Curl_hexbyte(&line[pos], client_random[i], FALSE);
|
||||
pos += 2;
|
||||
}
|
||||
line[pos++] = ' ';
|
||||
|
||||
/* Secret */
|
||||
for(i = 0; i < secretlen; i++) {
|
||||
line[pos++] = hex[secret[i] >> 4];
|
||||
line[pos++] = hex[secret[i] & 0xF];
|
||||
Curl_hexbyte(&line[pos], secret[i], FALSE);
|
||||
pos += 2;
|
||||
}
|
||||
line[pos++] = '\n';
|
||||
line[pos] = '\0';
|
||||
|
||||
/* Using fputs here instead of fprintf since libcurl's fprintf replacement
|
||||
may not be thread-safe. */
|
||||
fputs(line, keylog_file_fp);
|
||||
fputs((char *)line, keylog_file_fp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue