summaryrefslogtreecommitdiffstats
path: root/lib/escape.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/escape.c')
-rw-r--r--lib/escape.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/lib/escape.c b/lib/escape.c
index ed59838..56aa2b3 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -97,7 +97,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
return strdup("");
while(length--) {
- unsigned char in = *string; /* we need to treat the characters unsigned */
+ unsigned char in = *string++; /* treat the characters unsigned */
if(Curl_isunreserved(in)) {
/* append this */
@@ -106,15 +106,28 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
}
else {
/* encode it */
- if(Curl_dyn_addf(&d, "%%%02X", in))
+ const char hex[] = "0123456789ABCDEF";
+ char out[3]={'%'};
+ out[1] = hex[in>>4];
+ out[2] = hex[in & 0xf];
+ if(Curl_dyn_addn(&d, out, 3))
return NULL;
}
- 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.
*
@@ -137,54 +150,47 @@ CURLcode Curl_urldecode(const char *string, size_t length,
{
size_t alloc;
char *ns;
- size_t strindex = 0;
- unsigned long hex;
DEBUGASSERT(string);
DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
- alloc = (length?length:strlen(string)) + 1;
- ns = malloc(alloc);
+ alloc = (length?length:strlen(string));
+ ns = malloc(alloc + 1);
if(!ns)
return CURLE_OUT_OF_MEMORY;
- while(--alloc > 0) {
+ /* store output string */
+ *ostring = ns;
+
+ while(alloc) {
unsigned char in = *string;
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
- char hexstr[3];
- char *ptr;
- hexstr[0] = string[1];
- hexstr[1] = string[2];
- hexstr[2] = 0;
-
- hex = strtoul(hexstr, &ptr, 16);
+ in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
- in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
-
- string += 2;
- alloc -= 2;
+ string += 3;
+ alloc -= 3;
+ }
+ else {
+ string++;
+ alloc--;
}
if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
((ctrl == REJECT_ZERO) && (in == 0))) {
- free(ns);
+ Curl_safefree(*ostring);
return CURLE_URL_MALFORMAT;
}
- ns[strindex++] = in;
- string++;
+ *ns++ = in;
}
- ns[strindex] = 0; /* terminate it */
+ *ns = 0; /* terminate it */
if(olen)
/* store output size */
- *olen = strindex;
-
- /* store output string */
- *ostring = ns;
+ *olen = ns - *ostring;
return CURLE_OK;
}