On Sat, Feb 16, 2019 at 10:27:30AM +0100, Theo Buehler wrote: > 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.
OK feinerer@ Upstream commit has SVN revision 76143 (https://github.com/wch/r-source/commit/36bcd78ffd71547e1132903c00c5a6dae6e43609) > 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); > +