shithub: riscv

Download patch

ref: f428a5daaa64241f71f2221fbdd98ba48307efc2
parent: fcb974af3a3b9747083b618fb6be7a4e70df3201
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu May 10 15:46:38 EDT 2018

libplumb: fix plumbunpackpartial()

- *morep was not set in error cases
- attr and ntext could be leaked

--- a/sys/src/libplumb/mesg.c
+++ b/sys/src/libplumb/mesg.c
@@ -178,31 +178,6 @@
 	return n;
 }
 
-static int
-plumbline(char **linep, char *buf, int i, int n, int *bad)
-{
-	int starti;
-	char *p;
-
-	starti = i;
-	while(i<n && buf[i]!='\n')
-		i++;
-	if(i == n)
-		*bad = 1;
-	else{
-		p = malloc((i-starti) + 1);
-		if(p == nil)
-			*bad = 1;
-		else{
-			memmove(p, buf+starti, i-starti);
-			p[i-starti] = '\0';
-		}
-		*linep = p;
-		i++;
-	}
-	return i;
-}
-
 void
 plumbfree(Plumbmsg *m)
 {
@@ -340,56 +315,78 @@
 	return attr;
 }
 
+static char*
+plumbline(char *buf, int *o, int n)
+{
+	char *p;
+	int i;
+
+	i = *o;
+	if(i < 0 || i >= n)
+		return nil;
+	p = memchr(buf+i, '\n', n - i);
+	if(p == nil)
+		return nil;
+	n = p - (buf+i);
+	buf = malloc(n+1);
+	if(buf == nil)
+		return nil;
+	memmove(buf, p - n, n);
+	buf[n] = '\0';
+	*o = i + n+1;
+	return buf;
+}
+
 Plumbmsg*
 plumbunpackpartial(char *buf, int n, int *morep)
 {
 	Plumbmsg *m;
-	int i, bad;
 	char *ntext, *attr;
+	int i;
 
+	if(morep != nil)
+		*morep = 0;
 	m = malloc(sizeof(Plumbmsg));
 	if(m == nil)
 		return nil;
 	setmalloctag(m, getcallerpc(&buf));
 	memset(m, 0, sizeof(Plumbmsg));
-	if(morep != nil)
-		*morep = 0;
-	bad = 0;
-	i = plumbline(&m->src, buf, 0, n, &bad);
-	i = plumbline(&m->dst, buf, i, n, &bad);
-	i = plumbline(&m->wdir, buf, i, n, &bad);
-	i = plumbline(&m->type, buf, i, n, &bad);
-	i = plumbline(&attr, buf, i, n, &bad);
-	i = plumbline(&ntext, buf, i, n, &bad);
-	if(bad){
-		plumbfree(m);
-		return nil;
-	}
+	i = 0;
+	if((m->src = plumbline(buf, &i, n)) == nil)
+		goto bad;
+	if((m->dst = plumbline(buf, &i, n)) == nil)
+		goto bad;
+	if((m->wdir = plumbline(buf, &i, n)) == nil)
+		goto bad;
+	if((m->type = plumbline(buf, &i, n)) == nil)
+		goto bad;
+	if((attr = plumbline(buf, &i, n)) == nil)
+		goto bad;
 	m->attr = plumbunpackattr(attr);
 	free(attr);
+	if((ntext = plumbline(buf, &i, n)) == nil)
+		goto bad;
 	m->ndata = atoi(ntext);
-	if(m->ndata != n-i){
-		bad = 1;
-		if(morep!=nil && m->ndata>n-i)
-			*morep = m->ndata - (n-i);
-	}
 	free(ntext);
-	if(!bad){
-		m->data = malloc(n-i+1);	/* +1 for '\0' */
-		if(m->data == nil)
-			bad = 1;
-		else{
-			memmove(m->data, buf+i, m->ndata);
-			m->ndata = n-i;
-			/* null-terminate in case it's text */
-			m->data[m->ndata] = '\0';
-		}
+	if(m->ndata < 0)
+		goto bad;
+	n -= i;
+	if(n < m->ndata){
+		if(morep != nil)
+			*morep = m->ndata - n;
+		goto bad;
 	}
-	if(bad){
-		plumbfree(m);
-		m = nil;
-	}
+	m->data = malloc(m->ndata+1);	/* +1 for '\0' */
+	if(m->data == nil)
+		goto bad;
+	memmove(m->data, buf+i, m->ndata);
+	/* null-terminate in case it's text */
+	m->data[m->ndata] = '\0';
+
 	return m;
+bad:
+	plumbfree(m);
+	return nil;
 }
 
 Plumbmsg*
@@ -409,14 +406,15 @@
 	Plumbmsg *m;
 	int n, more;
 
-	buf = malloc(8192);
+	buf = malloc(n = 8192);
 	if(buf == nil)
 		return nil;
-	n = read(fd, buf, 8192);
-	m = nil;
-	if(n > 0){
+	n = read(fd, buf, n);
+	if(n <= 0)
+		m = nil;
+	else {
 		m = plumbunpackpartial(buf, n, &more);
-		if(m==nil && more>0){
+		if(m == nil && more > 0){
 			/* we now know how many more bytes to read for complete message */
 			buf = realloc(old = buf, n+more);
 			if(buf == nil){