http: fix segfault in handle_curl_result
authorJeff King <peff@peff.net>
Fri, 12 Oct 2012 06:22:49 +0000 (02:22 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 12 Oct 2012 16:42:31 +0000 (09:42 -0700)
When we create an http active_request_slot, we can set its
"results" pointer back to local storage. The http code will
fill in the details of how the request went, and we can
access those details even after the slot has been cleaned
up.

Commit 8809703 (http: factor out http error code handling)
switched us from accessing our local results struct directly
to accessing it via the "results" pointer of the slot. That
means we're accessing the slot after it has been marked as
finished, defeating the whole purpose of keeping the results
storage separate.

Most of the time this doesn't matter, as finishing the slot
does not actually clean up the pointer. However, when using
curl's multi interface with the dumb-http revision walker,
we might actually start a new request before handing control
back to the original caller. In that case, we may reuse the
slot, zeroing its results pointer, and leading the original
caller to segfault while looking for its results inside the
slot.

Instead, we need to pass a pointer to our local results
storage to the handle_curl_result function, rather than
relying on the pointer in the slot struct. This matches what
the original code did before the refactoring (which did not
use a separate function, and therefore just accessed the
results struct directly).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
http.c
http.h
remote-curl.c

diff --git a/http.c b/http.c
index 7c4a4072f24647bd3ab6cb6c24142d31c595bb86..9334386d194c5519c43889f261bf35e2efaea7f5 100644 (file)
--- a/http.c
+++ b/http.c
@@ -744,10 +744,9 @@ char *get_remote_object_url(const char *url, const char *hex,
        return strbuf_detach(&buf, NULL);
 }
 
-int handle_curl_result(struct active_request_slot *slot)
+int handle_curl_result(struct active_request_slot *slot,
+                      struct slot_results *results)
 {
-       struct slot_results *results = slot->results;
-
        if (results->curl_result == CURLE_OK) {
                credential_approve(&http_auth);
                return HTTP_OK;
@@ -818,7 +817,7 @@ static int http_request(const char *url, void *result, int target, int options)
 
        if (start_active_slot(slot)) {
                run_active_slot(slot);
-               ret = handle_curl_result(slot);
+               ret = handle_curl_result(slot, &results);
        } else {
                error("Unable to start HTTP request for %s", url);
                ret = HTTP_START_FAILED;
diff --git a/http.h b/http.h
index 12de25597df4077a52a44dace83093091514c10d..0bd1e849e1406c8c8a822c6ecc6de84d4b5e1798 100644 (file)
--- a/http.h
+++ b/http.h
@@ -78,7 +78,8 @@ extern int start_active_slot(struct active_request_slot *slot);
 extern void run_active_slot(struct active_request_slot *slot);
 extern void finish_active_slot(struct active_request_slot *slot);
 extern void finish_all_active_slots(void);
-extern int handle_curl_result(struct active_request_slot *slot);
+extern int handle_curl_result(struct active_request_slot *slot,
+                             struct slot_results *results);
 
 #ifdef USE_CURL_MULTI
 extern void fill_active_slots(void);
index 3ec474fc631eb3b433b3cadbd74aed4b83cba724..6054e47929f0ecc2a2a2465d7ee3413a3842f755 100644 (file)
@@ -369,7 +369,7 @@ static int run_slot(struct active_request_slot *slot)
        slot->curl_result = curl_easy_perform(slot->curl);
        finish_active_slot(slot);
 
-       err = handle_curl_result(slot);
+       err = handle_curl_result(slot, &results);
        if (err != HTTP_OK && err != HTTP_REAUTH) {
                error("RPC failed; result=%d, HTTP code = %ld",
                      results.curl_result, results.http_code);