summaryrefslogtreecommitdiff
path: root/user/netsurf/curl.patch
blob: c76a4dfa13194efe4889c78b33805365b475eb0d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
From 65b16f4c54eba748ee4c8b6580e6f08fc27534f8 Mon Sep 17 00:00:00 2001
From: Michael Drake <michael.drake@codethink.co.uk>
Date: Mon, 6 May 2019 17:12:14 +0100
Subject: Curl fetcher: Force HTTP1.1 to fix HTTP2 crash.

On ubuntu 19.4, curl is built with HTTP2 support, and we
segfault.

==18174== Invalid read of size 1
==18174==    at 0x4ACCE7D: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4B054B1: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AD398A: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AD7A0B: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AE93EE: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AEA8A8: curl_multi_perform (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x1F2EF7: fetch_curl_poll (curl.c:1209)
==18174==    by 0x1EEC5C: fetcher_poll (fetch.c:271)
==18174==    by 0x2A1ED4: schedule_run (schedule.c:160)
==18174==    by 0x15F941: framebuffer_run (gui.c:596)
==18174==    by 0x15F941: main (gui.c:2206)
==18174==  Address 0x9de95a8 is 3,224 bytes inside a block of size 6,304 free'd
==18174==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==18174==    by 0x4AD497B: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AE158C: curl_easy_cleanup (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x1F30DE: fetch_curl_cache_handle (curl.c:761)
==18174==    by 0x1F30DE: fetch_curl_stop (curl.c:840)
==18174==    by 0x1F30DE: fetch_curl_done (curl.c:1122)
==18174==    by 0x1F30DE: fetch_curl_poll (curl.c:1223)
==18174==    by 0x1EEC5C: fetcher_poll (fetch.c:271)
==18174==    by 0x2A1ED4: schedule_run (schedule.c:160)
==18174==    by 0x15F941: framebuffer_run (gui.c:596)
==18174==    by 0x15F941: main (gui.c:2206)
==18174==  Block was alloc'd at
==18174==    at 0x483AB35: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==18174==    by 0x4AE165F: curl_easy_duphandle (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x1F15EB: fetch_curl_get_handle (curl.c:738)
==18174==    by 0x1F15EB: fetch_curl_start (curl.c:750)
==18174==    by 0x1EEB22: fetch_dispatch_job (fetch.c:156)
==18174==    by 0x1EEB22: fetch_choose_and_dispatch (fetch.c:187)
==18174==    by 0x1EEB22: fetch_dispatch_jobs (fetch.c:247)
==18174==    by 0x1EF1BB: fetch_start (fetch.c:573)
==18174==    by 0x26C779: llcache_object_refetch (llcache.c:916)
==18174==    by 0x26D5E4: llcache_object_fetch (llcache.c:979)
==18174==    by 0x26D5E4: llcache_object_retrieve_from_cache (llcache.c:1767)
==18174==    by 0x26D5E4: llcache_object_retrieve (llcache.c:1865)
==18174==    by 0x26E42C: llcache_fetch_redirect (llcache.c:2110)
==18174==    by 0x26E42C: llcache_fetch_callback (llcache.c:2810)
==18174==    by 0x1F1295: fetch_curl_process_headers (curl.c:922)
==18174==    by 0x1F13A0: fetch_curl_data (curl.c:1324)
==18174==    by 0x4ACD4C3: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
==18174==    by 0x4AE00DA: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0)
---
 content/fetchers/curl.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index 7ce7c5b48..4602f6aea 100644
--- a/netsurf/content/fetchers/curl.c
+++ b/netsurf/content/fetchers/curl.c
@@ -1519,6 +1519,10 @@ nserror fetch_curl_register(void)
 	if (nsoption_bool(suppress_curl_debug)) {
 		SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
 	}
+
+	/* Currently we explode if curl uses HTTP2, so force 1.1. */
+	SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+
 	SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
 	SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
 	SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
-- 
cgit v1.2.1


From 3d80e825e1c77ece19c21ed1cc568049856a44de Mon Sep 17 00:00:00 2001
From: Daniel Silverstone <dsilvers@digital-scurf.org>
Date: Wed, 5 Jun 2019 19:51:47 +0100
Subject: content/fetchers/curl.c: Defer fetch start if inside cURL

In order to cope better with modern cURL which prevents making
cURL calls when inside a callback from within cURL, defer fetch
start when we are processing in `fetch_curl_data()`.

Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
---
 content/fetchers/curl.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

(limited to 'content/fetchers/curl.c')

diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index 63b9ea115..c039429a5 100644
--- a/netsurf/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -142,6 +142,9 @@ static char fetch_error_buffer[CURL_ERROR_SIZE];
 /** Proxy authentication details. */
 static char fetch_proxy_userpwd[100];
 
+/** Interlock to prevent initiation during callbacks */
+static bool inside_curl = false;
+
 
 /* OpenSSL 1.0.x to 1.1.0 certificate reference counting changed
  * LibreSSL declares its OpenSSL version as 2.1 but only supports the old way
@@ -710,6 +713,9 @@ fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
 	code = fetch_curl_set_options(fetch);
 	if (code != CURLE_OK) {
 		fetch->curl_handle = 0;
+		/* The handle maybe went bad, eat it */
+		NSLOG(netsurf, WARNING, "cURL handle maybe went bad, retry later");
+		curl_easy_cleanup(handle);
 		return false;
 	}
 
@@ -747,6 +753,10 @@ static CURL *fetch_curl_get_handle(lwc_string *host)
 static bool fetch_curl_start(void *vfetch)
 {
 	struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
+	if (inside_curl) {
+		NSLOG(netsurf, DEBUG, "Deferring fetch because we're inside cURL");
+		return false;
+	}
 	return fetch_curl_initiate_fetch(fetch,
 			fetch_curl_get_handle(fetch->host));
 }
@@ -1317,6 +1327,9 @@ static size_t fetch_curl_data(char *data, size_t size, size_t nmemb, void *_f)
 	CURLcode code;
 	fetch_msg msg;
 
+	assert(inside_curl == false);
+	inside_curl = true;
+
 	/* ensure we only have to get this information once */
 	if (!f->http_code) {
 		code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE,
@@ -1330,11 +1343,13 @@ static size_t fetch_curl_data(char *data, size_t size, size_t nmemb, void *_f)
 	 */
 	if (f->http_code == 401) {
 		f->http_code = 0;
+		inside_curl = false;
 		return size * nmemb;
 	}
 
 	if (f->abort || (!f->had_headers && fetch_curl_process_headers(f))) {
 		f->stopped = true;
+		inside_curl = false;
 		return 0;
 	}
 
@@ -1344,6 +1359,7 @@ static size_t fetch_curl_data(char *data, size_t size, size_t nmemb, void *_f)
 	msg.data.header_or_data.len = size * nmemb;
 	fetch_send_callback(&msg, f->fetch_handle);
 
+	inside_curl = false;
 	if (f->abort) {
 		f->stopped = true;
 		return 0;
-- 
cgit v1.2.1