ref: 292cce2ad127d30d29ca2824f7dd484620256ceb
parent: 5bb7240ee93111a7c73adaedc0dabfa0caacbe25
author: cinap_lenrek <[email protected]>
date: Sat Oct 20 16:32:22 EDT 2018
libdisk: catch null bytes in proto file, fix memory leaks
--- a/sys/src/libdisk/proto.c
+++ b/sys/src/libdisk/proto.c
@@ -64,6 +64,8 @@
static int copyfile(Mkaux*, File*, Dir*, int);
static void freefile(File*);
+static void freeoptptr(Opt*, void*);
+static char* getline(Mkaux*);
static File* getfile(Mkaux*, File*);
static char* getmode(Mkaux*, char*, ulong*);
static char* getname(Mkaux*, char*, char**);
@@ -72,16 +74,11 @@
static char* mkpath(Mkaux*, char*, char*);
static void mktree(Mkaux*, File*, int);
static void setname(Mkaux*, Name*, File*);
+static void setopt(Mkaux*, char*, char*);
static void skipdir(Mkaux*);
static void warn(Mkaux*, char *, ...);
static void popopt(Mkaux *mkaux);
-//static void
-//mprint(char *new, char *old, Dir *d, void*)
-//{
-// print("%s %s %D\n", new, old, d);
-//}
-
int
rdproto(char *proto, char *root, Mkfsenum *mkenum, Mkfserr *mkerr, void *a)
{
@@ -151,7 +148,7 @@
int rec;
child = getfile(mkaux, me);
- if(!child)
+ if(child == nil)
return;
if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){
rec = child->elem[0] == '+';
@@ -162,13 +159,13 @@
freefile(child);
child = getfile(mkaux, me);
}
- while(child && mkaux->indent > level){
+ while(child != nil && mkaux->indent > level){
if(mkfile(mkaux, child))
domkfs(mkaux, child, mkaux->indent);
freefile(child);
child = getfile(mkaux, me);
}
- if(child){
+ if(child != nil){
freefile(child);
Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
mkaux->lineno--;
@@ -198,7 +195,7 @@
continue;
}
child.new = mkpath(mkaux, me->new, d[i].name);
- if(me->old)
+ if(me->old != nil)
child.old = mkpath(mkaux, me->old, d[i].name);
child.elem = d[i].name;
setname(mkaux, &mkaux->oldfile, &child);
@@ -205,8 +202,7 @@
if((!(d[i].mode&DMDIR) || rec) && copyfile(mkaux, &child, &d[i], 1) && rec)
mktree(mkaux, &child, rec);
free(child.new);
- if(child.old)
- free(child.old);
+ free(child.old);
}
free(d);
}
@@ -281,11 +277,11 @@
o = mkaux->opt;
if(strcmp(f->uid, "-") != 0)
d->uid = f->uid;
- else if(o && o->uid)
+ else if(o != nil && o->uid != nil)
d->uid = o->uid;
if(strcmp(f->gid, "-") != 0)
d->gid = f->gid;
- else if(o && o->gid)
+ else if(o != nil && o->gid != nil)
d->gid = o->gid;
if(f->mode != ~0){
if(permonly)
@@ -294,10 +290,10 @@
warn(mkaux, "inconsistent mode for %s", f->new);
else
d->mode = f->mode;
- } else if(o && o->mask)
+ } else if(o != nil && o->mask)
d->mode = (d->mode & ~o->mask) | (o->mode & o->mask);
- if(p = strrchr(f->new, '/'))
+ if((p = strrchr(f->new, '/')) != nil)
d->name = p+1;
else
d->name = f->new;
@@ -415,16 +411,8 @@
o = mkaux->opt;
if(o == nil || mkaux->indent > o->level){
o = emalloc(mkaux, sizeof(*o));
- if(o == nil)
- longjmp(mkaux->jmp, 1);
- if(mkaux->opt){
+ if(mkaux->opt != nil)
*o = *mkaux->opt;
- if(o->uid)
- o->uid = estrdup(mkaux, o->uid);
- if(o->gid)
- o->gid = estrdup(mkaux, o->gid);
- }else
- memset(o, 0, sizeof(*o));
o->level = mkaux->indent;
o->prev = mkaux->opt;
mkaux->opt = o;
@@ -431,12 +419,14 @@
} else if(mkaux->indent < o->level)
return;
if(strcmp(key, "skip") == 0){
- o->skip = regcomp(val);
+ freeoptptr(o, &o->skip);
+ if((o->skip = regcomp(val)) == nil)
+ warn(mkaux, "bad regular expression %s", val);
} else if(strcmp(key, "uid") == 0){
- free(o->uid);
+ freeoptptr(o, &o->uid);
o->uid = *val ? estrdup(mkaux, val) : nil;
} else if(strcmp(key, "gid") == 0){
- free(o->gid);
+ freeoptptr(o, &o->gid);
o->gid = *val ? estrdup(mkaux, val) : nil;
} else if(strcmp(key, "mode") == 0){
if(!parsemode(val, &o->mask, &o->mode))
@@ -451,23 +441,37 @@
{
Opt *o;
- while(o = mkaux->opt){
+ while((o = mkaux->opt) != nil){
if(o->level <= mkaux->indent)
break;
mkaux->opt = o->prev;
- free(o->uid);
- free(o->gid);
+ freeoptptr(o, &o->skip);
+ freeoptptr(o, &o->uid);
+ freeoptptr(o, &o->gid);
free(o);
}
}
static void
+freeoptptr(Opt *o, void *p)
+{
+ int x = (void**)p - (void**)o;
+ void *v = ((void**)o)[x];
+ if(v == nil)
+ return;
+ ((void**)o)[x] = nil;
+ if((o = o->prev) != nil)
+ if(((void**)o)[x] == v)
+ return;
+ free(v);
+}
+
+
+static void
freefile(File *f)
{
- if(f->old)
- free(f->old);
- if(f->new)
- free(f->new);
+ free(f->old);
+ free(f->new);
free(f);
}
@@ -478,27 +482,10 @@
static void
skipdir(Mkaux *mkaux)
{
- char *p, c;
int level;
- if(mkaux->indent < 0)
- return;
level = mkaux->indent;
- for(;;){
- mkaux->indent = 0;
- p = Brdline(mkaux->b, '\n');
- mkaux->lineno++;
- if(!p){
- mkaux->indent = -1;
- return;
- }
- while((c = *p++) != '\n')
- if(c == ' ')
- mkaux->indent++;
- else if(c == '\t')
- mkaux->indent += 8;
- else
- break;
+ while(getline(mkaux) != nil){
if(mkaux->indent <= level){
popopt(mkaux);
Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
@@ -508,24 +495,27 @@
}
}
-static File*
-getfile(Mkaux *mkaux, File *old)
+static char*
+getline(Mkaux *mkaux)
{
- File *f;
- char *elem;
- char *p, *s;
+ char *p;
int c;
if(mkaux->indent < 0)
- return 0;
+ return nil;
loop:
mkaux->indent = 0;
p = Brdline(mkaux->b, '\n');
mkaux->lineno++;
- if(!p){
+ if(p == nil){
mkaux->indent = -1;
- return 0;
+ return nil;
}
+ if(memchr(p, 0, Blinelen(mkaux->b)) != nil){
+ warn(mkaux, "null bytes in proto");
+ longjmp(mkaux->jmp, 1);
+ return nil;
+ }
while((c = *p++) != '\n')
if(c == ' ')
mkaux->indent++;
@@ -535,41 +525,62 @@
break;
if(c == '\n' || c == '#')
goto loop;
- p--;
+ return --p;
+}
+
+static File*
+getfile(Mkaux *mkaux, File *old)
+{
+ File *f;
+ char *elem;
+ char *p, *s;
+
+loop:
+ if((p = getline(mkaux)) == nil)
+ return nil;
popopt(mkaux);
+
*strchr(p, '\n') = 0;
- if(s = strchr(p, '=')){
+ if((s = strchr(p, '=')) != nil){
*s++ = 0;
setopt(mkaux, p, s);
goto loop;
}else
p[strlen(p)] = '\n';
- f = emalloc(mkaux, sizeof *f);
- p = getname(mkaux, p, &elem);
- if(p == nil)
+
+ if((p = getname(mkaux, p, &elem)) == nil)
return nil;
+ f = emalloc(mkaux, sizeof *f);
f->new = mkpath(mkaux, old->new, elem);
free(elem);
f->elem = utfrrune(f->new, L'/') + 1;
- p = getmode(mkaux, p, &f->mode);
- p = getname(mkaux, p, &f->uid); /* LEAK */
- if(p == nil)
+
+ if((p = getmode(mkaux, p, &f->mode)) == nil){
+ freefile(f);
return nil;
+ }
- if(!*f->uid)
- strcpy(f->uid, "-");
- p = getname(mkaux, p, &f->gid); /* LEAK */
- if(p == nil)
+ if((p = getname(mkaux, p, &f->uid)) == nil){
+ freefile(f);
return nil;
+ }
+ if(*f->uid == 0)
+ strcpy(f->uid, "-");
- if(!*f->gid)
+ if((p = getname(mkaux, p, &f->gid)) == nil){
+ freefile(f);
+ return nil;
+ }
+ if(*f->gid == 0)
strcpy(f->gid, "-");
+
f->old = getpath(mkaux, p);
- if(f->old && strcmp(f->old, "-") == 0){
+ if(f->old != nil && strcmp(f->old, "-") == 0){
free(f->old);
- f->old = 0;
+ f->old = nil;
}
+
setname(mkaux, &mkaux->oldfile, f);
return f;
@@ -587,7 +598,7 @@
while((c = *q) != '\n' && c != ' ' && c != '\t')
q++;
if(q == p)
- return 0;
+ return nil;
n = q - p;
new = emalloc(mkaux, n + 1);
memcpy(new, p, n);
@@ -613,14 +624,14 @@
return nil;
memmove(*buf, start, p-start);
- (*buf)[p-start] = '\0';
+ (*buf)[p-start] = 0;
if(**buf == '$'){
s = getenv(*buf+1);
- if(s == 0){
+ if(s == nil){
warn(mkaux, "can't read environment variable %s", *buf+1);
- skipdir(mkaux);
free(*buf);
+ skipdir(mkaux);
return nil;
}
free(*buf);
@@ -636,12 +647,11 @@
ulong m;
*xmode = ~0;
- p = getname(mkaux, p, &buf);
- if(p == nil)
+ if((p = getname(mkaux, p, &buf)) == nil)
return nil;
s = buf;
- if(!*s || strcmp(s, "-") == 0)
+ if(*s == 0 || strcmp(s, "-") == 0)
return p;
m = 0;
if(*s == 'd'){
@@ -679,7 +689,7 @@
vseprint(buf, buf+sizeof(buf), fmt, va);
va_end(va);
- if(mkaux->warn)
+ if(mkaux->warn != nil)
mkaux->warn(buf, mkaux->a);
else
fprint(2, "warning: %s\n", buf);