Replace XDIGIT_TO_NUM by _unhex() with proper unsigned handling

* src/wget.h: Replace XDIGIT_TO_NUM by _unhex()
* src/html-parse.c (decode_entity): Use _unhex()
* src/host.c (is_valid_ipv6_address): Use _unhex()
* src/url.c (url_unescape_1): Use unsigned char to avoid UB
* src/res.c (free_specs): Likewise

Code taken from Wget2. XDIGIT_TO_NUM had a signed issue, detected by
scan-build static anylyzer.
This commit is contained in:
Tim Rühsen 2019-05-06 17:11:48 +02:00
parent a255d9f0c8
commit 2ba8da8f22
5 changed files with 12 additions and 9 deletions

View File

@ -516,7 +516,7 @@ is_valid_ipv6_address (const char *str, const char *end)
if (c_isxdigit (ch))
{
val <<= 4;
val |= XDIGIT_TO_NUM (ch);
val |= _unhex (ch);
if (val > 0xffff)
return false;
saw_xdigit = true;

View File

@ -386,7 +386,7 @@ decode_entity (const char **ptr, const char *end)
value = 0;
if (*p == 'x')
for (++p; value < 256 && p < end && c_isxdigit (*p); p++, digits++)
value = (value << 4) + XDIGIT_TO_NUM (*p);
value = (value << 4) + _unhex (*p);
else
for (; value < 256 && p < end && c_isdigit (*p); p++, digits++)
value = (value * 10) + (*p - '0');

View File

@ -419,7 +419,7 @@ free_specs (struct robot_specs *specs)
#define DECODE_MAYBE(c, ptr) do { \
if (c == '%' && c_isxdigit (ptr[1]) && c_isxdigit (ptr[2])) \
{ \
char decoded = X2DIGITS_TO_NUM (ptr[1], ptr[2]); \
unsigned char decoded = X2DIGITS_TO_NUM (ptr[1], ptr[2]); \
if (decoded != '/') \
{ \
c = decoded; \

View File

@ -175,8 +175,8 @@ static const unsigned char urlchr_table[256] =
static void
url_unescape_1 (char *s, unsigned char mask)
{
char *t = s; /* t - tortoise */
char *h = s; /* h - hare */
unsigned char *t = (unsigned char *) s; /* t - tortoise */
unsigned char *h = (unsigned char *) s; /* h - hare */
for (; *h; h++, t++)
{
@ -187,7 +187,7 @@ url_unescape_1 (char *s, unsigned char mask)
}
else
{
char c;
unsigned char c;
/* Do nothing if '%' is not followed by two hex digits. */
if (!h[1] || !h[2] || !(c_isxdigit (h[1]) && c_isxdigit (h[2])))
goto copychar;

View File

@ -239,10 +239,13 @@ typedef double SUM_SIZE_INT;
#define xzero(x) memset (&(x), '\0', sizeof (x))
/* Convert an ASCII hex digit to the corresponding number between 0
and 15. H should be a hexadecimal digit that satisfies isxdigit;
and 15. c should be a hexadecimal digit that satisfies c_isxdigit;
otherwise, the result is undefined. */
#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : c_toupper (h) - 'A' + 10)
#define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2))
static unsigned char _unhex(unsigned char c)
{
return c <= '9' ? c - '0' : (c <= 'F' ? c - 'A' + 10 : c - 'a' + 10);
}
#define X2DIGITS_TO_NUM(h1, h2) ((_unhex (h1) << 4) + _unhex (h2))
/* The reverse of the above: convert a number in the [0, 16) range to
the ASCII representation of the corresponding hexadecimal digit.