libplumb: fix plumbunpackpartial()
- *morep was not set in error cases - attr and ntext could be leaked
This commit is contained in:
parent
fcb974af3a
commit
f428a5daaa
1 changed files with 61 additions and 63 deletions
|
@ -178,31 +178,6 @@ plumbsend(int fd, Plumbmsg *m)
|
||||||
return n;
|
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
|
void
|
||||||
plumbfree(Plumbmsg *m)
|
plumbfree(Plumbmsg *m)
|
||||||
{
|
{
|
||||||
|
@ -340,56 +315,78 @@ plumbdelattr(Plumbattr *attr, char *name)
|
||||||
return attr;
|
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*
|
Plumbmsg*
|
||||||
plumbunpackpartial(char *buf, int n, int *morep)
|
plumbunpackpartial(char *buf, int n, int *morep)
|
||||||
{
|
{
|
||||||
Plumbmsg *m;
|
Plumbmsg *m;
|
||||||
int i, bad;
|
|
||||||
char *ntext, *attr;
|
char *ntext, *attr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(morep != nil)
|
||||||
|
*morep = 0;
|
||||||
m = malloc(sizeof(Plumbmsg));
|
m = malloc(sizeof(Plumbmsg));
|
||||||
if(m == nil)
|
if(m == nil)
|
||||||
return nil;
|
return nil;
|
||||||
setmalloctag(m, getcallerpc(&buf));
|
setmalloctag(m, getcallerpc(&buf));
|
||||||
memset(m, 0, sizeof(Plumbmsg));
|
memset(m, 0, sizeof(Plumbmsg));
|
||||||
if(morep != nil)
|
i = 0;
|
||||||
*morep = 0;
|
if((m->src = plumbline(buf, &i, n)) == nil)
|
||||||
bad = 0;
|
goto bad;
|
||||||
i = plumbline(&m->src, buf, 0, n, &bad);
|
if((m->dst = plumbline(buf, &i, n)) == nil)
|
||||||
i = plumbline(&m->dst, buf, i, n, &bad);
|
goto bad;
|
||||||
i = plumbline(&m->wdir, buf, i, n, &bad);
|
if((m->wdir = plumbline(buf, &i, n)) == nil)
|
||||||
i = plumbline(&m->type, buf, i, n, &bad);
|
goto bad;
|
||||||
i = plumbline(&attr, buf, i, n, &bad);
|
if((m->type = plumbline(buf, &i, n)) == nil)
|
||||||
i = plumbline(&ntext, buf, i, n, &bad);
|
goto bad;
|
||||||
if(bad){
|
if((attr = plumbline(buf, &i, n)) == nil)
|
||||||
plumbfree(m);
|
goto bad;
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
m->attr = plumbunpackattr(attr);
|
m->attr = plumbunpackattr(attr);
|
||||||
free(attr);
|
free(attr);
|
||||||
|
if((ntext = plumbline(buf, &i, n)) == nil)
|
||||||
|
goto bad;
|
||||||
m->ndata = atoi(ntext);
|
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);
|
free(ntext);
|
||||||
if(!bad){
|
if(m->ndata < 0)
|
||||||
m->data = malloc(n-i+1); /* +1 for '\0' */
|
goto bad;
|
||||||
|
n -= i;
|
||||||
|
if(n < m->ndata){
|
||||||
|
if(morep != nil)
|
||||||
|
*morep = m->ndata - n;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
m->data = malloc(m->ndata+1); /* +1 for '\0' */
|
||||||
if(m->data == nil)
|
if(m->data == nil)
|
||||||
bad = 1;
|
goto bad;
|
||||||
else{
|
|
||||||
memmove(m->data, buf+i, m->ndata);
|
memmove(m->data, buf+i, m->ndata);
|
||||||
m->ndata = n-i;
|
|
||||||
/* null-terminate in case it's text */
|
/* null-terminate in case it's text */
|
||||||
m->data[m->ndata] = '\0';
|
m->data[m->ndata] = '\0';
|
||||||
}
|
|
||||||
}
|
|
||||||
if(bad){
|
|
||||||
plumbfree(m);
|
|
||||||
m = nil;
|
|
||||||
}
|
|
||||||
return m;
|
return m;
|
||||||
|
bad:
|
||||||
|
plumbfree(m);
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plumbmsg*
|
Plumbmsg*
|
||||||
|
@ -409,14 +406,15 @@ plumbrecv(int fd)
|
||||||
Plumbmsg *m;
|
Plumbmsg *m;
|
||||||
int n, more;
|
int n, more;
|
||||||
|
|
||||||
buf = malloc(8192);
|
buf = malloc(n = 8192);
|
||||||
if(buf == nil)
|
if(buf == nil)
|
||||||
return nil;
|
return nil;
|
||||||
n = read(fd, buf, 8192);
|
n = read(fd, buf, n);
|
||||||
|
if(n <= 0)
|
||||||
m = nil;
|
m = nil;
|
||||||
if(n > 0){
|
else {
|
||||||
m = plumbunpackpartial(buf, n, &more);
|
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 */
|
/* we now know how many more bytes to read for complete message */
|
||||||
buf = realloc(old = buf, n+more);
|
buf = realloc(old = buf, n+more);
|
||||||
if(buf == nil){
|
if(buf == nil){
|
||||||
|
|
Loading…
Reference in a new issue