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);
+ 

Reply via email to