On Sun, 2003-10-05 at 02:56, Wayne Davison wrote:
> On Sat, Oct 04, 2003 at 11:38:48PM +0300, Timo Sirainen wrote:
> >     for (i=0; i < (int) s->count;i++) {
> 
> Yeah, that's pretty bad.  Attached is a patch that should fix this and a
> number of other related problems where the code assumed that size_t
> would fit into an int.

The main problem wasn't int vs. size_t. malloc() call would have
overflowed even if i had been size_t.

Included a patch that fixes all the potential malloc()/realloc()
overflows that I found. I'd feel a bit safer with them included :)

diff -ru rsync-2.5.6-old/checksum.c rsync-2.5.6/checksum.c
--- rsync-2.5.6-old/checksum.c	2002-04-08 11:29:04.000000000 +0300
+++ rsync-2.5.6/checksum.c	2003-10-07 00:40:20.000000000 +0300
@@ -56,6 +56,11 @@
 	static int len1;
 	struct mdfour m;
 
+	if (len <= 0 || len > INT_MAX-4) {
+		rprintf(FERROR, "overflow: len=%d\n", len);
+		overflow("get_checksum2");
+	}
+
 	if (len > len1) {
 		if (buf1) free(buf1);
 		buf1 = (char *)malloc(len+4);
diff -ru rsync-2.5.6-old/exclude.c rsync-2.5.6/exclude.c
--- rsync-2.5.6-old/exclude.c	2003-01-26 22:10:23.000000000 +0200
+++ rsync-2.5.6/exclude.c	2003-10-07 00:31:12.000000000 +0300
@@ -186,6 +186,11 @@
 	if (list && *list)
 		for (; (*list)[len]; len++) ;
 
+	if (len > INT_MAX/2) {
+		rprintf(FERROR, "overflow: len=%d\n", len);
+		overflow("add_exclude_list");
+	}
+
 	if (strcmp(pattern,"!") == 0) {
 		if (verbose > 2)
 			rprintf(FINFO,"clearing exclude list\n");
diff -ru rsync-2.5.6-old/flist.c rsync-2.5.6/flist.c
--- rsync-2.5.6-old/flist.c	2003-10-04 22:08:23.000000000 +0300
+++ rsync-2.5.6/flist.c	2003-10-07 00:42:40.000000000 +0300
@@ -307,7 +307,13 @@
 	if (flist->count >= flist->malloced) {
 		size_t new_bytes;
 		void *new_ptr;
-		
+
+		if (flist->malloced >= INT_MAX/2) {
+			rprintf(FERROR,"overflow: flist->malloced=%d\n",
+				flist->malloced);
+                        overflow("flist_expand");
+		}
+
 		if (flist->malloced < 1000)
 			flist->malloced += 1000;
 		else
@@ -543,7 +549,7 @@
 
 	if (preserve_links && S_ISLNK(file->mode)) {
 		int l = read_int(f);
-		if (l < 0) {
+		if (l < 0 || l >= INT_MAX) {
 			rprintf(FERROR, "overflow: l=%d\n", l);
 			overflow("receive_file_entry");
 		}
diff -ru rsync-2.5.6-old/hlink.c rsync-2.5.6/hlink.c
--- rsync-2.5.6-old/hlink.c	2002-03-25 09:07:03.000000000 +0200
+++ rsync-2.5.6/hlink.c	2003-10-07 00:45:29.000000000 +0300
@@ -57,6 +57,11 @@
 	if (hlink_list)
 		free(hlink_list);
 
+	if (flist->count > INT_MAX/sizeof(hlink_list[0])) {
+		rprintf(FERROR, "overflow: flist->count=%d\n", flist->count);
+		overflow("init_hard_links");
+	}
+
 	if (!(hlink_list =
 	      (struct file_struct *) malloc(sizeof(hlink_list[0]) *
 					    flist->count)))
diff -ru rsync-2.5.6-old/log.c rsync-2.5.6/log.c
--- rsync-2.5.6-old/log.c	2002-12-24 09:42:04.000000000 +0200
+++ rsync-2.5.6/log.c	2003-10-07 00:45:19.000000000 +0300
@@ -90,6 +90,12 @@
 static void err_list_add(int code, char *buf, int len)
 {
 	struct err_list *el;
+
+	if (len < 0 || len > INT_MAX-4) {
+		rprintf(FERROR, "overflow: len=%d\n", len);
+		overflow("err_list_add");
+	}
+
 	el = (struct err_list *)malloc(sizeof(*el));
 	if (!el) exit_cleanup(RERR_MALLOC);
 	el->next = NULL;
diff -ru rsync-2.5.6-old/match.c rsync-2.5.6/match.c
--- rsync-2.5.6-old/match.c	2002-04-09 09:11:06.000000000 +0300
+++ rsync-2.5.6/match.c	2003-10-07 00:46:34.000000000 +0300
@@ -67,6 +67,11 @@
   if (!tag_table)
     tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
 
+  if (s->count > INT_MAX/sizeof(targets[0])) {
+    rprintf(FERROR, "overflow: s->count=%d\n", s->count);
+    overflow("build_hash_table");
+  }
+
   targets = (struct target *)malloc(sizeof(targets[0])*s->count);
   if (!tag_table || !targets) 
     out_of_memory("build_hash_table");
diff -ru rsync-2.5.6-old/receiver.c rsync-2.5.6/receiver.c
--- rsync-2.5.6-old/receiver.c	2003-10-04 22:08:23.000000000 +0300
+++ rsync-2.5.6/receiver.c	2003-10-07 00:42:03.000000000 +0300
@@ -66,6 +66,11 @@
 static void add_delete_entry(struct file_struct *file)
 {
 	if (dlist_len == dlist_alloc_len) {
+		if (dlist_alloc_len >= INT_MAX - 1024) {
+			rprintf(FERROR,"overflow: dlist_alloc_len=%d\n",
+				dlist_alloc_len);
+                        overflow("add_delete_entry");
+		}
 		dlist_alloc_len += 1024;
 		delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
 		if (!delete_list) out_of_memory("add_delete_entry");
diff -ru rsync-2.5.6-old/sender.c rsync-2.5.6/sender.c
--- rsync-2.5.6-old/sender.c	2003-10-05 02:12:14.000000000 +0300
+++ rsync-2.5.6/sender.c	2003-10-07 00:47:14.000000000 +0300
@@ -62,6 +61,11 @@
 	if (s->count == 0) 
 		return(s);
 
+	if (s->count >= INT_MAX/sizeof(s->sums[0])) {
+		rprintf(FERROR, "overflow: s->count=%d\n", s->count);
+		overflow("receive_sums");
+	}
+
 	s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
 	if (!s->sums) out_of_memory("receive_sums");
 
diff -ru rsync-2.5.6-old/util.c rsync-2.5.6/util.c
--- rsync-2.5.6-old/util.c	2003-01-19 23:37:11.000000000 +0200
+++ rsync-2.5.6/util.c	2003-10-07 00:37:43.000000000 +0300
@@ -540,6 +540,11 @@
 
 void *Realloc(void *p, int size)
 {
+	if (size <= 0) {
+		/* Should never happen - potential security hole */
+		rprintf(FERROR,"Realloc() called with size=%d\n", size);
+		abort();
+	}
 	if (!p) return (void *)malloc(size);
 	return (void *)realloc(p, size);
 }
-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to