diff options
author | Daniel Stenberg <daniel@haxx.se> | 2014-10-17 12:59:32 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2014-11-05 08:05:14 +0100 |
commit | b3875606925536f82fc61f3114ac42f29eaf6945 (patch) | |
tree | 229666d262222b2f34967e00fb5300ec69cda258 /lib/url.c | |
parent | d997c8b2f6521d78c6ef63411cfeb226f7927281 (diff) |
curl_easy_duphandle: CURLOPT_COPYPOSTFIELDS read out of bounds
When duplicating a handle, the data to post was duplicated using
strdup() when it could be binary and contain zeroes and it was not even
zero terminated! This caused read out of bounds crashes/segfaults.
Since the lib/strdup.c file no longer is easily shared with the curl
tool with this change, it now uses its own version instead.
Bug: http://curl.haxx.se/docs/adv_20141105.html
CVE: CVE-2014-3707
Reported-By: Symeon Paraschoudis
Diffstat (limited to 'lib/url.c')
-rw-r--r-- | lib/url.c | 22 |
1 files changed, 17 insertions, 5 deletions
@@ -125,6 +125,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out); #include "multihandle.h" #include "pipeline.h" #include "dotdot.h" +#include "strdup.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -270,8 +271,9 @@ void Curl_freeset(struct SessionHandle *data) { /* Free all dynamic strings stored in the data->set substructure. */ enum dupstring i; - for(i=(enum dupstring)0; i < STRING_LAST; i++) + for(i=(enum dupstring)0; i < STRING_LAST; i++) { Curl_safefree(data->set.str[i]); + } if(data->change.referer_alloc) { Curl_safefree(data->change.referer); @@ -356,14 +358,24 @@ CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src) memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); /* duplicate all strings */ - for(i=(enum dupstring)0; i< STRING_LAST; i++) { + for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { result = setstropt(&dst->set.str[i], src->set.str[i]); if(result) - break; + return result; } - /* If a failure occurred, freeing has to be performed externally. */ - return result; + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], src->set.postfieldsize); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + return CURLE_OK; } /* |