patch against overflows in saveload.c

Jean Meloche jean@stat.ubc.ca
Fri, 02 Apr 1999 21:58:54 +0000


This is a multi-part message in MIME format.
--------------3F9F11E6B00532CFDD5A424A
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

R fails to save long strings... (with xdr)

> str<-''; for(i in c(0:1000)) str<-paste(str,'a')
> q(save='yes')
Error: a write error occured
>

This was noticed a while ago and someone
suggested a large fixed sized buffer.

The attached patch allocates a buffer as needed
using malloc. I know R has ist own allocation
mechanism but I figured malloc was ok for
such short-lived buffers.

If not, please let me know how to do it properly.

--
Jean Meloche
--------------3F9F11E6B00532CFDD5A424A
Content-Type: text/plain; charset=us-ascii;
 name="sl.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="sl.diff"

--- saveload.c	Tue Feb 16 09:15:59 1999
+++ /usr/local/R-0.63.3/src/main/saveload.c	Fri Apr  2 13:25:42 1999
@@ -1,7 +1,6 @@
 /*
  *  R : A Computer Language for Statistical Data Analysis
  *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- *  Copyright (C) 1997--1999  Robert Gentleman, Ross Ihaka and the R Core Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -61,7 +60,7 @@
 static int	(*InInteger)(FILE*);
 static double	(*InReal)(FILE*);
 static complex	(*InComplex)(FILE*);
-static char*	(*InString)(FILE*);
+static char*	(*InString)(FILE*,int,char *);
 static void	(*InTerm)(FILE*);
 
 
@@ -195,7 +194,7 @@
     fputc('\"', fp);
 }
 
-static char *AsciiInString(FILE *fp)
+static char *AsciiInString(FILE *fp, int len, char *buf)
 {
     int c;
     bufp = buf;
@@ -346,16 +345,17 @@
 
 static void XdrOutString(FILE *fp, char *s)
 {
-    if (!xdr_string(&xdrs, &s, MAXELTSIZE - 1)) {
+    if (!xdr_string(&xdrs, &s, strlen(s))) {
 	xdr_destroy(&xdrs);
 	error("a write error occured\n");
     }
 }
 
-static char *XdrInString(FILE *fp)
+static char *XdrInString(FILE *fp, int len, char *buf)
 {
-    char *bufp = buf;
-    if (!xdr_string(&xdrs, &bufp, MAXELTSIZE - 1)) {
+    char *bufp;
+    bufp=buf;
+    if (!xdr_string(&xdrs, &bufp, len)) {
 	xdr_destroy(&xdrs);
 	error("a read error occured\n");
     }
@@ -439,7 +439,7 @@
 	error("a write error occured\n");
 }
 
-static char *BinaryInString(FILE *fp)
+static char *BinaryInString(FILE *fp, int len, char *buf)
 {
     bufp = buf;
     do {
@@ -705,6 +705,8 @@
 		OutSpace(fp);
 		OutInteger(fp, NodeToOffset(&R_NHeap[i]));
 		OutSpace(fp);
+		OutInteger(fp, strlen(CHAR(PRINTNAME(&R_NHeap[i]))));
+		OutSpace(fp);
 		OutString(fp, CHAR(PRINTNAME(&R_NHeap[i])));
 		OutNewline(fp);
 		k++;
@@ -737,7 +739,6 @@
     for (i = 0; i < R_NSize; i++) {
 	if (MARK(&R_NHeap[i])) {
 	    if (TYPEOF(&R_NHeap[i]) != SYMSXP) {
-
 		OutInteger(fp, n);
 		OutSpace(fp);
 		OutInteger(fp, TYPEOF(&R_NHeap[i]));
@@ -845,6 +846,7 @@
 {
     unsigned int j;
     int len;
+    char *buf;
 
     TYPEOF(s) = InInteger(fp);
 
@@ -887,12 +889,16 @@
     case SPECIALSXP:
     case BUILTINSXP:
 	len = InInteger(fp);
-	PRIMOFFSET(s) = StrToInternal(InString(fp));
+	if((buf=malloc(len+1))==NULL) error("not enough memory to restore data\n");
+	PRIMOFFSET(s) = StrToInternal(InString(fp, len, buf));
+	free(buf);
 	break;
     case CHARSXP:
 	LENGTH(s) = len = InInteger(fp);
 	ReallocString(s, len);
-	strcpy(CHAR(s), InString(fp));
+	if((buf=malloc(len+1))==NULL) error("not enough memory to restore data\n");
+	strcpy(CHAR(s), InString(fp, len, buf));
+	free(buf);
 	break;
     case REALSXP:
 	LENGTH(s) = len = InInteger(fp);
@@ -956,9 +962,14 @@
     /* computing the forwarding addresses */
 
     for (i = 0 ; i < NSymbol ; i++) {
+	char *buf;
+	int len;
 	j = InInteger(fp);
 	OldOffset[j] = InInteger(fp);
-	NewAddress[j] = install(InString(fp));
+	len = InInteger(fp);
+	if((buf=malloc(len+1))==NULL) error("not enough memory to restore data\n");
+	NewAddress[j] = install(InString(fp,len,buf));
+	free(buf);
     }
 
     /* symbols are all installed */
@@ -1074,7 +1085,7 @@
 	TAG(t) = install(CHAR(STRING(CAR(args))[j]));
 	CAR(t) = findVar(TAG(t), R_GlobalContext->sysparent);
 	if (CAR(t) == R_UnboundValue)
-            error("Object \"%s\" not found\n", CHAR(PRINTNAME(TAG(t))));
+	    error("Object \"%s\" not found\n", CHAR(PRINTNAME(TAG(t))));
     }
 
     R_SaveToFile(s, fp, INTEGER(CADDR(args))[0]);
@@ -1811,12 +1822,12 @@
 do_hdf5save (SEXP call, SEXP op, SEXP args, SEXP env)
 {
     errorcall(call, "HDF5 support unavailable\n");
-    return(R_NilValue);		/* -Wall */
+    return(R_NilValue);         /* -Wall */
 }
 SEXP
 do_hdf5load (SEXP call, SEXP op, SEXP args, SEXP env)
 {
     errorcall(call, "HDF5 support unavailable\n");
-    return(R_NilValue);		/* -Wall */    
+    return(R_NilValue);         /* -Wall */
 }
 #endif

--------------3F9F11E6B00532CFDD5A424A--

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._