When running R with vm.malloc_conf=F, doing
> install.package("any")
on a fresh R install leads a segfault due to a use-after-free in
src/modules/internet/libcurl.c:
644 for (int i = 0; i < nurls; i++) {
...
here hnd[0] is freed:
656 curl_easy_cleanup(hnd[i]);
657 }
658 // This can show an invalid read: can it be improved?
659 long status = 0L;
660 if(nurls == 1)
661 curl_easy_getinfo(hnd[0], CURLINFO_RESPONSE_CODE, &status);
and here it is used again to retrieve the status code.
Note that the value of status is used later only in case nurls == 1
for error reporting. The patch below should therefore preserve the
intended behavior since curl_easy_getinfo() is idempotent.
Index: Makefile
===================================================================
RCS file: /var/cvs/ports/math/R/Makefile,v
retrieving revision 1.105
diff -u -p -r1.105 Makefile
--- Makefile 23 Dec 2018 08:03:45 -0000 1.105
+++ Makefile 16 Feb 2019 08:54:02 -0000
@@ -2,6 +2,7 @@
COMMENT= powerful math/statistics/graphics language
DISTNAME= R-3.5.2
+REVISION= 0
SO_VERSION= 34.2
.for _lib in R Rblas Rlapack
Index: patches/patch-src_modules_internet_libcurl_c
===================================================================
RCS file: patches/patch-src_modules_internet_libcurl_c
diff -N patches/patch-src_modules_internet_libcurl_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_modules_internet_libcurl_c 16 Feb 2019 08:43:53
-0000
@@ -0,0 +1,31 @@
+$OpenBSD$
+
+Avoid use-after-free.
+Index: src/modules/internet/libcurl.c
+--- src/modules/internet/libcurl.c.orig
++++ src/modules/internet/libcurl.c
+@@ -641,12 +641,12 @@ in_do_curlDownload(SEXP call, SEXP op, SEXP args, SEXP
+
+ n_err += curlMultiCheckerrs(mhnd);
+
++ long status = 0L;
+ for (int i = 0; i < nurls; i++) {
+ if (out[i]) {
+ fclose(out[i]);
+ double dl;
+ curl_easy_getinfo(hnd[i], CURLINFO_SIZE_DOWNLOAD, &dl);
+- long status;
+ curl_easy_getinfo(hnd[i], CURLINFO_RESPONSE_CODE, &status);
+ // should we do something about incomplete transfers?
+ if (status != 200 && dl == 0. && strchr(mode, 'w'))
+@@ -655,10 +655,6 @@ in_do_curlDownload(SEXP call, SEXP op, SEXP args, SEXP
+ curl_multi_remove_handle(mhnd, hnd[i]);
+ curl_easy_cleanup(hnd[i]);
+ }
+- // This can show an invalid read: can it be improved?
+- long status = 0L;
+- if(nurls == 1)
+- curl_easy_getinfo(hnd[0], CURLINFO_RESPONSE_CODE, &status);
+ curl_multi_cleanup(mhnd);
+ if (!cacheOK) curl_slist_free_all(slist1);
+