Commit 1759e1b
committed
net/http: move postdata ownership to http_t instead of copying it in net_http_new
net_http_new(conn) used to malloc + memcpy conn->postdata into a fresh
state->request.postdata buffer. For multi-MB POST bodies (file
uploads, netplay syncs, translation-service requests) that is a full
body-sized allocation + copy on every request dispatch.
The copy was unnecessary. conn is freed by the caller right after
net_http_new returns - both call sites in the tree follow the pattern
conn = net_http_connection_new(...);
/* optionally net_http_connection_set_content(conn, ...) */
h = net_http_new(conn);
/* ... drive h to completion ... */
net_http_delete(h);
net_http_connection_free(conn);
(see tasks/task_http.c:90 and libretro-common/samples/net/net_http_test.c:66)
and conn->postdata is only read by net_http_new and freed by
net_http_connection_free - no other code path observes or uses it.
The http_connection_t struct is forward-declared in the public
header, so external code cannot reach postdata by any other route.
Move ownership: assign state->request.postdata = conn->postdata, then
null conn->postdata and zero conn->contentlength so
net_http_connection_free does not double-free. One tracked allocation
flows from net_http_connection_new / net_http_connection_set_content
straight through to net_http_delete, with no intermediate copy.
This also removes an OOM failure mode: the previous code's malloc
could fail for large bodies on memory-constrained systems, and the
caller had to detect that via the (conn->postdata && conn->contentlength
&& !state->request.postdata) check further down. With ownership
transfer the setup cannot fail on the postdata path, so drop that
OOM check and document why.
Safety analysis:
- Threading: conn is single-owner during net_http_new (no concurrent
access; task_http.c's cb_http_conn_default is the only dispatcher
and holds conn exclusively for the duration of the call).
- Double-free: conn->postdata is nulled before net_http_new returns,
so net_http_connection_free's 'if (conn->postdata) free(...)' is a
no-op on the stolen field.
- OOM during the rest of net_http_new: the postdata is already
transferred by that point, so if any subsequent strdup fails and
we take the error path, net_http_delete(state) frees the stolen
postdata via its normal request.postdata teardown. No leak on
the error path.
- conn->contentlength is also zeroed; net_http_connection_free does
not look at it so this is purely for consistency, but it also
means anyone who later queries the emptied conn sees a correctly
empty body rather than a claim of nonzero content-length with a
NULL buffer.
contenttype / domain / path / method / useragent / headers still use
strdup - those are small and bounded, and keeping them as copies
preserves the property that conn is still 'complete' after
net_http_new for debugging or future reuse scenarios. Only postdata,
which dominates the memory cost, gets the ownership-transfer
treatment.1 parent f3b3d69 commit 1759e1b
1 file changed
Lines changed: 20 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
837 | 837 | | |
838 | 838 | | |
839 | 839 | | |
840 | | - | |
841 | | - | |
842 | | - | |
843 | | - | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
844 | 854 | | |
845 | 855 | | |
846 | 856 | | |
| |||
870 | 880 | | |
871 | 881 | | |
872 | 882 | | |
873 | | - | |
874 | 883 | | |
875 | 884 | | |
876 | 885 | | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
877 | 892 | | |
878 | 893 | | |
879 | 894 | | |
| |||
0 commit comments