libdisk: catch null bytes in proto file, fix memory leaks

This commit is contained in:
cinap_lenrek 2018-10-20 20:32:22 +02:00
parent 5bb7240ee9
commit 292cce2ad1

View file

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