Skip to content

Commit 747a710

Browse files
peffgitster
authored andcommitted
http-push: free curl header lists
To pass headers to curl, we have to allocate a curl_slist linked list and then feed it to curl_easy_setopt(). But the header list is not copied by curl, and must remain valid until we are finished with the request. A few spots in http-push get this right, freeing the list after finishing the request, but many do not. In most cases the fix is simple: we set up the curl slot, start it, and then use run_active_slot() to take it to completion. After that, we don't need the headers anymore and can call curl_slist_free_all(). But one case is trickier: when we do a MOVE request, we start the request but don't immediately finish it. It's possible we could change this to be more like the other requests, but I didn't want to get into risky refactoring of this code. So we need to stick the header list into the request struct and remember to free it later. Curiously, the struct already has a headers field for this purpose! It goes all the way back to 58e60dd (Add support for pushing to a remote repository using HTTP/DAV, 2005-11-02), but it doesn't look like it was ever used. We can make use of it just by assigning our headers to it, and there is already code in finish_request() to clean it up. This fixes several leaks triggered by t5540. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4324c6c commit 747a710

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

http-push.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,11 @@ static void start_move(struct transfer_request *request)
437437
if (start_active_slot(slot)) {
438438
request->slot = slot;
439439
request->state = RUN_MOVE;
440+
request->headers = dav_headers;
440441
} else {
441442
request->state = ABORTED;
442443
FREE_AND_NULL(request->url);
444+
curl_slist_free_all(dav_headers);
443445
}
444446
}
445447

@@ -1398,6 +1400,7 @@ static int update_remote(const struct object_id *oid, struct remote_lock *lock)
13981400
if (start_active_slot(slot)) {
13991401
run_active_slot(slot);
14001402
strbuf_release(&out_buffer.buf);
1403+
curl_slist_free_all(dav_headers);
14011404
if (results.curl_result != CURLE_OK) {
14021405
fprintf(stderr,
14031406
"PUT error: curl result=%d, HTTP code=%ld\n",
@@ -1407,6 +1410,7 @@ static int update_remote(const struct object_id *oid, struct remote_lock *lock)
14071410
}
14081411
} else {
14091412
strbuf_release(&out_buffer.buf);
1413+
curl_slist_free_all(dav_headers);
14101414
fprintf(stderr, "Unable to start PUT request\n");
14111415
return 0;
14121416
}
@@ -1516,6 +1520,7 @@ static void update_remote_info_refs(struct remote_lock *lock)
15161520
results.curl_result, results.http_code);
15171521
}
15181522
}
1523+
curl_slist_free_all(dav_headers);
15191524
}
15201525
strbuf_release(&buffer.buf);
15211526
}

0 commit comments

Comments
 (0)