ref: 4a120a381652668b7eb9313d9b8ca1835ddccb91
parent: c8a71691b4a6c979673884b2a9bdef3e805c4e31
author: aiju <devnull@localhost>
date: Mon Aug 20 10:26:19 EDT 2018
fix unbounded recursion bug in hjfs
--- a/sys/src/cmd/hjfs/dump.c
+++ b/sys/src/cmd/hjfs/dump.c
@@ -112,8 +112,8 @@
return -1;
}
-int
-willmodify(Fs *fs, Loc *l, int nolock)
+static int
+willmodify1(Fs *fs, Loc *l)
{
Buf *p;
Loc *m;
@@ -121,22 +121,13 @@
Dentry *d;
int rc;
- if((l->flags & LDUMPED) != 0)
- return 1;
- if(!nolock){
-again:
- runlock(fs);
- wlock(fs);
- }
- if(l->next != nil && willmodify(fs, l->next, 1) < 0)
- goto err;
rc = chref(fs, l->blk, 0);
if(rc < 0)
- goto err;
+ return -1;
if(rc == 0){
dprint("willmodify: block %lld has refcount 0\n", l->blk);
werrstr("phase error -- willmodify");
- goto err;
+ return -1;
}
if(rc == 1)
goto done;
@@ -143,7 +134,7 @@
p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
if(p == nil)
- goto err;
+ return -1;
d = getdent(l->next, p);
if(d != nil) for(i = 0; i < d->size; i++){
rc = getblk(fs, l->next, p, i, &r, GBREAD);
@@ -155,12 +146,12 @@
phase:
werrstr("willmodify -- phase error");
putbuf(p);
- goto err;
+ return -1;
found:
rc = getblk(fs, l->next, p, i, &r, GBWRITE);
if(rc < 0){
putbuf(p);
- goto err;
+ return -1;
}
if(rc == 0)
goto phase;
@@ -180,17 +171,50 @@
}
done:
l->flags |= LDUMPED;
+ return 0;
+}
+
+int
+willmodify(Fs *fs, Loc *l, int nolock)
+{
+ Loc **st;
+ int sti, rc;
+
+ if((l->flags & LDUMPED) != 0)
+ return 1;
if(!nolock){
+again:
+ runlock(fs);
+ wlock(fs);
+ }
+ st = emalloc(sizeof(Loc *));
+ *st = l;
+ sti = 0;
+ for(;;){
+ if((st[sti]->flags & LDUMPED) != 0 || st[sti]->next == nil)
+ break;
+ st = erealloc(st, (sti + 2) * sizeof(Loc *));
+ st[sti + 1] = st[sti]->next;
+ sti++;
+ }
+ rc = 0;
+ for(; sti >= 0; sti--){
+ rc = willmodify1(fs, st[sti]);
+ if(rc < 0){
+ free(st);
+ if(!nolock){
+ wunlock(fs);
+ rlock(fs);
+ }
+ return -1;
+ }
+ }
+ if(!nolock){
wunlock(fs);
rlock(fs);
if(chref(fs, l->blk, 0) != 1)
goto again;
}
- return 0;
-err:
- if(!nolock){
- wunlock(fs);
- rlock(fs);
- }
- return -1;
+ free(st);
+ return rc;
}