shithub: git9

Download patch

ref: 6f767f2ae82dee8cbcfdf39c95a7a952c0e0565a
parent: f205736514bcfbbab5dc17a7db5d5a89b7961cc5
author: Ori Bernstein <[email protected]>
date: Fri Dec 4 10:57:40 EST 2020

all: convenience api for checking overflow

we were using emalloc and erealloc to allocate
or grow arrays, often without checking for
overflow. This code adds a check for overflow,
using a uvlong and capping to 2 gigabytes of
array -- which ought to be enough for our uses.

If bigger arrays end up needed, we can tweak
the overflow checks in one place.

--- a/delta.c
+++ b/delta.c
@@ -36,7 +36,7 @@
 		db = dt->b;
 		dt->sz *= 2;
 		dt->nb = 0;
-		dt->b = emalloc(dt->sz * sizeof(Dblock));
+		dt->b = eamalloc(dt->sz, sizeof(Dblock));
 		for(i = 0; i < sz; i++)
 			if(db[i].buf != nil)
 				addblk(dt, db[i].buf, db[i].len, db[i].off, db[i].rhash);
@@ -112,7 +112,7 @@
 	rh = 0;
 	dt->nb = 0;
 	dt->sz = 128;
-	dt->b = emalloc(dt->sz*sizeof(Dblock));
+	dt->b = eamalloc(dt->sz, sizeof(Dblock));
 	while(e != bp + nbase){
 		e += nextblk(s, bp + nbase, &rh);
 		addblk(dt, s, e - s, s - bp, rh);
--- a/fetch.c
+++ b/fetch.c
@@ -175,8 +175,8 @@
 	nref = 0;
 	refsz = 16;
 	first = 1;
-	have = emalloc(refsz * sizeof(have[0]));
-	want = emalloc(refsz * sizeof(want[0]));
+	have = eamalloc(refsz, sizeof(have[0]));
+	want = eamalloc(refsz, sizeof(want[0]));
 	while(1){
 		n = readpkt(c, buf, sizeof(buf));
 		if(n == -1)
--- a/fs.c
+++ b/fs.c
@@ -669,7 +669,7 @@
 	oaux = o->aux;
 	aux = emalloc(sizeof(Gitaux));
 	aux->ncrumb = oaux->ncrumb;
-	aux->crumb = emalloc(oaux->ncrumb * sizeof(Crumb));
+	aux->crumb = eamalloc(oaux->ncrumb, sizeof(Crumb));
 	for(i = 0; i < aux->ncrumb; i++){
 		aux->crumb[i] = oaux->crumb[i];
 		aux->crumb[i].name = estrdup(oaux->crumb[i].name);
--- a/git.h
+++ b/git.h
@@ -269,7 +269,9 @@
 
 /* util functions */
 void	dprint(int, char *, ...);
+void	*eamalloc(ulong, ulong);
 void	*emalloc(ulong);
+void	*earealloc(void *, ulong, ulong);
 void	*erealloc(void *, ulong);
 char	*estrdup(char *);
 int	slurpdir(char *, Dir **);
--- a/objset.c
+++ b/objset.c
@@ -8,7 +8,7 @@
 {
 	s->sz = 16;
 	s->nobj = 0;
-	s->obj = emalloc(s->sz * sizeof(Hash));
+	s->obj = eamalloc(s->sz, sizeof(Hash));
 }
 
 void
@@ -41,7 +41,7 @@
 
 		s->sz *= 2;
 		s->nobj = 0;
-		s->obj = emalloc(s->sz * sizeof(Hash));
+		s->obj = eamalloc(s->sz, sizeof(Hash));
 		for(i = 0; i < sz; i++)
 			if(obj[i])
 				osadd(s, obj[i]);
--- a/ref.c
+++ b/ref.c
@@ -335,7 +335,7 @@
 		free(q);
 		q = n;
 	}
-	*res = emalloc(keep.nobj*sizeof(Object*));
+	*res = eamalloc(keep.nobj, sizeof(Object*));
 	*nres = 0;
 	for(i = 0; i < keep.sz; i++){
 		if(keep.obj[i] != nil && !oshas(&drop, keep.obj[i]->hash)){
@@ -568,7 +568,7 @@
 		free(ev.stk);
 		return -1;
 	}
-	h = emalloc(ev.nstk*sizeof(Hash));
+	h = eamalloc(ev.nstk, sizeof(Hash));
 	for(i = 0; i < ev.nstk; i++)
 		h[i] = ev.stk[i]->hash;
 	*r = h;
--- a/save.c
+++ b/save.c
@@ -240,8 +240,8 @@
 	r = -1;
 	nsub = 0;
 	nent = t->tree->nent;
-	ent = emalloc(nent * sizeof(*ent));
-	sub = emalloc((epath - path)*sizeof(Object*));
+	ent = eamalloc(nent, sizeof(*ent));
+	sub = eamalloc((epath - path), sizeof(Object*));
 	memcpy(ent, t->tree->ent, nent*sizeof(*ent));
 	for(p = path; p != epath; p = ep){
 		ne = pathelt(elt, sizeof(elt), *p + off, &isdir);
--- a/send.c
+++ b/send.c
@@ -41,8 +41,8 @@
 	if(sendall)
 		return listrefs(tailp, refp);
 	nu = 0;
-	tail = emalloc((nremoved + nbranch)*sizeof(Hash));
-	ref = emalloc((nremoved + nbranch)*sizeof(char*));
+	tail = eamalloc((nremoved + nbranch), sizeof(Hash));
+	ref = eamalloc((nremoved + nbranch), sizeof(char*));
 	for(i = 0; i < nbranch; i++){
 		ref[nu] = estrdup(branch[i]);
 		if(resolveref(&tail[nu], branch[i]) == -1)
@@ -108,7 +108,7 @@
 
 	first = 1;
 	nupd = readours(&ours, &refs);
-	theirs = emalloc(nupd*sizeof(Hash));
+	theirs = eamalloc(nupd, sizeof(Hash));
 	while(1){
 		n = readpkt(c, buf, sizeof(buf));
 		if(n == -1)
--- a/util.c
+++ b/util.c
@@ -8,6 +8,7 @@
 Hash Zhash;
 
 int chattygit;
+int hidepct;
 
 Object*
 emptydir(void)
@@ -61,11 +62,41 @@
 }
 
 void *
+eamalloc(ulong n, ulong sz)
+{
+	uvlong na;
+	void *v;
+
+	if((na = (uvlong)n*(uvlong)sz) >= (1ULL<<30))
+		sysfatal("alloc: overflow");
+	v = mallocz(na, 1);
+	if(v == nil)
+		sysfatal("malloc: %r");
+	setmalloctag(v, getcallerpc(&n));
+	return v;
+}
+
+void *
 erealloc(void *p, ulong n)
 {
 	void *v;
 	
 	v = realloc(p, n);
+	if(v == nil)
+		sysfatal("realloc: %r");
+	setmalloctag(v, getcallerpc(&p));
+	return v;
+}
+
+void *
+earealloc(void *p, ulong n, ulong sz)
+{
+	uvlong na;
+	void *v;
+
+	if((na = (uvlong)n*(uvlong)sz) >= (1ULL<<30))
+		sysfatal("alloc: overflow");
+	v = realloc(p, na);
 	if(v == nil)
 		sysfatal("realloc: %r");
 	setmalloctag(v, getcallerpc(&p));