File rsync-fix-compilation-do_malloc_fixes.patch of Package rsync.37081

commit 11eb67eec9b4d990ae4df680cf7db77dad1b8630
Author: Wayne Davison <wayne@opencoder.net>
Date:   Thu Jun 25 19:59:19 2020 -0700

    Some memory allocation improvements
    
     - All the memory-allocation macros now auto-check for failure and exit
       with a failure message that incudes the caller's file and lineno
       info.  This includes strdup().
    
     - Added the `--max-alloc=SIZE` option to be able to override the memory
       allocator's sanity-check limit.  It defaults to 1G (as before).
       Fixes bugzilla bug 12769.

Index: rsync-3.1.0/access.c
===================================================================
--- rsync-3.1.0.orig/access.c
+++ rsync-3.1.0/access.c
@@ -19,6 +19,7 @@
  */
 
 #include "rsync.h"
+#include "ifuncs.h"
 
 static int allow_forward_dns;
 
@@ -52,10 +53,8 @@ static int match_hostname(const char **h
 		if (strcmp(addr, inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i]))) == 0) {
 			/* If reverse lookups are off, we'll use the conf-specified
 			 * hostname in preference to UNDETERMINED. */
-			if (host == undetermined_hostname) {
-				if (!(*host_ptr = strdup(tok)))
-					*host_ptr = undetermined_hostname;
-			}
+			if (host == undetermined_hostname)
+				*host_ptr = strdup(tok);
 			return 1;
 		}
 	}
@@ -243,9 +242,6 @@ static int access_match(const char *list
 	char *tok;
 	char *list2 = strdup(list);
 
-	if (!list2)
-		out_of_memory("access_match");
-
 	strlower(list2);
 
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
Index: rsync-3.1.0/acls.c
===================================================================
--- rsync-3.1.0.orig/acls.c
+++ rsync-3.1.0/acls.c
@@ -181,8 +181,6 @@ static rsync_acl *create_racl(void)
 {
 	rsync_acl *racl = new(rsync_acl);
 
-	if (!racl)
-		out_of_memory("create_racl");
 	*racl = empty_rsync_acl;
 
 	return racl;
@@ -349,8 +347,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sac
 			      sizeof (id_access), id_access_sorter);
 		}
 #endif
-		if (!(racl->names.idas = new_array(id_access, temp_ida_list.count)))
-			out_of_memory("unpack_smb_acl");
+		racl->names.idas = new_array(id_access, temp_ida_list.count);
 		memcpy(racl->names.idas, temp_ida_list.items,
 		       temp_ida_list.count * sizeof (id_access));
 	} else
