Merge ~bryce/ubuntu/+source/php7.4:sru-lp1887826-curlfile-post-focal into ubuntu/+source/php7.4:ubuntu/focal-devel
- Git
- lp:~bryce/ubuntu/+source/php7.4
- sru-lp1887826-curlfile-post-focal
- Merge into ubuntu/focal-devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Bryce Harrington | ||||
Approved revision: | 6ad8d68d01f2ad47035910fe397db8724c849274 | ||||
Merge reported by: | Bryce Harrington | ||||
Merged at revision: | 6ad8d68d01f2ad47035910fe397db8724c849274 | ||||
Proposed branch: | ~bryce/ubuntu/+source/php7.4:sru-lp1887826-curlfile-post-focal | ||||
Merge into: | ubuntu/+source/php7.4:ubuntu/focal-devel | ||||
Diff against target: |
615 lines (+587/-0) 4 files modified
debian/changelog (+15/-0) debian/patches/0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch (+501/-0) debian/patches/0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch (+68/-0) debian/patches/series (+3/-0) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christian Ehrhardt (community) | Approve | ||
Canonical Server | Pending | ||
Review via email: mp+390343@code.launchpad.net |
Commit message
Description of the change
This addresses a server-next requested SRU of a fix for "CURLFile POST missing Content-Length header" (LP: #1887826)
The upstream fix for the bug applies on top of another, related CURL fix, so I have included both.
PPA: https:/
Christian Ehrhardt (paelzer) wrote : | # |
Christian Ehrhardt (paelzer) wrote : | # |
SRU Template is mostly good, but requires an [Regression Potential] still.
Christian Ehrhardt (paelzer) wrote : | # |
Actually headers would be really nice, while I can find upstream from the patches, to know that they are for https:/
The changes are quite many, but if one excludes the tests no more.
0042 (the actual fix) is small and LGTM.
0041 (needed for the other to apply) - this one is much bigger. It has further different behavior if libcurl >7.56.0 which is true for Focal (7.68.0-
Did you run these tests that got updated with the change? Might be build time checks ...
Christian Ehrhardt (paelzer) wrote : | # |
Yeah all those tests ran on build
https:/
That gives some extra confidence boost.
Christian Ehrhardt (paelzer) wrote : | # |
Summary:
- quite a change but LGTM
- please add regression considerations to SRU
- if not too much add extended patch headers
Under these conditions +1 to that SRU
Bryce Harrington (bryce) wrote : | # |
Thanks, I've added the DEP3 and force pushed, and updated the regression section on the SRU.
$ git push pkg focal-devel
Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 12 threads
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 7.08 KiB | 7.08 MiB/s, done.
Total 11 (delta 7), reused 0 (delta 0)
remote:
remote: Create a merge proposal for 'ubuntu/
remote: https:/
remote:
To ssh://git.
f80afec1d.
$ dput ubuntu php7.4_
Checking signature on .changes
gpg: /home/bryce/
Checking signature on .dsc
gpg: /home/bryce/
Uploading to ubuntu (via ftp to upload.ubuntu.com):
Uploading php7.4_
Uploading php7.4_
Uploading php7.4_
Uploading php7.4_
Successfully uploaded packages.
Bryce Harrington (bryce) wrote : | # |
And per tests, yes with PHP I always do a full build, which runs the testsuite. The autopkgtests don't run locally (I think junk left by the build process confuses one of the tests) but the local build tends to catch most of the issues in practice.
Christian Ehrhardt (paelzer) wrote : | # |
FYI Still in proposed:
php7.4 | 7.4.3-4ubuntu2.3 | focal-proposed | source, all
Most seemed to be flaky arm boxes, but the fails on php-parser/4.2.2-2 are on all architectures and might need a look
Bryce Harrington (bryce) wrote : | # |
Yes, I had looked at that a couple weeks back, it's this bug:
https:/
Bryce Harrington (bryce) wrote : | # |
This has migrated
Preview Diff
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index c679a9c..6b4387b 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,18 @@ |
6 | +php7.4 (7.4.3-4ubuntu2.3~focal1) focal; urgency=medium |
7 | + |
8 | + * ppa build for focal |
9 | + |
10 | + -- Bryce Harrington <bryce@canonical.com> Fri, 04 Sep 2020 20:11:34 -0700 |
11 | + |
12 | +php7.4 (7.4.3-4ubuntu2.3) focal; urgency=medium |
13 | + |
14 | + * d/p/0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch, |
15 | + d/p/0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch: |
16 | + Fix issue with cURL causing chunked mode for file transfers. |
17 | + (LP: #1887826) |
18 | + |
19 | + -- Bryce Harrington <bryce@canonical.com> Thu, 03 Sep 2020 13:06:34 -0700 |
20 | + |
21 | php7.4 (7.4.3-4ubuntu2.2) focal-security; urgency=medium |
22 | |
23 | * SECURITY UPDATE: Denial of service through oversized memory allocated |
24 | diff --git a/debian/patches/0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch b/debian/patches/0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch |
25 | new file mode 100644 |
26 | index 0000000..94f9edf |
27 | --- /dev/null |
28 | +++ b/debian/patches/0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch |
29 | @@ -0,0 +1,501 @@ |
30 | +From 2d0dec91a53bddbf9f9e09d9c58188515907d650 Mon Sep 17 00:00:00 2001 |
31 | +From: "Christoph M. Becker" <cmbecker69@gmx.de> |
32 | +Date: Tue, 4 Feb 2020 11:01:33 +0100 |
33 | +Subject: [PATCH] Fix #79019: Copied cURL handles upload empty file |
34 | + |
35 | +To cater to `curl_copy_handle()` of cURL handles with attached |
36 | +`CURLFile`s, we must not attach the opened stream, because the stream |
37 | +may not be seekable, so that we could rewind, when the same stream is |
38 | +going to be uploaded multiple times. Instead, we're opening the stream |
39 | +lazily in the read callback. |
40 | + |
41 | +Since `curl_multi_perfom()` processes easy handles asynchronously, we |
42 | +have no control of the operation sequence. Since duplicated cURL |
43 | +handles may be used with multi handles, we cannot use a single arg |
44 | +structure, but actually have to rebuild the whole mime structure on |
45 | +handle duplication and attach this to the new handle. |
46 | + |
47 | +In order to better test this behavior, we extend the test responder to |
48 | +print the size of the upload, and patch the existing tests accordingly. |
49 | + |
50 | +Origin: upstream, https://github.com/php/php-src/commit/2d0dec91a53bddbf9f9e09d9c58188515907d650 |
51 | +Bug: https://bugs.php.net/bug.php?id=79019 |
52 | +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/php7.4/+bug/1887826 |
53 | + |
54 | +diff --git a/ext/curl/interface.c b/ext/curl/interface.c |
55 | +index 07026e1d9c..668f7a71d9 100644 |
56 | +--- a/ext/curl/interface.c |
57 | ++++ b/ext/curl/interface.c |
58 | +@@ -1795,11 +1795,20 @@ static void curl_free_post(void **post) |
59 | + } |
60 | + /* }}} */ |
61 | + |
62 | +-/* {{{ curl_free_stream |
63 | ++struct mime_data_cb_arg { |
64 | ++ zend_string *filename; |
65 | ++ php_stream *stream; |
66 | ++}; |
67 | ++ |
68 | ++/* {{{ curl_free_cb_arg |
69 | + */ |
70 | +-static void curl_free_stream(void **post) |
71 | ++static void curl_free_cb_arg(void **cb_arg_p) |
72 | + { |
73 | +- php_stream_close((php_stream *)*post); |
74 | ++ struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) *cb_arg_p; |
75 | ++ |
76 | ++ ZEND_ASSERT(cb_arg->stream == NULL); |
77 | ++ zend_string_release(cb_arg->filename); |
78 | ++ efree(cb_arg); |
79 | + } |
80 | + /* }}} */ |
81 | + |
82 | +@@ -1900,11 +1909,13 @@ php_curl *alloc_curl_handle() |
83 | + |
84 | + zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t)curl_free_string, 0); |
85 | + zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0); |
86 | +- zend_llist_init(&ch->to_free->stream, sizeof(php_stream *), (llist_dtor_func_t)curl_free_stream, 0); |
87 | ++ zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t)curl_free_cb_arg, 0); |
88 | + |
89 | + ch->to_free->slist = emalloc(sizeof(HashTable)); |
90 | + zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); |
91 | +- |
92 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
93 | ++ ZVAL_UNDEF(&ch->postfields); |
94 | ++#endif |
95 | + return ch; |
96 | + } |
97 | + /* }}} */ |
98 | +@@ -2094,62 +2105,48 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) |
99 | + (*source->clone)++; |
100 | + } |
101 | + |
102 | +-/* {{{ proto resource curl_copy_handle(resource ch) |
103 | +- Copy a cURL handle along with all of it's preferences */ |
104 | +-PHP_FUNCTION(curl_copy_handle) |
105 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
106 | ++static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */ |
107 | + { |
108 | +- CURL *cp; |
109 | +- zval *zid; |
110 | +- php_curl *ch, *dupch; |
111 | +- |
112 | +- ZEND_PARSE_PARAMETERS_START(1,1) |
113 | +- Z_PARAM_RESOURCE(zid) |
114 | +- ZEND_PARSE_PARAMETERS_END(); |
115 | ++ struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg; |
116 | ++ ssize_t numread; |
117 | + |
118 | +- if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { |
119 | +- RETURN_FALSE; |
120 | ++ if (cb_arg->stream == NULL) { |
121 | ++ if (!(cb_arg->stream = php_stream_open_wrapper(ZSTR_VAL(cb_arg->filename), "rb", IGNORE_PATH, NULL))) { |
122 | ++ return CURL_READFUNC_ABORT; |
123 | ++ } |
124 | + } |
125 | +- |
126 | +- cp = curl_easy_duphandle(ch->cp); |
127 | +- if (!cp) { |
128 | +- php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle"); |
129 | +- RETURN_FALSE; |
130 | ++ numread = php_stream_read(cb_arg->stream, buffer, nitems * size); |
131 | ++ if (numread < 0) { |
132 | ++ php_stream_close(cb_arg->stream); |
133 | ++ cb_arg->stream = NULL; |
134 | ++ return CURL_READFUNC_ABORT; |
135 | + } |
136 | +- |
137 | +- dupch = alloc_curl_handle(); |
138 | +- dupch->cp = cp; |
139 | +- |
140 | +- _php_setup_easy_copy_handlers(dupch, ch); |
141 | +- |
142 | +- Z_ADDREF_P(zid); |
143 | +- |
144 | +- ZVAL_RES(return_value, zend_register_resource(dupch, le_curl)); |
145 | +- dupch->res = Z_RES_P(return_value); |
146 | ++ return numread; |
147 | + } |
148 | + /* }}} */ |
149 | + |
150 | +-#if LIBCURL_VERSION_NUM >= 0x073800 |
151 | +-static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */ |
152 | ++static int seek_cb(void *arg, curl_off_t offset, int origin) /* {{{ */ |
153 | + { |
154 | +- php_stream *stream = (php_stream *) arg; |
155 | +- ssize_t numread = php_stream_read(stream, buffer, nitems * size); |
156 | ++ struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg; |
157 | ++ int res; |
158 | + |
159 | +- if (numread < 0) { |
160 | +- return CURL_READFUNC_ABORT; |
161 | ++ if (cb_arg->stream == NULL) { |
162 | ++ return CURL_SEEKFUNC_CANTSEEK; |
163 | + } |
164 | +- return numread; |
165 | ++ res = php_stream_seek(cb_arg->stream, offset, origin); |
166 | ++ return res == SUCCESS ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK; |
167 | + } |
168 | + /* }}} */ |
169 | + |
170 | +-static int seek_cb(void *arg, curl_off_t offset, int origin) /* {{{ */ |
171 | ++static void free_cb(void *arg) /* {{{ */ |
172 | + { |
173 | +- php_stream *stream = (php_stream *) arg; |
174 | +- int res = php_stream_seek(stream, offset, origin); |
175 | ++ struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg; |
176 | + |
177 | +- if (res) { |
178 | +- return CURL_SEEKFUNC_CANTSEEK; |
179 | ++ if (cb_arg->stream != NULL) { |
180 | ++ php_stream_close(cb_arg->stream); |
181 | ++ cb_arg->stream = NULL; |
182 | + } |
183 | +- return CURL_SEEKFUNC_OK; |
184 | + } |
185 | + /* }}} */ |
186 | + #endif |
187 | +@@ -2160,7 +2157,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
188 | + zval *current; |
189 | + HashTable *postfields; |
190 | + zend_string *string_key; |
191 | +- zend_ulong num_key; |
192 | ++ zend_ulong num_key; |
193 | + #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
194 | + curl_mime *mime = NULL; |
195 | + curl_mimepart *part; |
196 | +@@ -2202,7 +2199,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
197 | + zval *prop, rv; |
198 | + char *type = NULL, *filename = NULL; |
199 | + #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
200 | +- php_stream *stream; |
201 | ++ struct mime_data_cb_arg *cb_arg; |
202 | + #endif |
203 | + |
204 | + prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv); |
205 | +@@ -2225,24 +2222,25 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
206 | + } |
207 | + |
208 | + #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
209 | +- if (!(stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", IGNORE_PATH, NULL))) { |
210 | +- zend_string_release_ex(string_key, 0); |
211 | +- return FAILURE; |
212 | +- } |
213 | ++ zval_ptr_dtor(&ch->postfields); |
214 | ++ ZVAL_COPY(&ch->postfields, zpostfields); |
215 | ++ |
216 | ++ cb_arg = emalloc(sizeof *cb_arg); |
217 | ++ cb_arg->filename = zend_string_copy(postval); |
218 | ++ cb_arg->stream = NULL; |
219 | ++ |
220 | + part = curl_mime_addpart(mime); |
221 | + if (part == NULL) { |
222 | +- php_stream_close(stream); |
223 | + zend_string_release_ex(string_key, 0); |
224 | + return FAILURE; |
225 | + } |
226 | + if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK |
227 | +- || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, NULL, stream)) != CURLE_OK |
228 | ++ || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, free_cb, cb_arg)) != CURLE_OK |
229 | + || (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK |
230 | + || (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) { |
231 | +- php_stream_close(stream); |
232 | + error = form_error; |
233 | + } |
234 | +- zend_llist_add_element(&ch->to_free->stream, &stream); |
235 | ++ zend_llist_add_element(&ch->to_free->stream, &cb_arg); |
236 | + #else |
237 | + form_error = curl_formadd(&first, &last, |
238 | + CURLFORM_COPYNAME, ZSTR_VAL(string_key), |
239 | +@@ -2310,11 +2308,60 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
240 | + zend_llist_add_element(&ch->to_free->post, &first); |
241 | + error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first); |
242 | + #endif |
243 | ++ |
244 | + SAVE_CURL_ERROR(ch, error); |
245 | + return error == CURLE_OK ? SUCCESS : FAILURE; |
246 | + } |
247 | + /* }}} */ |
248 | + |
249 | ++/* {{{ proto resource curl_copy_handle(resource ch) |
250 | ++ Copy a cURL handle along with all of it's preferences */ |
251 | ++PHP_FUNCTION(curl_copy_handle) |
252 | ++{ |
253 | ++ CURL *cp; |
254 | ++ zval *zid; |
255 | ++ php_curl *ch, *dupch; |
256 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
257 | ++ zval *postfields; |
258 | ++#endif |
259 | ++ |
260 | ++ ZEND_PARSE_PARAMETERS_START(1,1) |
261 | ++ Z_PARAM_RESOURCE(zid) |
262 | ++ ZEND_PARSE_PARAMETERS_END(); |
263 | ++ |
264 | ++ if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { |
265 | ++ RETURN_FALSE; |
266 | ++ } |
267 | ++ |
268 | ++ cp = curl_easy_duphandle(ch->cp); |
269 | ++ if (!cp) { |
270 | ++ php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle"); |
271 | ++ RETURN_FALSE; |
272 | ++ } |
273 | ++ |
274 | ++ dupch = alloc_curl_handle(); |
275 | ++ dupch->cp = cp; |
276 | ++ |
277 | ++ _php_setup_easy_copy_handlers(dupch, ch); |
278 | ++ |
279 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
280 | ++ postfields = &ch->postfields; |
281 | ++ if (Z_TYPE_P(postfields) != IS_UNDEF) { |
282 | ++ if (build_mime_structure_from_hash(dupch, postfields) != SUCCESS) { |
283 | ++ _php_curl_close_ex(dupch); |
284 | ++ php_error_docref(NULL, E_WARNING, "Cannot rebuild mime structure"); |
285 | ++ RETURN_FALSE; |
286 | ++ } |
287 | ++ } |
288 | ++#endif |
289 | ++ |
290 | ++ Z_ADDREF_P(zid); |
291 | ++ |
292 | ++ ZVAL_RES(return_value, zend_register_resource(dupch, le_curl)); |
293 | ++ dupch->res = Z_RES_P(return_value); |
294 | ++} |
295 | ++/* }}} */ |
296 | ++ |
297 | + static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ */ |
298 | + { |
299 | + CURLcode error = CURLE_OK; |
300 | +@@ -3613,6 +3660,9 @@ static void _php_curl_close_ex(php_curl *ch) |
301 | + #endif |
302 | + |
303 | + efree(ch->handlers); |
304 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
305 | ++ zval_ptr_dtor(&ch->postfields); |
306 | ++#endif |
307 | + efree(ch); |
308 | + } |
309 | + /* }}} */ |
310 | +diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h |
311 | +index 5d93f16c03..f4f722e134 100644 |
312 | +--- a/ext/curl/php_curl.h |
313 | ++++ b/ext/curl/php_curl.h |
314 | +@@ -183,6 +183,9 @@ typedef struct { |
315 | + struct _php_curl_error err; |
316 | + zend_bool in_callback; |
317 | + uint32_t* clone; |
318 | ++#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
319 | ++ zval postfields; |
320 | ++#endif |
321 | + } php_curl; |
322 | + |
323 | + #define CURLOPT_SAFE_UPLOAD -1 |
324 | +diff --git a/ext/curl/tests/bug27023.phpt b/ext/curl/tests/bug27023.phpt |
325 | +index 3d649b3f73..f985c192b8 100644 |
326 | +--- a/ext/curl/tests/bug27023.phpt |
327 | ++++ b/ext/curl/tests/bug27023.phpt |
328 | +@@ -38,7 +38,7 @@ var_dump(curl_exec($ch)); |
329 | + curl_close($ch); |
330 | + ?> |
331 | + --EXPECTF-- |
332 | +-string(%d) "curl_testdata1.txt|application/octet-stream" |
333 | +-string(%d) "curl_testdata1.txt|text/plain" |
334 | +-string(%d) "foo.txt|application/octet-stream" |
335 | +-string(%d) "foo.txt|text/plain" |
336 | ++string(%d) "curl_testdata1.txt|application/octet-stream|6" |
337 | ++string(%d) "curl_testdata1.txt|text/plain|6" |
338 | ++string(%d) "foo.txt|application/octet-stream|6" |
339 | ++string(%d) "foo.txt|text/plain|6" |
340 | +diff --git a/ext/curl/tests/bug77711.phpt b/ext/curl/tests/bug77711.phpt |
341 | +index 148c26322a..8ef5e48891 100644 |
342 | +--- a/ext/curl/tests/bug77711.phpt |
343 | ++++ b/ext/curl/tests/bug77711.phpt |
344 | +@@ -24,7 +24,7 @@ curl_close($ch); |
345 | + ===DONE=== |
346 | + --EXPECTF-- |
347 | + bool(true) |
348 | +-string(%d) "АБВ.txt|application/octet-stream" |
349 | ++string(%d) "АБВ.txt|application/octet-stream|5" |
350 | + ===DONE=== |
351 | + --CLEAN-- |
352 | + <?php |
353 | +diff --git a/ext/curl/tests/curl_copy_handle_variation3.phpt b/ext/curl/tests/curl_copy_handle_variation3.phpt |
354 | +index 18f35f71b1..32946bb4df 100644 |
355 | +--- a/ext/curl/tests/curl_copy_handle_variation3.phpt |
356 | ++++ b/ext/curl/tests/curl_copy_handle_variation3.phpt |
357 | +@@ -29,8 +29,8 @@ curl_close($ch2); |
358 | + ===DONE=== |
359 | + --EXPECTF-- |
360 | + bool(true) |
361 | +-string(%d) "АБВ.txt|application/octet-stream" |
362 | +-string(%d) "АБВ.txt|application/octet-stream" |
363 | ++string(%d) "АБВ.txt|application/octet-stream|5" |
364 | ++string(%d) "АБВ.txt|application/octet-stream|5" |
365 | + ===DONE=== |
366 | + --CLEAN-- |
367 | + <?php |
368 | +diff --git a/ext/curl/tests/curl_copy_handle_variation4.phpt b/ext/curl/tests/curl_copy_handle_variation4.phpt |
369 | +new file mode 100644 |
370 | +index 0000000000..e160c06c64 |
371 | +--- /dev/null |
372 | ++++ b/ext/curl/tests/curl_copy_handle_variation4.phpt |
373 | +@@ -0,0 +1,46 @@ |
374 | ++--TEST-- |
375 | ++curl_copy_handle() allows to post CURLFile multiple times with curl_multi_exec() |
376 | ++--SKIPIF-- |
377 | ++<?php include 'skipif.inc'; ?> |
378 | ++--FILE-- |
379 | ++<?php |
380 | ++include 'server.inc'; |
381 | ++$host = curl_cli_server_start(); |
382 | ++ |
383 | ++$ch1 = curl_init(); |
384 | ++curl_setopt($ch1, CURLOPT_SAFE_UPLOAD, 1); |
385 | ++curl_setopt($ch1, CURLOPT_URL, "{$host}/get.php?test=file"); |
386 | ++// curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); |
387 | ++ |
388 | ++$filename = __DIR__ . '/АБВ.txt'; |
389 | ++file_put_contents($filename, "Test."); |
390 | ++$file = curl_file_create($filename); |
391 | ++$params = array('file' => $file); |
392 | ++var_dump(curl_setopt($ch1, CURLOPT_POSTFIELDS, $params)); |
393 | ++ |
394 | ++$ch2 = curl_copy_handle($ch1); |
395 | ++$ch3 = curl_copy_handle($ch1); |
396 | ++ |
397 | ++$mh = curl_multi_init(); |
398 | ++curl_multi_add_handle($mh, $ch1); |
399 | ++curl_multi_add_handle($mh, $ch2); |
400 | ++do { |
401 | ++ $status = curl_multi_exec($mh, $active); |
402 | ++ if ($active) { |
403 | ++ curl_multi_select($mh); |
404 | ++ } |
405 | ++} while ($active && $status == CURLM_OK); |
406 | ++ |
407 | ++curl_multi_remove_handle($mh, $ch1); |
408 | ++curl_multi_remove_handle($mh, $ch2); |
409 | ++curl_multi_remove_handle($mh, $ch3); |
410 | ++curl_multi_close($mh); |
411 | ++?> |
412 | ++===DONE=== |
413 | ++--EXPECTF-- |
414 | ++bool(true) |
415 | ++АБВ.txt|application/octet-stream|5АБВ.txt|application/octet-stream|5===DONE=== |
416 | ++--CLEAN-- |
417 | ++<?php |
418 | ++@unlink(__DIR__ . '/АБВ.txt'); |
419 | ++?> |
420 | +diff --git a/ext/curl/tests/curl_copy_handle_variation5.phpt b/ext/curl/tests/curl_copy_handle_variation5.phpt |
421 | +new file mode 100644 |
422 | +index 0000000000..019704e6c8 |
423 | +--- /dev/null |
424 | ++++ b/ext/curl/tests/curl_copy_handle_variation5.phpt |
425 | +@@ -0,0 +1,52 @@ |
426 | ++--TEST-- |
427 | ++curl_copy_handle() allows to post CURLFile multiple times if postfields change |
428 | ++--SKIPIF-- |
429 | ++<?php include 'skipif.inc'; ?> |
430 | ++--FILE-- |
431 | ++<?php |
432 | ++include 'server.inc'; |
433 | ++$host = curl_cli_server_start(); |
434 | ++ |
435 | ++$ch1 = curl_init(); |
436 | ++curl_setopt($ch1, CURLOPT_SAFE_UPLOAD, 1); |
437 | ++curl_setopt($ch1, CURLOPT_URL, "{$host}/get.php?test=file"); |
438 | ++curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); |
439 | ++ |
440 | ++$filename = __DIR__ . '/abc.txt'; |
441 | ++file_put_contents($filename, "Test."); |
442 | ++$file = curl_file_create($filename); |
443 | ++$params = array('file' => $file); |
444 | ++var_dump(curl_setopt($ch1, CURLOPT_POSTFIELDS, $params)); |
445 | ++ |
446 | ++$ch2 = curl_copy_handle($ch1); |
447 | ++ |
448 | ++$filename = __DIR__ . '/def.txt'; |
449 | ++file_put_contents($filename, "Other test."); |
450 | ++$file = curl_file_create($filename); |
451 | ++$params = array('file' => $file); |
452 | ++var_dump(curl_setopt($ch2, CURLOPT_POSTFIELDS, $params)); |
453 | ++ |
454 | ++$ch3 = curl_copy_handle($ch2); |
455 | ++ |
456 | ++var_dump(curl_exec($ch1)); |
457 | ++curl_close($ch1); |
458 | ++ |
459 | ++var_dump(curl_exec($ch2)); |
460 | ++curl_close($ch2); |
461 | ++ |
462 | ++var_dump(curl_exec($ch3)); |
463 | ++curl_close($ch3); |
464 | ++?> |
465 | ++===DONE=== |
466 | ++--EXPECTF-- |
467 | ++bool(true) |
468 | ++bool(true) |
469 | ++string(%d) "abc.txt|application/octet-stream|5" |
470 | ++string(%d) "def.txt|application/octet-stream|11" |
471 | ++string(%d) "def.txt|application/octet-stream|11" |
472 | ++===DONE=== |
473 | ++--CLEAN-- |
474 | ++<?php |
475 | ++@unlink(__DIR__ . '/abc.txt'); |
476 | ++@unlink(__DIR__ . '/def.txt'); |
477 | ++?> |
478 | +diff --git a/ext/curl/tests/curl_file_upload.phpt b/ext/curl/tests/curl_file_upload.phpt |
479 | +index 73a2f363fb..1626f8117c 100644 |
480 | +--- a/ext/curl/tests/curl_file_upload.phpt |
481 | ++++ b/ext/curl/tests/curl_file_upload.phpt |
482 | +@@ -60,15 +60,15 @@ var_dump(curl_exec($ch)); |
483 | + curl_close($ch); |
484 | + ?> |
485 | + --EXPECTF-- |
486 | +-string(%d) "curl_testdata1.txt|application/octet-stream" |
487 | +-string(%d) "curl_testdata1.txt|text/plain" |
488 | +-string(%d) "foo.txt|application/octet-stream" |
489 | +-string(%d) "foo.txt|text/plain" |
490 | ++string(%d) "curl_testdata1.txt|application/octet-stream|6" |
491 | ++string(%d) "curl_testdata1.txt|text/plain|6" |
492 | ++string(%d) "foo.txt|application/octet-stream|6" |
493 | ++string(%d) "foo.txt|text/plain|6" |
494 | + string(%d) "text/plain" |
495 | + string(%d) "%s/curl_testdata1.txt" |
496 | +-string(%d) "curl_testdata1.txt|text/plain" |
497 | ++string(%d) "curl_testdata1.txt|text/plain|6" |
498 | + string(%d) "foo.txt" |
499 | +-string(%d) "foo.txt|application/octet-stream" |
500 | ++string(%d) "foo.txt|application/octet-stream|6" |
501 | + |
502 | + Warning: curl_setopt(): Disabling safe uploads is no longer supported in %s on line %d |
503 | + string(0) "" |
504 | +diff --git a/ext/curl/tests/curl_file_upload_stream.phpt b/ext/curl/tests/curl_file_upload_stream.phpt |
505 | +index 03c85b4b82..949cccbc31 100644 |
506 | +--- a/ext/curl/tests/curl_file_upload_stream.phpt |
507 | ++++ b/ext/curl/tests/curl_file_upload_stream.phpt |
508 | +@@ -24,5 +24,5 @@ curl_close($ch); |
509 | + ===DONE=== |
510 | + --EXPECT-- |
511 | + bool(true) |
512 | +-string(21) "i-love-php|text/plain" |
513 | ++string(24) "i-love-php|text/plain|11" |
514 | + ===DONE=== |
515 | +diff --git a/ext/curl/tests/responder/get.inc b/ext/curl/tests/responder/get.inc |
516 | +index f9269745f6..64ab267d50 100644 |
517 | +--- a/ext/curl/tests/responder/get.inc |
518 | ++++ b/ext/curl/tests/responder/get.inc |
519 | +@@ -28,7 +28,7 @@ |
520 | + break; |
521 | + case 'file': |
522 | + if (isset($_FILES['file'])) { |
523 | +- echo $_FILES['file']['name'] . '|' . $_FILES['file']['type']; |
524 | ++ echo $_FILES['file']['name'] . '|' . $_FILES['file']['type'] . '|' . $_FILES['file']['size']; |
525 | + } |
526 | + break; |
527 | + case 'method': |
528 | +-- |
529 | +2.25.1 |
530 | + |
531 | diff --git a/debian/patches/0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch b/debian/patches/0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch |
532 | new file mode 100644 |
533 | index 0000000..a2bfafc |
534 | --- /dev/null |
535 | +++ b/debian/patches/0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch |
536 | @@ -0,0 +1,68 @@ |
537 | +From fc8b3ab7cbb4f5e77584babeaf25b9bf16f524cd Mon Sep 17 00:00:00 2001 |
538 | +From: "Christoph M. Becker" <cmbecker69@gmx.de> |
539 | +Date: Mon, 2 Mar 2020 18:45:12 +0100 |
540 | +Subject: [PATCH] Fix #79013: Content-Length missing when posting a curlFile |
541 | + with curl |
542 | + |
543 | +Unfortunately, some Webservers (e.g. IIS) do not implement the (F)CGI |
544 | +specifications correctly wrt. chunked uploads (i.e. Transfer-encoding: |
545 | +chunked), but instead pass -1 as CONTENT_LENGTH to the CGI |
546 | +application. However, our (F)CFI SAPIs (i.e. cgi and cgi-fcgi) do not |
547 | +support this. |
548 | + |
549 | +Therefore we try to retrieve the stream size in advance and pass it to |
550 | +`curl_mime_data_cb()` to prevent libcurl from doing chunked uploads. |
551 | +This is basically the same approach that `curl_mime_filedata()` |
552 | +implements, except that we are keeping already opened streams open for |
553 | +the `read_cb()`. |
554 | + |
555 | +Origin: upstream, https://github.com/php/php-src/commit/fc8b3ab7cbb4f5e77584babeaf25b9bf16f524cd |
556 | +Bug: https://bugs.php.net/bug.php?id=79013 |
557 | +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/php7.4/+bug/1887826 |
558 | + |
559 | +diff --git a/ext/curl/interface.c b/ext/curl/interface.c |
560 | +index 668f7a71d9..45e41ba49e 100644 |
561 | +--- a/ext/curl/interface.c |
562 | ++++ b/ext/curl/interface.c |
563 | +@@ -2200,6 +2200,10 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
564 | + char *type = NULL, *filename = NULL; |
565 | + #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ |
566 | + struct mime_data_cb_arg *cb_arg; |
567 | ++ php_stream *stream; |
568 | ++ php_stream_statbuf ssb; |
569 | ++ size_t filesize = -1; |
570 | ++ curl_seek_callback seekfunc = seek_cb; |
571 | + #endif |
572 | + |
573 | + prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv); |
574 | +@@ -2225,9 +2229,17 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
575 | + zval_ptr_dtor(&ch->postfields); |
576 | + ZVAL_COPY(&ch->postfields, zpostfields); |
577 | + |
578 | ++ if ((stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", STREAM_MUST_SEEK, NULL))) { |
579 | ++ if (!stream->readfilters.head && !php_stream_stat(stream, &ssb)) { |
580 | ++ filesize = ssb.sb.st_size; |
581 | ++ } |
582 | ++ } else { |
583 | ++ seekfunc = NULL; |
584 | ++ } |
585 | ++ |
586 | + cb_arg = emalloc(sizeof *cb_arg); |
587 | + cb_arg->filename = zend_string_copy(postval); |
588 | +- cb_arg->stream = NULL; |
589 | ++ cb_arg->stream = stream; |
590 | + |
591 | + part = curl_mime_addpart(mime); |
592 | + if (part == NULL) { |
593 | +@@ -2235,7 +2247,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields |
594 | + return FAILURE; |
595 | + } |
596 | + if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK |
597 | +- || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, free_cb, cb_arg)) != CURLE_OK |
598 | ++ || (form_error = curl_mime_data_cb(part, filesize, read_cb, seekfunc, free_cb, cb_arg)) != CURLE_OK |
599 | + || (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK |
600 | + || (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) { |
601 | + error = form_error; |
602 | +-- |
603 | +2.25.1 |
604 | + |
605 | diff --git a/debian/patches/series b/debian/patches/series |
606 | index 6b41753..6237d6a 100644 |
607 | --- a/debian/patches/series |
608 | +++ b/debian/patches/series |
609 | @@ -42,3 +42,6 @@ CVE-2020-7064.patch |
610 | CVE-2020-7065.patch |
611 | CVE-2020-7066.patch |
612 | CVE-2019-11048.patch |
613 | + |
614 | +0041-Fix-79019-Copied-cURL-handles-upload-empty-file.patch |
615 | +0042-Fix-79013-Content-Length-missing-when-posting-a-curl.patch |
Changelog, Version, ... all look good to me.
The patches could use some headers again, but in this case one can recognize they are upstream patches and the hash is preserved, so I consider adding the headers optional.
I can recommend git-to-dquilt which does all that for you in one go. /git.launchpad. net/~ubuntu- server/ ubuntu- helpers/ tree/README. md#n63
https:/
but as I said optional in this case.
The patches are huge, give me a few minutes if they look SRU-compatible on closer examination.