[CVE-2016-7167] curl escape and unescape integer overflows
[platform/upstream/curl.git] / lib / escape.c
index 9923e64..e61260d 100644 (file)
@@ -5,11 +5,11 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, 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
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
  *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
 
 #include <curl/curl.h>
 
-#include "curl_memory.h"
 #include "urldata.h"
 #include "warnless.h"
 #include "non-ascii.h"
 #include "escape.h"
-
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
-
-/* The last #include file should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
 #include "memdebug.h"
 
 /* Portable character check (remember EBCDIC). Do not use isalnum() because
    its behavior is altered by the current locale.
-   See http://tools.ietf.org/html/rfc3986#section-2.3
+   See https://tools.ietf.org/html/rfc3986#section-2.3
 */
 static bool Curl_isunreserved(unsigned char in)
 {
@@ -78,17 +75,24 @@ char *curl_unescape(const char *string, int length)
   return curl_easy_unescape(NULL, string, length, NULL);
 }
 
-char *curl_easy_escape(CURL *handle, const char *string, int inlength)
+char *curl_easy_escape(struct Curl_easy *data, const char *string,
+                       int inlength)
 {
-  size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
+  size_t alloc;
   char *ns;
   char *testing_ptr = NULL;
   unsigned char in; /* we need to treat the characters unsigned */
-  size_t newlen = alloc;
+  size_t newlen;
   size_t strindex=0;
   size_t length;
   CURLcode result;
 
+  if(inlength < 0)
+    return NULL;
+
+  alloc = (inlength?(size_t)inlength:strlen(string))+1;
+  newlen = alloc;
+
   ns = malloc(alloc);
   if(!ns)
     return NULL;
@@ -107,7 +111,7 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
         alloc *= 2;
         testing_ptr = realloc(ns, alloc);
         if(!testing_ptr) {
-          free( ns );
+          free(ns);
           return NULL;
         }
         else {
@@ -115,7 +119,7 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
         }
       }
 
-      result = Curl_convert_to_network(handle, &in, 1);
+      result = Curl_convert_to_network(data, &in, 1);
       if(result) {
         /* Curl_convert_to_network calls failf if unsuccessful */
         free(ns);
@@ -142,7 +146,7 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
  * *olen. If length == 0, the length is assumed to be strlen(string).
  *
  */
-CURLcode Curl_urldecode(struct SessionHandle *data,
+CURLcode Curl_urldecode(struct Curl_easy *data,
                         const char *string, size_t length,
                         char **ostring, size_t *olen,
                         bool reject_ctrl)
@@ -209,18 +213,20 @@ CURLcode Curl_urldecode(struct SessionHandle *data,
  * If length == 0, the length is assumed to be strlen(string).
  * If olen == NULL, no output length is stored.
  */
-char *curl_easy_unescape(CURL *handle, const char *string, int length,
-                         int *olen)
+char *curl_easy_unescape(struct Curl_easy *data, const char *string,
+                         int length, int *olen)
 {
   char *str = NULL;
-  size_t inputlen = length;
-  size_t outputlen;
-  CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
-                                FALSE);
-  if(res)
-    return NULL;
-  if(olen)
-    *olen = curlx_uztosi(outputlen);
+  if(length >= 0) {
+    size_t inputlen = length;
+    size_t outputlen;
+    CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
+                                  FALSE);
+    if(res)
+      return NULL;
+    if(olen)
+      *olen = curlx_uztosi(outputlen);
+  }
   return str;
 }
 
@@ -229,6 +235,5 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length,
    the library's memory system */
 void curl_free(void *p)
 {
-  if(p)
-    free(p);
+  free(p);
 }