libc: fix out of bounds access in dirpackage(), simplify
- dirpackage() was not checking if the stat entry lies within the buffer. fixed. - simplify dirpackage(), as we process all the bytes from the buffer, we do not need to track "ss" here as its the same as "ts". - zero Dir* array pointer early in dirread() and dirreadall() and avoid calling dirpackage on <= buffer length.
This commit is contained in:
parent
4ed396d438
commit
8fd1aa2626
1 changed files with 12 additions and 17 deletions
|
@ -7,29 +7,22 @@ long
|
||||||
dirpackage(uchar *buf, long ts, Dir **d)
|
dirpackage(uchar *buf, long ts, Dir **d)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
long ss, i, n, nn, m;
|
long i, n, nn, m;
|
||||||
|
|
||||||
*d = nil;
|
|
||||||
if(ts <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first find number of all stats, check they look like stats, & size all associated strings
|
* first find number of all stats, check they look like stats, & size all associated strings
|
||||||
*/
|
*/
|
||||||
ss = 0;
|
|
||||||
n = 0;
|
n = 0;
|
||||||
for(i = 0; i < ts; i += m){
|
for(i = 0; i < ts; i += m){
|
||||||
|
if(i+BIT16SZ >= ts)
|
||||||
|
return -1;
|
||||||
m = BIT16SZ + GBIT16(&buf[i]);
|
m = BIT16SZ + GBIT16(&buf[i]);
|
||||||
if(statcheck(&buf[i], m) < 0)
|
if(i+m > ts || statcheck(&buf[i], m) < 0)
|
||||||
break;
|
return -1;
|
||||||
ss += m;
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i != ts)
|
*d = malloc(n * sizeof(Dir) + ts);
|
||||||
return -1;
|
|
||||||
|
|
||||||
*d = malloc(n * sizeof(Dir) + ss);
|
|
||||||
if(*d == nil)
|
if(*d == nil)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -39,8 +32,8 @@ dirpackage(uchar *buf, long ts, Dir **d)
|
||||||
s = (char*)*d + n * sizeof(Dir);
|
s = (char*)*d + n * sizeof(Dir);
|
||||||
nn = 0;
|
nn = 0;
|
||||||
for(i = 0; i < ts; i += m){
|
for(i = 0; i < ts; i += m){
|
||||||
m = BIT16SZ + GBIT16((uchar*)&buf[i]);
|
m = BIT16SZ + GBIT16(&buf[i]);
|
||||||
if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){
|
if(i+m > ts || nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){
|
||||||
free(*d);
|
free(*d);
|
||||||
*d = nil;
|
*d = nil;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -58,11 +51,12 @@ dirread(int fd, Dir **d)
|
||||||
uchar *buf;
|
uchar *buf;
|
||||||
long ts;
|
long ts;
|
||||||
|
|
||||||
|
*d = nil;
|
||||||
buf = malloc(DIRMAX);
|
buf = malloc(DIRMAX);
|
||||||
if(buf == nil)
|
if(buf == nil)
|
||||||
return -1;
|
return -1;
|
||||||
ts = read(fd, buf, DIRMAX);
|
ts = read(fd, buf, DIRMAX);
|
||||||
if(ts >= 0)
|
if(ts > 0)
|
||||||
ts = dirpackage(buf, ts, d);
|
ts = dirpackage(buf, ts, d);
|
||||||
free(buf);
|
free(buf);
|
||||||
return ts;
|
return ts;
|
||||||
|
@ -74,6 +68,7 @@ dirreadall(int fd, Dir **d)
|
||||||
uchar *buf, *nbuf;
|
uchar *buf, *nbuf;
|
||||||
long n, ts;
|
long n, ts;
|
||||||
|
|
||||||
|
*d = nil;
|
||||||
buf = nil;
|
buf = nil;
|
||||||
ts = 0;
|
ts = 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
|
@ -88,7 +83,7 @@ dirreadall(int fd, Dir **d)
|
||||||
break;
|
break;
|
||||||
ts += n;
|
ts += n;
|
||||||
}
|
}
|
||||||
if(ts >= 0)
|
if(ts > 0)
|
||||||
ts = dirpackage(buf, ts, d);
|
ts = dirpackage(buf, ts, d);
|
||||||
free(buf);
|
free(buf);
|
||||||
if(ts == 0 && n < 0)
|
if(ts == 0 && n < 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue