diff options
Diffstat (limited to 'lib/escape.c')
-rw-r--r-- | lib/escape.c | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/lib/escape.c b/lib/escape.c index 7121db31..2bea145f 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, 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 @@ -79,82 +79,83 @@ char *curl_unescape(const char *string, int length) char *curl_easy_escape(struct Curl_easy *data, const char *string, int inlength) { - size_t alloc; - char *ns; - char *testing_ptr = NULL; - size_t newlen; - size_t strindex = 0; size_t length; CURLcode result; + struct dynbuf d; if(inlength < 0) return NULL; - alloc = (inlength?(size_t)inlength:strlen(string)) + 1; - newlen = alloc; + Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH); - ns = malloc(alloc); - if(!ns) - return NULL; + length = (inlength?(size_t)inlength:strlen(string)); + if(!length) + return strdup(""); - length = alloc-1; while(length--) { unsigned char in = *string; /* we need to treat the characters unsigned */ - if(Curl_isunreserved(in)) - /* just copy this */ - ns[strindex++] = in; + if(Curl_isunreserved(in)) { + /* append this */ + if(Curl_dyn_addn(&d, &in, 1)) + return NULL; + } else { /* encode it */ - newlen += 2; /* the size grows with two, since this'll become a %XX */ - if(newlen > alloc) { - alloc *= 2; - testing_ptr = Curl_saferealloc(ns, alloc); - if(!testing_ptr) - return NULL; - ns = testing_ptr; - } - + char encoded[4]; result = Curl_convert_to_network(data, (char *)&in, 1); if(result) { /* Curl_convert_to_network calls failf if unsuccessful */ - free(ns); + Curl_dyn_free(&d); return NULL; } - msnprintf(&ns[strindex], 4, "%%%02X", in); - - strindex += 3; + msnprintf(encoded, sizeof(encoded), "%%%02X", in); + if(Curl_dyn_add(&d, encoded)) + return NULL; } string++; } - ns[strindex] = 0; /* terminate it */ - return ns; + + return Curl_dyn_ptr(&d); } /* * Curl_urldecode() URL decodes the given string. * - * Optionally detects control characters (byte codes lower than 32) in the - * data and rejects such data. - * * Returns a pointer to a malloced string in *ostring with length given in * *olen. If length == 0, the length is assumed to be strlen(string). * * 'data' can be set to NULL but then this function can't convert network * data to host for non-ascii. + * + * ctrl options: + * - REJECT_NADA: accept everything + * - REJECT_CTRL: rejects control characters (byte codes lower than 32) in + * the data + * - REJECT_ZERO: rejects decoded zero bytes + * + * The values for the enum starts at 2, to make the assert detect legacy + * invokes that used TRUE/FALSE (0 and 1). */ + CURLcode Curl_urldecode(struct Curl_easy *data, const char *string, size_t length, char **ostring, size_t *olen, - bool reject_ctrl) + enum urlreject ctrl) { - size_t alloc = (length?length:strlen(string)) + 1; - char *ns = malloc(alloc); + size_t alloc; + char *ns; size_t strindex = 0; unsigned long hex; CURLcode result = CURLE_OK; + DEBUGASSERT(string); + DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */ + + alloc = (length?length:strlen(string)) + 1; + ns = malloc(alloc); + if(!ns) return CURLE_OUT_OF_MEMORY; @@ -186,7 +187,8 @@ CURLcode Curl_urldecode(struct Curl_easy *data, alloc -= 2; } - if(reject_ctrl && (in < 0x20)) { + if(((ctrl == REJECT_CTRL) && (in < 0x20)) || + ((ctrl == REJECT_ZERO) && (in == 0))) { free(ns); return CURLE_URL_MALFORMAT; } @@ -220,7 +222,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string, size_t inputlen = length; size_t outputlen; CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen, - FALSE); + REJECT_NADA); if(res) return NULL; |