diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-10-05 04:31:31 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-10-05 04:31:31 +0200 |
commit | 0e09795831f37b86206e4dc9b3a0ac8bcd90401e (patch) | |
tree | 22e593360937f5d58497f3aa46ee3791520ac767 /sys/src/cmd/dossrv/dossubs.c | |
parent | ec518776982d6d1173683a1108e7537fc329ed43 (diff) |
dossrv: handle file offsets > 2^31
maximum file size is 4GB-1 as the file length is stored in
a 32 bit long. make sure it doesnt overflow on write or
or truncate. interpret the file length as unsigned. pass
vlong to readfile()/writefile()/truncfile() so we can
handle overflows and not just ignore the upper bits.
Diffstat (limited to 'sys/src/cmd/dossrv/dossubs.c')
-rw-r--r-- | sys/src/cmd/dossrv/dossubs.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/src/cmd/dossrv/dossubs.c b/sys/src/cmd/dossrv/dossubs.c index 8c4af3701..a48f735fb 100644 --- a/sys/src/cmd/dossrv/dossubs.c +++ b/sys/src/cmd/dossrv/dossubs.c @@ -674,7 +674,7 @@ emptydir(Xfile *f) } long -readdir(Xfile *f, void *vbuf, long offset, long count) +readdir(Xfile *f, void *vbuf, vlong offset, long count) { Xfs *xf; Dosbpb *bp; @@ -921,7 +921,7 @@ error: } long -readfile(Xfile *f, void *vbuf, long offset, long count) +readfile(Xfile *f, void *vbuf, vlong offset, long count) { Xfs *xf = f->xf; Dosbpb *bp = xf->ptr; @@ -930,7 +930,12 @@ readfile(Xfile *f, void *vbuf, long offset, long count) int isect, addr, o, c; Iosect *p; uchar *buf; - long length, rcnt; + ulong length, rcnt; + + if(offset >= MAXFILELEN) + return 0; + if(offset+count > MAXFILELEN) + count = MAXFILELEN - offset; rcnt = 0; length = GLONG(d->length); @@ -961,17 +966,24 @@ readfile(Xfile *f, void *vbuf, long offset, long count) } long -writefile(Xfile *f, void *vbuf, long offset, long count) +writefile(Xfile *f, void *vbuf, vlong offset, long count) { Xfs *xf = f->xf; Dosbpb *bp = xf->ptr; Dosptr *dp = f->ptr; Dosdir *d = dp->d; - int isect, addr = 0, o, c; + int isect, addr, o, c; Iosect *p; uchar *buf; - long length, rcnt = 0, dlen; + ulong length, rcnt, dlen; + + if(offset >= MAXFILELEN) + return 0; + if(offset+count > MAXFILELEN) + count = MAXFILELEN - offset; + rcnt = 0; + addr = 0; buf = vbuf; isect = offset/bp->sectsize; o = offset%bp->sectsize; @@ -997,7 +1009,7 @@ writefile(Xfile *f, void *vbuf, long offset, long count) rcnt += c; o = 0; } - if(rcnt <= 0 && addr < 0) + if(addr < 0) return -1; length = 0; dlen = GLONG(d->length); @@ -1016,13 +1028,17 @@ writefile(Xfile *f, void *vbuf, long offset, long count) } int -truncfile(Xfile *f, long length) +truncfile(Xfile *f, vlong length) { Xfs *xf = f->xf; Dosbpb *bp = xf->ptr; Dosptr *dp = f->ptr; Dosdir *d = dp->d; - long clust, next, n; + long clust, next; + vlong n; + + if(length > MAXFILELEN) + return -1; mlock(bp); clust = getstart(f->xf, d); @@ -1093,7 +1109,7 @@ getdir(Xfs *xfs, Dir *dp, Dosdir *d, int addr, int offset) dp->mode |= DMDIR|0111; dp->length = 0; }else - dp->length = GLONG(d->length); + dp->length = (ulong)GLONG(d->length); if(d->attr & DSYSTEM){ dp->mode |= DMEXCL; if(iscontig(xfs, d)) @@ -1898,7 +1914,7 @@ dirdump(void *vdbuf) i = GSHORT(d->adate); s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31); - seprint(s, ebuf, " %d %d", GSHORT(d->start), GSHORT(d->length)); + seprint(s, ebuf, " %d %lud", GSHORT(d->start), (ulong)GLONG(d->length)); } chat("%s\n", buf); } |