@@ -520,9 +517,7 @@ static int get_rsync_acl(const char *fna
 
 		if (cnt) {
 			char *bp = buf + 4*4;
-			id_access *ida;
-			if (!(ida = racl->names.idas = new_array(id_access, cnt)))
-				out_of_memory("get_rsync_acl");
+			id_access *ida = racl->names.idas = new_array(id_access, cnt);
 			racl->names.count = cnt;
 			for ( ; cnt--; ida++, bp += 4+4) {
 				ida->id = IVAL(bp, 0);
@@ -966,12 +961,7 @@ static uchar recv_ida_entries(int f, ida
 	uchar computed_mask_bits = 0;
 	int i, count = read_varint(f);
 
-	if (count) {
-		if (!(ent->idas = new_array(id_access, count)))
-			out_of_memory("recv_ida_entries");
-	} else
-		ent->idas = NULL;
-
+	ent->idas = count ? new_array(id_access, count) : NULL;
 	ent->count = count;
 
 	for (i = 0; i < count; i++) {
Index: rsync-3.1.0/authenticate.c
===================================================================
--- rsync-3.1.0.orig/authenticate.c
+++ rsync-3.1.0/authenticate.c
@@ -20,6 +20,7 @@
 
 #include "rsync.h"
 #include "itypes.h"
+#include "ifuncs.h"
 
 extern int read_only;
 extern char *password_file;
@@ -250,8 +251,7 @@ char *auth_server(int f_in, int f_out, i
 	}
 	*pass++ = '\0';
 
-	if (!(users = strdup(users)))
-		out_of_memory("auth_server");
+	users = strdup(users);
 
 	for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
 		char *opts;
@@ -286,8 +286,7 @@ char *auth_server(int f_in, int f_out, i
 				 || getallgroups(auth_uid, gid_list, &auth_uid_groups_cnt) != NULL)
 					auth_uid_groups_cnt = 0;
 				else {
-					if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
-						out_of_memory("auth_server");
+					auth_uid_groups = new_array(char *, auth_uid_groups_cnt);
 					for (j = 0; j < auth_uid_groups_cnt; j++)
 						auth_uid_groups[j] = gid_to_group(gid_list[j]);
 				}
Index: rsync-3.1.0/checksum.c
===================================================================
--- rsync-3.1.0.orig/checksum.c
+++ rsync-3.1.0/checksum.c
@@ -81,8 +81,6 @@ void get_checksum2(char *buf, int32 len,
 				free(buf1);
 			buf1 = new_array(char, len+4);
 			len1 = len;
-			if (!buf1)
-				out_of_memory("get_checksum2");
 		}
 
 		memcpy(buf1, buf, len);
Index: rsync-3.1.0/clientserver.c
===================================================================
--- rsync-3.1.0.orig/clientserver.c
+++ rsync-3.1.0/clientserver.c
@@ -231,8 +231,7 @@ int start_inband_exchange(int f_in, int
 	else
 		modlen = p - *argv;
 
-	if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
-		out_of_memory("start_inband_exchange");
+	modname = new_array(char, modlen+1+1); /* room for '/' & '\0' */
 	strlcpy(modname, *argv, modlen + 1);
 	modname[modlen] = '/';
 	modname[modlen+1] = '\0';
Index: rsync-3.1.0/exclude.c
===================================================================
--- rsync-3.1.0.orig/exclude.c
+++ rsync-3.1.0/exclude.c
@@ -21,6 +21,7 @@
  */
 
 #include "rsync.h"
+#include "ifuncs.h"
 
 extern int am_server;
 extern int am_sender;
@@ -217,8 +218,7 @@ static void add_rule(filter_rule_list *l
 	} else
 		suf_len = 0;
 
-	if (!(rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
-		out_of_memory("add_rule");
+	rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1);
 	if (pre_len) {
 		memcpy(rule->pattern, dirbuf + module_dirlen, pre_len);
 		for (cp = rule->pattern; cp < rule->pattern + pre_len; cp++) {
@@ -276,8 +276,7 @@ static void add_rule(filter_rule_list *l
 			}
 		}
 
-		if (!(lp = new_array(filter_rule_list, 1)))
-			out_of_memory("add_rule");
+		lp = new_array0(filter_rule_list, 1);
 		lp->head = lp->tail = lp->parent_dirscan_head = NULL;
 		if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
 			out_of_memory("add_rule");
@@ -285,11 +284,7 @@ static void add_rule(filter_rule_list *l
 
 		if (mergelist_cnt == mergelist_size) {
 			mergelist_size += 5;
-			mergelist_parents = realloc_array(mergelist_parents,
-						filter_rule *,
-						mergelist_size);
-			if (!mergelist_parents)
-				out_of_memory("add_rule");
+			mergelist_parents = realloc_array(mergelist_parents, filter_rule *, mergelist_size);
 		}
 		if (DEBUG_GTE(FILTER, 2)) {
 			rprintf(FINFO, "[%s] activating mergelist #%d%s\n",
@@ -647,8 +642,6 @@ void *push_local_filters(const char *dir
 	push = (struct local_filter_state *)new_array(char,
 			  sizeof (struct local_filter_state)
 			+ (mergelist_cnt-1) * sizeof (filter_rule_list));
-	if (!push)
-		out_of_memory("push_local_filters");
 
 	push->mergelist_cnt = mergelist_cnt;
 	for (i = 0; i < mergelist_cnt; i++) {
@@ -949,8 +942,7 @@ static filter_rule *parse_rule_tok(const
 	if (!*s)
 		return NULL;
 
-	if (!(rule = new0(filter_rule)))
-		out_of_memory("parse_rule_tok");
+	rule = new0(filter_rule);
 
 	/* Inherit from the template.  Don't inherit FILTRULES_SIDES; we check
 	 * that later. */
@@ -1258,8 +1250,7 @@ void parse_filter_str(filter_rule_list *
 				const char *name;
 				filter_rule *excl_self;
 
-				if (!(excl_self = new0(filter_rule)))
-					out_of_memory("parse_filter_str");
+				excl_self = new0(filter_rule);
 				/* Find the beginning of the basename and add an exclude for it. */
 				for (name = pat + pat_len; name > pat && name[-1] != '/'; name--) {}
 				add_rule(listp, name, (pat + pat_len) - name, excl_self, 0);
Index: rsync-3.1.0/fileio.c
===================================================================
--- rsync-3.1.0.orig/fileio.c
+++ rsync-3.1.0/fileio.c
@@ -137,8 +137,6 @@ int write_file(int f, char *buf, int len
 				wf_writeBufSize = WRITE_SIZE * 8;
 				wf_writeBufCnt  = 0;
 				wf_writeBuf = new_array(char, wf_writeBufSize);
-				if (!wf_writeBuf)
-					out_of_memory("write_file");
 			}
 			r1 = (int)MIN((size_t)len, wf_writeBufSize - wf_writeBufCnt);
 			if (r1) {
@@ -173,8 +171,7 @@ struct map_struct *map_file(int fd, OFF_
 {
 	struct map_struct *map;
 
-	if (!(map = new0(struct map_struct)))
-		out_of_memory("map_file");
+	map = new0(struct map_struct);
 
 	if (blk_size && (read_size % blk_size))
 		read_size += blk_size - (read_size % blk_size);
@@ -217,8 +214,6 @@ char *map_ptr(struct map_struct *map, OF
 	/* make sure we have allocated enough memory for the window */
 	if (window_size > map->p_size) {
 		map->p = realloc_array(map->p, char, window_size);
-		if (!map->p)
-			out_of_memory("map_ptr");
 		map->p_size = window_size;
 	}
 
Index: rsync-3.1.0/flist.c
===================================================================
--- rsync-3.1.0.orig/flist.c
+++ rsync-3.1.0/flist.c
@@ -318,8 +318,7 @@ static void flist_expand(struct file_lis
 	if (flist->malloced < flist->used + extra)
 		flist->malloced = flist->used + extra;
 
-	new_ptr = realloc_array(flist->files, struct file_struct *,
-				flist->malloced);
+	new_ptr = realloc_array(flist->files, struct file_struct *, flist->malloced);
 
 	if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) {
 		rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n",
@@ -1333,10 +1332,8 @@ struct file_struct *make_file(const char
 		  + linkname_len;
 	if (pool)
 		bp = pool_alloc(pool, alloc_len, "make_file");
-	else {
-		if (!(bp = new_array(char, alloc_len)))
-			out_of_memory("make_file");
-	}
+	else
+		bp = new_array(char, alloc_len);
 
 	memset(bp, 0, extra_len + FILE_STRUCT_LEN);
 	bp += extra_len;
@@ -1643,8 +1640,7 @@ static void fsort(struct file_struct **f
 	if (use_qsort)
 		qsort(fp, num, PTR_SIZE, file_compare);
 	else {
-		struct file_struct **tmp = new_array(struct file_struct *,
-						     (num+1) / 2);
+		struct file_struct **tmp = new_array(struct file_struct *, (num+1) / 2);
 		fsort_tmp(fp, num, tmp);
 		free(tmp);
 	}
@@ -1874,13 +1870,11 @@ static void send_implied_dirs(int f, str
 	len = strlen(limit+1);
 	memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
 	if (!relname_list) {
-		if (!(relname_list = new0(item_list)))
-			out_of_memory("send_implied_dirs");
+		relname_list = new0(item_list);
 		memcpy(F_DIR_RELNAMES_P(lastpath_struct), &relname_list, sizeof relname_list);
 	}
 	rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32);
-	if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len)))
-		out_of_memory("send_implied_dirs");
+	*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len);
 	(*rnpp)->name_type = name_type;
 	strlcpy((*rnpp)->fname, limit+1, len + 1);
 
@@ -2027,8 +2021,7 @@ void send_extra_file_list(int f, int at_
 		}
 
 		if (need_unsorted_flist) {
-			if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
-				out_of_memory("send_extra_file_list");
+			flist->sorted = new_array(struct file_struct *, flist->used);
 			memcpy(flist->sorted, flist->files,
 			       flist->used * sizeof (struct file_struct*));
 		} else
@@ -2383,8 +2376,7 @@ struct file_list *send_file_list(int f,
 	 * recursion mode, the sender marks duplicate dirs so that it can
 	 * send them together in a single file-list. */
 	if (need_unsorted_flist) {
-		if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
-			out_of_memory("send_file_list");
+		flist->sorted = new_array(struct file_struct *, flist->used);
 		memcpy(flist->sorted, flist->files,
 		       flist->used * sizeof (struct file_struct*));
 	} else
@@ -2567,8 +2559,7 @@ struct file_list *recv_file_list(int f,
 		 * order and for calling flist_find()).  We keep the "files"
 		 * list unsorted for our exchange of index numbers with the
 		 * other side (since their names may not sort the same). */
-		if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
-			out_of_memory("recv_file_list");
+		flist->sorted = new_array(struct file_struct *, flist->used);
 		memcpy(flist->sorted, flist->files,
 		       flist->used * sizeof (struct file_struct*));
 		if (inc_recurse && dir_flist->used > dstart) {
@@ -2778,8 +2769,7 @@ struct file_list *flist_new(int flags, c
 {
 	struct file_list *flist;
 
-	if (!(flist = new0(struct file_list)))
-		out_of_memory(msg);
+	flist = new0(struct file_list);
 
 	if (flags & FLIST_TEMP) {
 		if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0,
Index: rsync-3.1.0/generator.c
===================================================================
--- rsync-3.1.0.orig/generator.c
+++ rsync-3.1.0/generator.c
@@ -2193,8 +2193,6 @@ void generate_files(int f_out, const cha
 	if (delete_during == 2) {
 		deldelay_size = BIGPATHBUFLEN * 4;
 		deldelay_buf = new_array(char, deldelay_size);
-		if (!deldelay_buf)
-			out_of_memory("delete-delay");
 	}
 	info_levels[INFO_FLIST] = info_levels[INFO_PROGRESS] = 0;
 
Index: rsync-3.1.0/getgroups.c
===================================================================
--- rsync-3.1.0.orig/getgroups.c
+++ rsync-3.1.0/getgroups.c
@@ -20,8 +20,7 @@
 
 #include "rsync.h"
 
-int
-main(UNUSED(int argc), UNUSED(char *argv[]))
+ int main(UNUSED(int argc), UNUSED(char *argv[]))
 {
 	int n, i;
 	gid_t *list;
Index: rsync-3.1.0/hashtable.c
===================================================================
--- rsync-3.1.0.orig/hashtable.c
+++ rsync-3.1.0/hashtable.c
@@ -35,9 +35,8 @@ struct hashtable *hashtable_create(int s
 			size *= 2;
 	}
 
-	if (!(tbl = new(struct hashtable))
-	 || !(tbl->nodes = new_array0(char, size * node_size)))
-		out_of_memory("hashtable_create");
+	tbl = new(struct hashtable);
+	tbl->nodes = new_array0(char, size * node_size);
 	tbl->size = size;
 	tbl->entries = 0;
 	tbl->node_size = node_size;
@@ -84,8 +83,7 @@ void *hashtable_find(struct hashtable *t
 		int size = tbl->size * 2;
 		int i;
 
-		if (!(tbl->nodes = new_array0(char, size * tbl->node_size)))
-			out_of_memory("hashtable_node");
+		tbl->nodes = new_array0(char, size * tbl->node_size);
 		tbl->size = size;
 		tbl->entries = 0;
 
Index: rsync-3.1.0/hlink.c
===================================================================
--- rsync-3.1.0.orig/hlink.c
+++ rsync-3.1.0/hlink.c
@@ -127,8 +127,7 @@ static void match_gnums(int32 *ndx_list,
 		if (inc_recurse) {
 			node = hashtable_find(prior_hlinks, gnum, 1);
 			if (!node->data) {
-				if (!(node->data = new_array0(char, 5)))
-					out_of_memory("match_gnums");
+				node->data = new_array0(char, 5);
 				assert(gnum >= hlink_flist->ndx_start);
 				file->flags |= FLAG_HLINK_FIRST;
 				prev = -1;
@@ -192,8 +191,7 @@ void match_hard_links(struct file_list *
 		int i, ndx_count = 0;
 		int32 *ndx_list;
 
-		if (!(ndx_list = new_array(int32, flist->used)))
-			out_of_memory("match_hard_links");
+		ndx_list = new_array(int32, flist->used);
 
 		for (i = 0; i < flist->used; i++) {
 			if (F_IS_HLINKED(flist->sorted[i]))
@@ -543,8 +541,7 @@ void finish_hard_link(struct file_struct
 			exit_cleanup(RERR_MESSAGEIO);
 		}
 		free(node->data);
-		if (!(node->data = strdup(our_name)))
-			out_of_memory("finish_hard_link");
+		node->data = strdup(our_name);
 	}
 }
 
Index: rsync-3.1.0/ifuncs.h
===================================================================
--- rsync-3.1.0.orig/ifuncs.h
+++ rsync-3.1.0/ifuncs.h
@@ -19,8 +19,7 @@
 static inline void
 alloc_xbuf(xbuf *xb, size_t sz)
 {
-	if (!(xb->buf = new_array(char, sz)))
-		out_of_memory("alloc_xbuf");
+	xb->buf = new_array(char, sz);
 	xb->size = sz;
 	xb->len = xb->pos = 0;
 }
@@ -29,8 +28,6 @@ static inline void
 realloc_xbuf(xbuf *xb, size_t sz)
 {
 	char *bf = realloc_array(xb->buf, char, sz);
-	if (!bf)
-		out_of_memory("realloc_xbuf");
 	xb->buf = bf;
 	xb->size = sz;
 }
@@ -104,3 +101,11 @@ free_stat_x(stat_x *sx_p)
     }
 #endif
 }
+
+static inline char *my_strdup(const char *str, const char *file, int line)
+{
+    int len = strlen(str)+1;
+    char *buf = _my_alloc(do_malloc, len, 1, file, line);
+    memcpy(buf, str, len);
+    return buf;
+}
Index: rsync-3.1.0/io.c
===================================================================
--- rsync-3.1.0.orig/io.c
+++ rsync-3.1.0/io.c
@@ -1264,8 +1264,7 @@ void read_args(int f_in, char *mod_name,
 	rl_flags |= (protect_args && ic_recv != (iconv_t)-1 ? RL_CONVERT : 0);
 #endif
 
-	if (!(argv = new_array(char *, maxargs)))
-		out_of_memory("read_args");
+	argv = new_array(char *, maxargs);
 	if (mod_name && !protect_args)
 		argv[argc++] = "rsyncd";
 
@@ -1278,8 +1277,7 @@ void read_args(int f_in, char *mod_name,
 
 		if (argc == maxargs-1) {
 			maxargs += MAX_ARGS;
-			if (!(argv = realloc_array(argv, char *, maxargs)))
-				out_of_memory("read_args");
+			argv = realloc_array(argv, char *, maxargs);
 		}
 
 		if (dot_pos) {
@@ -1287,8 +1285,7 @@ void read_args(int f_in, char *mod_name,
 				int len = strlen(buf);
 				if (request_len)
 					request_p[0][request_len++] = ' ';
-				if (!(*request_p = realloc_array(*request_p, char, request_len + len + 1)))
-					out_of_memory("read_args");
+				*request_p = realloc_array(*request_p, char, request_len + len + 1);
 				memcpy(*request_p + request_len, buf, len + 1);
 				request_len += len;
 			}
@@ -1297,8 +1294,7 @@ void read_args(int f_in, char *mod_name,
 			else
 				glob_expand(buf, &argv, &argc, &maxargs);
 		} else {
-			if (!(p = strdup(buf)))
-				out_of_memory("read_args");
+			p = strdup(buf);
 			argv[argc++] = p;
 			if (*p == '.' && p[1] == '\0')
 				dot_pos = argc;
Index: rsync-3.1.0/loadparm.c
===================================================================
--- rsync-3.1.0.orig/loadparm.c
+++ rsync-3.1.0/loadparm.c
@@ -42,6 +42,7 @@
  */
 
 #include "rsync.h"
+#include "ifuncs.h"
 #include "itypes.h"
 
 extern item_list dparam_list;
@@ -395,8 +396,7 @@ static char *expand_vars(char *str)
 		return str;
 
 	bufsize = strlen(str) + 2048;
-	if ((buf = new_array(char, bufsize+1)) == NULL) /* +1 for trailing '\0' */
-		out_of_memory("expand_vars");
+	buf = new_array(char, bufsize+1); /* +1 for trailing '\0' */
 
 	for (t = buf, f = str; bufsize && *f; ) {
 		if (*f == '%' && *++f != '%') {
@@ -519,10 +519,7 @@ FN_LOCAL_BOOL(lp_write_only, write_only)
  * the start, so any lost memory is inconsequential. */
 static inline void string_set(char **s, const char *v)
 {
-	if (!v)
-		*s = NULL;
-	else if (!(*s = strdup(v)))
-		out_of_memory("string_set");
+	*s = v ? strdup(v) : NULL;
 }
 
 /* Copy the local_vars, strdup'ing any strings.  NOTE:  this depends on
Index: rsync-3.1.0/main.c
===================================================================
--- rsync-3.1.0.orig/main.c
+++ rsync-3.1.0/main.c
@@ -22,6 +22,7 @@
 
 #include "rsync.h"
 #include "inums.h"
+#include "ifuncs.h"
 #include "io.h"
 #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
 #include <locale.h>
@@ -410,8 +411,6 @@ static pid_t do_cmd(char *cmd, char *mac
 		if (!cmd)
 			cmd = RSYNC_RSH;
 		cmd = need_to_free = strdup(cmd);
-		if (!cmd)
-			goto oom;
 
 		for (t = f = cmd; *f; f++) {
 			if (*f == ' ')
@@ -549,10 +548,6 @@ static pid_t do_cmd(char *cmd, char *mac
 		free(need_to_free);
 
 	return pid;
-
-  oom:
-	out_of_memory("do_cmd");
-	return 0; /* not reached */
 }
 
 /* The receiving side operates in one of two modes:
@@ -717,8 +712,6 @@ static void check_alt_basis_dirs(void)
 		if (dry_run > 1 && *bdir != '/') {
 			int len = curr_dir_len + 1 + bd_len + 1;
 			char *new = new_array(char, len);
-			if (!new)
-				out_of_memory("check_alt_basis_dirs");
 			if (slash && strncmp(bdir, "../", 3) == 0) {
 			    /* We want to remove only one leading "../" prefix for
 			     * the directory we couldn't create in dry-run mode:
@@ -1208,19 +1201,12 @@ int client_run(int f_in, int f_out, pid_
 	return MAX(exit_code, exit_code2);
 }
 
-static int copy_argv(char *argv[])
+static void dup_argv(char *argv[])
 {
 	int i;
 
-	for (i = 0; argv[i]; i++) {
-		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
-				 __FILE__, __LINE__);
-			return RERR_MALLOC;
-		}
-	}
-
-	return 0;
+	for (i = 0; argv[i]; i++)
+		argv[i] = strdup(argv[i]);
 }
 
 
@@ -1241,8 +1227,7 @@ static int start_client(int argc, char *
 
 	/* Don't clobber argv[] so that ps(1) can still show the right
 	 * command line. */
-	if ((ret = copy_argv(argv)) != 0)
-		return ret;
+	dup_argv(argv);
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
Index: rsync-3.1.0/match.c
===================================================================
--- rsync-3.1.0.orig/match.c
+++ rsync-3.1.0/match.c
@@ -65,8 +65,6 @@ static void build_hash_table(struct sum_
 		if (hash_table)
 			free(hash_table);
 		hash_table = new_array(int32, tablesize);
-		if (!hash_table)
-			out_of_memory("build_hash_table");
 		alloc_size = tablesize;
 	}
 
Index: rsync-3.1.0/options.c
===================================================================
--- rsync-3.1.0.orig/options.c
+++ rsync-3.1.0/options.c
@@ -20,6 +20,7 @@
  */
 
 #include "rsync.h"
+#include "ifuncs.h"
 #include "itypes.h"
 #include <popt.h>
 #include <zlib.h>
@@ -181,6 +182,10 @@ int link_dest = 0;
 int basis_dir_cnt = 0;
 char *dest_option = NULL;
 
+#define DEFAULT_MAX_ALLOC (1024L * 1024 * 1024)
+size_t max_alloc = DEFAULT_MAX_ALLOC;
+char *max_alloc_arg;
+
 static int remote_option_alloc = 0;
 int remote_option_cnt = 0;
 const char **remote_options = NULL;
@@ -373,8 +378,7 @@ static char *make_output_option(struct o
 		return NULL;
 
 	len++;
-	if (!(buf = new_array(char, len)))
-		out_of_memory("make_output_option");
+	buf = new_array(char, len);
 	pos = 0;
 
 	if (skipped || max < 5)
@@ -930,6 +934,7 @@ static struct poptOption long_options[]
   {"ignore-existing",  0,  POPT_ARG_NONE,   &ignore_existing, 0, 0, 0 },
   {"max-size",         0,  POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
   {"min-size",         0,  POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
+  {"max-alloc",        0,  POPT_ARG_STRING, &max_alloc_arg, 0, 0, 0 },
   {"sparse",          'S', POPT_ARG_VAL,    &sparse_files, 1, 0, 0 },
   {"no-sparse",        0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
   {"no-S",             0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
@@ -1219,14 +1224,16 @@ static int count_args(const char **argv)
 	return i;
 }
 
-
-static OFF_T parse_size_arg(char **size_arg, char def_suf)
+/* If the size_arg is an invalid string or the value is < min_value, an error
+ * is put into err_buf & the return is -1.  Note that this parser does NOT
+ * support negative numbers, so a min_value < 0 doesn't make any sense. */
+static ssize_t parse_size_arg(char *size_arg, char def_suf, const char *opt_name, ssize_t min_value)
 {
-	int reps, mult, make_compatible = 0;
-	const char *arg;
-	OFF_T size = 1;
+	int reps, mult;
+	const char *arg, *err = "invalid";
+	ssize_t size = 1;
 
-	for (arg = *size_arg; isDigit(arg); arg++) {}
+	for (arg = size_arg; isDigit(arg); arg++) {}
 	if (*arg == '.')
 		for (arg++; isDigit(arg); arg++) {}
 	switch (*arg && *arg != '+' && *arg != '-' ? *arg++ : def_suf) {
@@ -1242,40 +1249,40 @@ static OFF_T parse_size_arg(char **size_
 	case 'g': case 'G':
 		reps = 3;
 		break;
+	case 't': case 'T':
+		reps = 4;
+		break;
+	case 'p': case 'P':
+		reps = 5;
+		break;
 	default:
-		return -1;
+		goto failure;
 	}
 	if (*arg == 'b' || *arg == 'B')
-		mult = 1000, make_compatible = 1, arg++;
+		mult = 1000, arg++;
 	else if (!*arg || *arg == '+' || *arg == '-')
 		mult = 1024;
 	else if (strncasecmp(arg, "ib", 2) == 0)
 		mult = 1024, arg += 2;
 	else
-		return -1;
+		goto failure;
 	while (reps--)
 		size *= mult;
-	size *= atof(*size_arg);
+	size *= atof(size_arg);
 	if ((*arg == '+' || *arg == '-') && arg[1] == '1')
-		size += atoi(arg), make_compatible = 1, arg += 2;
+		size += atoi(arg), arg += 2;
 	if (*arg)
-		return -1;
-	if (size > 0 && make_compatible && def_suf == 'b') {
-		/* We convert this manually because we may need %lld precision,
-		 * and that's not a portable sprintf() escape. */
-		char buf[128], *s = buf + sizeof buf - 1;
-		OFF_T num = size;
-		*s = '\0';
-		while (num) {
-			*--s = (char)(num % 10) + '0';
-			num /= 10;
-		}
-		if (!(*size_arg = strdup(s)))
-			out_of_memory("parse_size_arg");
+		goto failure;
+	if (size < min_value) {
+		err = size < 0 ? "too big" : "too small";
+		goto failure;
 	}
 	return size;
-}
 
+failure:
+	snprintf(err_buf, sizeof err_buf, "--%s value is %s: %s\n", opt_name, err, size_arg);
+	return -1;
+}
 
 static void create_refuse_error(int which)
 {
@@ -1464,8 +1471,6 @@ int parse_arguments(int *argc_p, const c
 			if (daemon_filter_list.head) {
 				int rej;
 				char *cp = strdup(arg);
-				if (!cp)
-					out_of_memory("parse_arguments");
 				if (!*cp)
 					rej = 1;
 				else {
@@ -1583,8 +1588,6 @@ int parse_arguments(int *argc_p, const c
 				remote_option_alloc += 16;
 				remote_options = realloc_array(remote_options,
 							const char *, remote_option_alloc);
-				if (!remote_options)
-					out_of_memory("parse_arguments");
 				if (!remote_option_cnt)
 					remote_options[0] = "ARG0";
 			}
@@ -1614,39 +1617,25 @@ int parse_arguments(int *argc_p, const c
 			break;
 
 		case OPT_MAX_SIZE:
-			if ((max_size = parse_size_arg(&max_size_arg, 'b')) < 0) {
-				snprintf(err_buf, sizeof err_buf,
-					"--max-size value is invalid: %s\n",
-					max_size_arg);
+			if ((max_size = parse_size_arg(max_size_arg, 'b', "max-size", 0)) < 0)
 				return 0;
-			}
+			max_size_arg = num_to_byte_string(max_size);
 			break;
 
 		case OPT_MIN_SIZE:
-			if ((min_size = parse_size_arg(&min_size_arg, 'b')) < 0) {
-				snprintf(err_buf, sizeof err_buf,
-					"--min-size value is invalid: %s\n",
-					min_size_arg);
+			if ((min_size = parse_size_arg(min_size_arg, 'b', "min-size", 0)) < 0)
 				return 0;
-			}
+			min_size_arg = num_to_byte_string(min_size);
 			break;
 
-		case OPT_BWLIMIT:
-			{
-				OFF_T limit = parse_size_arg(&bwlimit_arg, 'K');
-				if (limit < 0) {
-					snprintf(err_buf, sizeof err_buf,
-						"--bwlimit value is invalid: %s\n", bwlimit_arg);
-					return 0;
-				}
-				bwlimit = (limit + 512) / 1024;
-				if (limit && !bwlimit) {
-					snprintf(err_buf, sizeof err_buf,
-						"--bwlimit value is too small: %s\n", bwlimit_arg);
-					return 0;
-				}
-			}
+		case OPT_BWLIMIT: {
+			ssize_t size = parse_size_arg(bwlimit_arg, 'K', "bwlimit", 512);
+			if (size < 0)
+				return 0;
+			bwlimit_arg = num_to_byte_string(size);
+			bwlimit = (size + 512) / 1024;
 			break;
+		}
 
 		case OPT_APPEND:
 			if (am_server)
@@ -1854,6 +1843,18 @@ int parse_arguments(int *argc_p, const c
 		}
 	}
 
+	if (!max_alloc_arg) {
+		max_alloc_arg = getenv("RSYNC_MAX_ALLOC");
+		if (max_alloc_arg && !*max_alloc_arg)
+			max_alloc_arg = NULL;
+	}
+	if (max_alloc_arg) {
+		ssize_t size = parse_size_arg(max_alloc_arg, 'B', "max-alloc", 1024*1024);
+		if (size < 0)
+			return 0;
+		max_alloc = size;
+	}
+
 	if (protect_args < 0) {
 		if (am_server)
 			protect_args = 0;
@@ -2680,6 +2681,11 @@ void server_options(char **args, int *ar
 		}
 	}
 
+	if (max_alloc_arg && max_alloc != DEFAULT_MAX_ALLOC) {
+		args[ac++] = "--max-alloc";
+		args[ac++] = max_alloc_arg;
+	}
+
 	/* --delete-missing-args needs the cooperation of both sides, but
 	 * the sender can handle --ignore-missing-args by itself. */
 	if (missing_args == 2)
Index: rsync-3.1.0/params.c
===================================================================
--- rsync-3.1.0.orig/params.c
+++ rsync-3.1.0/params.c
@@ -212,11 +212,6 @@ static BOOL Section( FILE *InFile, BOOL
       {
       bSize += BUFR_INC;
       bufr   = realloc_array( bufr, char, bSize );
-      if( NULL == bufr )
-        {
-        rprintf(FLOG, "%s Memory re-allocation failure.", func);
-        return( False );
-        }
       }
 
     /* Handle a single character. */
@@ -306,11 +301,6 @@ static BOOL Parameter( FILE *InFile, BOO
       {
       bSize += BUFR_INC;
       bufr   = realloc_array( bufr, char, bSize );
-      if( NULL == bufr )
-        {
-        rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
-        return( False );
-        }
       }
 
     switch( c )
@@ -382,11 +372,6 @@ static BOOL Parameter( FILE *InFile, BOO
       {
       bSize += BUFR_INC;
       bufr   = realloc_array( bufr, char, bSize );
-      if( NULL == bufr )
-        {
-        rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
-        return( False );
-        }
       }
 
     switch( c )
@@ -639,12 +624,6 @@ int pm_process( char *FileName,
     {                                         /* allocate one, then parse,   */
     bSize = BUFR_INC;                         /* then free.                  */
     bufr = new_array( char, bSize );
-    if( NULL == bufr )
-      {
-      rprintf(FLOG, "%s memory allocation failure.\n", func);
-      fclose(InFile);
-      return( False );
-      }
     result = Parse( InFile, sfunc, pfunc );
     free( bufr );
     bufr  = NULL;
Index: rsync-3.1.0/sender.c
===================================================================
--- rsync-3.1.0.orig/sender.c
+++ rsync-3.1.0/sender.c
@@ -61,13 +61,10 @@ BOOL extra_flist_sending_enabled;
  **/
 static struct sum_struct *receive_sums(int f)
 {
-	struct sum_struct *s;
-	int32 i;
+	struct sum_struct *s = new(struct sum_struct);
 	int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
 	OFF_T offset = 0;
-
-	if (!(s = new(struct sum_struct)))
-		out_of_memory("receive_sums");
+	int32 i;
 
 	read_sum_head(f, s);
 
@@ -88,8 +85,7 @@ static struct sum_struct *receive_sums(i
 	if (s->count == 0)
 		return(s);
 
-	if (!(s->sums = new_array(struct sum_buf, s->count)))
-		out_of_memory("receive_sums");
+	s->sums = new_array(struct sum_buf, s->count);
 
 	for (i = 0; i < s->count; i++) {
 		s->sums[i].sum1 = read_int(f);
Index: rsync-3.1.0/socket.c
===================================================================
--- rsync-3.1.0.orig/socket.c
+++ rsync-3.1.0/socket.c
@@ -26,6 +26,7 @@
 
 #include "rsync.h"
 #include "itypes.h"
+#include "ifuncs.h"
 #ifdef HAVE_NETINET_IN_SYSTM_H
 #include <netinet/in_systm.h>
 #endif
@@ -250,8 +251,6 @@ int open_socket_out(char *host, int port
 
 	for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
 	errnos = new_array0(int, addr_cnt);
-	if (!errnos)
-		out_of_memory("open_socket_out");
 
 	s = -1;
 	/* Try to connect to all addresses for this machine until we get
@@ -359,8 +358,7 @@ int open_socket_out_wrapped(char *host,
 				len += hlen;
 		}
 		f = prog;
-		if (!(prog = new_array(char, len)))
-			out_of_memory("open_socket_out_wrapped");
+		prog = new_array(char, len);
 		for (t = prog; *f; f++) {
 			if (*f == '%') {
 				switch (*++f) {
@@ -428,8 +426,6 @@ static int *open_socket_in(int type, int
 
 	socks = new_array(int, maxs + 1);
 	errmsgs = new_array(char *, maxs);
-	if (!socks || !errmsgs)
-		out_of_memory("open_socket_in");
 
 	/* We may not be able to create the socket, if for example the
 	 * machine knows about IPv6 in the C library, but not in the
@@ -722,9 +718,6 @@ void set_socket_options(int fd, char *op
 
 	options = strdup(options);
 
-	if (!options)
-		out_of_memory("set_socket_options");
-
 	for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
 		int ret=0,i;
 		int value = 1;
Index: rsync-3.1.0/token.c
===================================================================
--- rsync-3.1.0.orig/token.c
+++ rsync-3.1.0/token.c
@@ -69,8 +69,7 @@ static void add_suffix(struct suffix_tre
 		if (node->letter > ltr)
 			break;
 	}
-	if (!(newnode = new(struct suffix_tree)))
-		out_of_memory("add_suffix");
+	newnode = new(struct suffix_tree);
 	newnode->sibling = node;
 	newnode->child = NULL;
 	newnode->letter = ltr;
@@ -87,8 +86,7 @@ static void add_nocompress_suffixes(cons
 	char *buf, *t;
 	const char *f = str;
 
-	if (!(buf = new_array(char, strlen(f) + 1)))
-		out_of_memory("add_nocompress_suffixes");
+	buf = new_array(char, strlen(f) + 1);
 
 	while (*f) {
 		if (*f == '/') {
@@ -126,8 +124,7 @@ static void init_set_compression(void)
 	else
 		f = lp_dont_compress(module_id);
 
-	if (!(match_list = t = new_array(char, strlen(f) + 2)))
-		out_of_memory("set_compression");
+	match_list = t = new_array(char, strlen(f) + 2);
 
 	per_file_default_level = def_compress_level;
 
@@ -222,11 +219,8 @@ static int32 simple_recv_token(int f, ch
 	static char *buf;
 	int32 n;
 
-	if (!buf) {
+	if (!buf)
 		buf = new_array(char, CHUNK_SIZE);
-		if (!buf)
-			out_of_memory("simple_recv_token");
-	}
 
 	if (residue == 0) {
 		int32 i = read_int(f);
@@ -315,8 +309,7 @@ send_deflated_token(int f, int32 token,
 				rprintf(FERROR, "compression init failed\n");
 				exit_cleanup(RERR_PROTOCOL);
 			}
-			if ((obuf = new_array(char, OBUF_SIZE)) == NULL)
-				out_of_memory("send_deflated_token");
+			obuf = new_array(char, OBUF_SIZE);
 			init_done = 1;
 		} else
 			deflateReset(&tx_strm);
@@ -463,9 +456,8 @@ static int32 recv_deflated_token(int f,
 					rprintf(FERROR, "inflate init failed\n");
 					exit_cleanup(RERR_PROTOCOL);
 				}
-				if (!(cbuf = new_array(char, MAX_DATA_COUNT))
-				    || !(dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE))))
-					out_of_memory("recv_deflated_token");
+				cbuf = new_array(char, MAX_DATA_COUNT);
+				dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE));
 				init_done = 1;
 			} else {
 				inflateReset(&rx_strm);
Index: rsync-3.1.0/uidlist.c
===================================================================
--- rsync-3.1.0.orig/uidlist.c
+++ rsync-3.1.0/uidlist.c
@@ -85,8 +85,6 @@ static struct idlist *add_to_list(struct
 				  id_t id2, uint16 flags)
 {
 	struct idlist *node = new(struct idlist);
-	if (!node)
-		out_of_memory("add_to_list");
 	node->next = *root;
 	node->u = noiu;
 	node->id = id;
@@ -160,8 +158,6 @@ static int is_in_group(gid_t gid)
 		if ((ngroups = getgroups(0, NULL)) < 0)
 			ngroups = 0;
 		gidset = new_array(GETGROUPS_T, ngroups+1);
-		if (!gidset)
-			out_of_memory("is_in_group");
 		if (ngroups > 0)
 			ngroups = getgroups(ngroups, gidset);
 		/* The default gid might not be in the list on some systems. */
@@ -174,8 +170,6 @@ static int is_in_group(gid_t gid)
 		if (DEBUG_GTE(OWN, 2)) {
 			int pos;
 			char *gidbuf = new_array(char, ngroups*21+32);
-			if (!gidbuf)
-				out_of_memory("is_in_group");
 			pos = snprintf(gidbuf, 32, "process has %d gid%s: ",
 				       ngroups, ngroups == 1? "" : "s");
 			for (n = 0; n < ngroups; n++) {
@@ -376,8 +370,6 @@ uid_t recv_user_name(int f, uid_t uid)
 	struct idlist *node;
 	int len = read_byte(f);
 	char *name = new_array(char, len+1);
-	if (!name)
-		out_of_memory("recv_user_name");
 	read_sbuf(f, name, len);
 	if (numeric_ids < 0) {
 		free(name);
@@ -392,8 +384,6 @@ gid_t recv_group_name(int f, gid_t gid,
 	struct idlist *node;
 	int len = read_byte(f);
 	char *name = new_array(char, len+1);
-	if (!name)
-		out_of_memory("recv_group_name");
 	read_sbuf(f, name, len);
 	if (numeric_ids < 0) {
 		free(name);
Index: rsync-3.1.0/util.c
===================================================================
--- rsync-3.1.0.orig/util.c
+++ rsync-3.1.0/util.c
@@ -699,8 +699,7 @@ int lock_range(int fd, int offset, int l
 }
 
 #define ENSURE_MEMSPACE(buf, type, sz, req) \
-	if ((req) > sz && !(buf = realloc_array(buf, type, sz = MAX(sz * 2, req)))) \
-		out_of_memory("glob_expand")
+	do { if ((req) > sz) buf = realloc_array(buf, type, sz = MAX(sz * 2, req)); } while(0)
 
 static inline void call_glob_match(const char *name, int len, int from_glob,
 				   char *arg, int abpos, int fbpos);
@@ -802,8 +801,7 @@ static inline void call_glob_match(const
 		glob_match(arg, abpos, fbpos);
 	} else {
 		ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
-		if (!(glob.argv[glob.argc++] = strdup(glob.arg_buf)))
-			out_of_memory("glob_match");
+		glob.argv[glob.argc++] = strdup(glob.arg_buf);
 	}
 }
 
@@ -827,8 +825,6 @@ int glob_expand(const char *arg, char **
 		s = sanitize_path(NULL, arg, "", 0, SP_KEEP_DOT_DIRS);
 	else {
 		s = strdup(arg);
-		if (!s)
-			out_of_memory("glob_expand");
 		clean_fname(s, CFN_KEEP_DOT_DIRS
 			     | CFN_KEEP_TRAILING_SLASH
 			     | CFN_COLLAPSE_DOT_DOT_DIRS);
@@ -880,8 +876,7 @@ void glob_expand_module(char *base1, cha
 		return;
 	}
 
-	if (!(arg = strdup(arg)))
-		out_of_memory("glob_expand_module");
+	arg = strdup(arg);
 
 	if (asprintf(&base," %s/", base1) < 0)
 		out_of_memory("glob_expand_module");
@@ -1092,11 +1087,10 @@ char *sanitize_path(char *dest, const ch
 			depth = 0;
 			p++;
 		}
-		if (dest) {
-			if (rlen + plen + 1 >= MAXPATHLEN)
-				return NULL;
-		} else if (!(dest = new_array(char, rlen + plen + 1)))
-			out_of_memory("sanitize_path");
+		if (!dest)
+			dest = new_array(char, MAX(rlen + plen + 1, 2));
+		else if (rlen + plen + 1 >= MAXPATHLEN)
+			return NULL;
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
 			if (rlen > 1)
@@ -1228,13 +1222,10 @@ char *normalize_path(char *path, BOOL fo
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
-		if (!(path = strdup(curr_dir)))
-			out_of_memory("normalize_path");
+		path = strdup(curr_dir);
 		curr_dir[curr_dir_len] = '\0';
-	} else if (force_newbuf) {
-		if (!(path = strdup(path)))
-			out_of_memory("normalize_path");
-	}
+	} else if (force_newbuf)
+		path = strdup(path);
 
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
 
@@ -1628,8 +1619,7 @@ struct bitbag *bitbag_create(int max_ndx
 	struct bitbag *bb = new(struct bitbag);
 	bb->slot_cnt = (max_ndx + BB_PER_SLOT_BITS - 1) / BB_PER_SLOT_BITS;
 
-	if (!(bb->bits = (uint32**)calloc(bb->slot_cnt, sizeof (uint32*))))
-		out_of_memory("bitbag_create");
+	bb->bits = (uint32**)calloc(bb->slot_cnt, sizeof (uint32*));
 
 	return bb;
 }
@@ -1710,8 +1700,7 @@ void flist_ndx_push(flist_ndx_list *lp,
 {
 	struct flist_ndx_item *item;
 
-	if (!(item = new(struct flist_ndx_item)))
-		out_of_memory("flist_ndx_push");
+	item = new(struct flist_ndx_item);
 	item->next = NULL;
 	item->ndx = ndx;
 	if (lp->tail)
@@ -1754,8 +1743,7 @@ void *expand_item_list(item_list *lp, si
 			new_size *= 2;
 		if (new_size < lp->malloced)
 			overflow_exit("expand_item_list");
-		/* Using _realloc_array() lets us pass the size, not a type. */
-		new_ptr = _realloc_array(lp->items, item_size, new_size);
+		new_ptr = realloc_buf(lp->items, new_size * item_size);
 		if (DEBUG_GTE(FLIST, 3)) {
 			rprintf(FINFO, "[%s] expand %s to %s bytes, did%s move\n",
 				who_am_i(), desc, big_num(new_size * item_size),
Index: rsync-3.1.0/util2.c
===================================================================
--- rsync-3.1.0.orig/util2.c
+++ rsync-3.1.0/util2.c
@@ -27,6 +27,10 @@
 
 extern int checksum_len;
 
+extern size_t max_alloc;
+
+char *do_malloc = "42";
+
 /**
  * Sleep for a specified number of milliseconds.
  *
@@ -57,22 +61,39 @@ int msleep(int t)
 	return True;
 }
 
-#define MALLOC_MAX 0x40000000
-
-void *_new_array(unsigned long num, unsigned int size, int use_calloc)
+/* We convert a num manually because need %lld precision, and that's not a portable sprintf() escape. */
+char *num_to_byte_string(ssize_t num)
 {
-	if (num >= MALLOC_MAX/size)
-		return NULL;
-	return use_calloc ? calloc(num, size) : malloc(num * size);
+	char buf[128], *s = buf + sizeof buf - 1;
+
+	*s = '\0';
+	while (num) {
+		*--s = (char)(num % 10) + '0';
+		num /= 10;
+	}
+	return strdup(s);
 }
 
-void *_realloc_array(void *ptr, unsigned int size, size_t num)
+void *_my_alloc(void *ptr, size_t num, size_t size, const char *file, int line)
 {
-	if (num >= MALLOC_MAX/size)
-		return NULL;
+	if (num >= max_alloc/size) {
+		if (!file)
+			return NULL;
+		rprintf(FERROR, "[%s] exceeded --max-alloc=%s setting (file=%s, line=%d)\n",
+			who_am_i(), num_to_byte_string(max_alloc), file, line);
+		exit_cleanup(RERR_MALLOC);
+	}
 	if (!ptr)
-		return malloc(size * num);
-	return realloc(ptr, size * num);
+		ptr = calloc(num, size);
+	else if (ptr == do_malloc)
+		ptr = malloc(num * size);
+	else
+		ptr = realloc(ptr, num * size);
+	if (!ptr && file) {
+		rprintf(FERROR, "[%s] out of memory (file=%s, line=%d)\n", who_am_i(), file, line);
+		exit_cleanup(RERR_MALLOC);
+	}
+	return ptr;
 }
 
 const char *sum_as_hex(const char *sum)
Index: rsync-3.1.0/xattrs.c
===================================================================
--- rsync-3.1.0.orig/xattrs.c
+++ rsync-3.1.0/xattrs.c
@@ -130,8 +130,6 @@ static ssize_t get_xattr_names(const cha
 	if (!namebuf) {
 		namebuf_len = 1024;
 		namebuf = new_array(char, namebuf_len);
-		if (!namebuf)
-			out_of_memory("get_xattr_names");
 	}
 
 	while (1) {
@@ -159,8 +157,6 @@ static ssize_t get_xattr_names(const cha
 			free(namebuf);
 		namebuf_len = list_len + 1024;
 		namebuf = new_array(char, namebuf_len);
-		if (!namebuf)
-			out_of_memory("get_xattr_names");
 	}
 
 	return list_len;
@@ -191,8 +187,7 @@ static char *get_xattr_data(const char *
 		extra_len = 1; /* request non-zero amount of memory */
 	if (datum_len + extra_len < datum_len)
 		overflow_exit("get_xattr_data");
-	if (!(ptr = new_array(char, datum_len + extra_len)))
-		out_of_memory("get_xattr_data");
+	ptr = new_array(char, datum_len + extra_len);
 
 	if (datum_len) {
 		size_t len = sys_lgetxattr(fname, name, ptr, datum_len);
@@ -264,8 +259,7 @@ static int rsync_xal_get(const char *fna
 			sum_update(ptr, datum_len);
 			free(ptr);
 
-			if (!(ptr = new_array(char, name_offset + name_len)))
-				out_of_memory("rsync_xal_get");
+			ptr = new_array(char, name_offset + name_len);
 			*ptr = XSTATE_ABBREV;
 			sum_end(ptr + 1);
 		} else
@@ -653,8 +647,6 @@ int recv_xattr_request(struct file_struc
 		if (rxa->name_len + rxa->datum_len < rxa->name_len)
 			overflow_exit("recv_xattr_request");
 		rxa->datum = new_array(char, rxa->datum_len + rxa->name_len);
-		if (!rxa->datum)
-			out_of_memory("recv_xattr_request");
 		name = rxa->datum + rxa->datum_len;
 		memcpy(name, rxa->name, rxa->name_len);
 		rxa->name = name;
@@ -723,8 +715,6 @@ void receive_xattr(int f, struct file_st
 		 || (dget_len + extra_len + name_len < dget_len))
 			overflow_exit("receive_xattr");
 		ptr = new_array(char, dget_len + extra_len + name_len);
-		if (!ptr)
-			out_of_memory("receive_xattr");
 		name = ptr + dget_len + extra_len;
 		read_buf(f, name, name_len);
 		if (name_len < 1 || name[name_len-1] != '\0') {
Index: rsync-3.1.0/rsync.h
===================================================================
--- rsync-3.1.0.orig/rsync.h
+++ rsync-3.1.0/rsync.h
@@ -1179,13 +1179,20 @@ extern int errno;
 
 /* handler for null strings in printf format */
 #define NS(s) ((s)?(s):"<NULL>")
+ 
+extern char *do_malloc;
 
 /* Convenient wrappers for malloc and realloc.  Use them. */
-#define new(type) ((type*)malloc(sizeof (type)))
-#define new0(type) ((type*)calloc(1, sizeof (type)))
-#define new_array(type, num) ((type*)_new_array((num), sizeof (type), 0))
-#define new_array0(type, num) ((type*)_new_array((num), sizeof (type), 1))
-#define realloc_array(ptr, type, num) ((type*)_realloc_array((ptr), sizeof(type), (num)))
+#define new(type) ((type*)_my_alloc(do_malloc, 1, sizeof (type), __FILE__, __LINE__))
+#define new0(type) ((type*)_my_alloc(NULL, 1, sizeof (type), __FILE__, __LINE__))
+#define realloc_buf(ptr, num) _my_alloc((ptr), (num), 1, __FILE__, __LINE__)
+
+#define new_array(type, num) ((type*)_my_alloc(do_malloc, (num), sizeof (type), __FILE__, __LINE__))
+#define new_array0(type, num) ((type*)_my_alloc(NULL, (num), sizeof (type), __FILE__, __LINE__))
+#define realloc_array(ptr, type, num) ((type*)_my_alloc((ptr), (num), sizeof (type), __FILE__, __LINE__))
+
+#undef strdup
+#define strdup(s) my_strdup(s, __FILE__, __LINE__)
 
 /* use magic gcc attributes to catch format errors */
  void rprintf(enum logcode , const char *, ...)
Index: rsync-3.1.0/t_stub.c
===================================================================
--- rsync-3.1.0.orig/t_stub.c
+++ rsync-3.1.0/t_stub.c
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This program is distributed in the hf that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -31,6 +31,7 @@ int module_dirlen = 0;
 int preserve_acls = 0;
 int preserve_times = 0;
 int preserve_xattrs = 0;
+size_t max_alloc = 1024*1024*1024;
 char *partial_dir;
 char *module_dir;
 filter_rule_list daemon_filter_list;
Index: rsync-3.1.0/Makefile.in
===================================================================
--- rsync-3.1.0.orig/Makefile.in
+++ rsync-3.1.0/Makefile.in
@@ -47,7 +47,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  po
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -129,7 +129,7 @@ getgroups$(EXEEXT): getgroups.o
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
@@ -278,7 +278,7 @@ check29: all $(CHECK_PROGS) $(CHECK_SYML
 check30: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
 	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=30
 
-wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
+wildtest.o: wildtest.c t_stub.o lib/wildmatch.c rsync.h config.h
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
openSUSE Build Service is sponsored by