fix(data): reject partial and malformed map data
This commit is contained in:
87
trie.c
87
trie.c
@@ -1,14 +1,33 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
static char*
|
||||
readline(Biobuf *b, char *path)
|
||||
{
|
||||
char *line;
|
||||
|
||||
errno = 0;
|
||||
line = Brdstr(b, '\n', 1);
|
||||
if(errno != 0)
|
||||
die("can't read %s: %s", path, strerror(errno));
|
||||
return line;
|
||||
}
|
||||
|
||||
static int
|
||||
newnode(Trie *t)
|
||||
{
|
||||
int cap;
|
||||
int i;
|
||||
|
||||
if(t->n >= t->cap){
|
||||
t->cap *= 2;
|
||||
t->nodes = erealloc(t->nodes, t->cap * sizeof(Tnode));
|
||||
if(t->cap > INT_MAX/2 ||
|
||||
(ulong)t->cap > ULONG_MAX/(2*sizeof(Tnode)))
|
||||
die("map is too large");
|
||||
cap = t->cap * 2;
|
||||
t->nodes = erealloc(t->nodes, (ulong)cap * sizeof(Tnode));
|
||||
t->cap = cap;
|
||||
}
|
||||
i = t->n++;
|
||||
memset(&t->nodes[i], 0, sizeof(Tnode));
|
||||
@@ -54,7 +73,7 @@ insert(Trie *t, char *key, int klen, char *val, int vlen)
|
||||
ni = ci;
|
||||
}
|
||||
free(t->nodes[ni].val);
|
||||
t->nodes[ni].val = emalloc(vlen + 1);
|
||||
t->nodes[ni].val = emalloc((ulong)vlen + 1);
|
||||
memmove(t->nodes[ni].val, val, vlen);
|
||||
t->nodes[ni].val[vlen] = '\0';
|
||||
t->nodes[ni].vlen = vlen;
|
||||
@@ -66,41 +85,45 @@ trieopen(char *path)
|
||||
Trie *t;
|
||||
Biobuf *b;
|
||||
char *line, *tab, *key, *val;
|
||||
Str s;
|
||||
int klen, vlen;
|
||||
|
||||
b = Bopen(path, OREAD);
|
||||
if(b == nil)
|
||||
die("can't open: %s", path);
|
||||
die("can't open %s: %s", path, strerror(errno));
|
||||
t = emalloc(sizeof(*t));
|
||||
t->cap = 1024;
|
||||
t->nodes = emalloc(t->cap * sizeof(Tnode));
|
||||
t->nodes = emalloc((ulong)t->cap * sizeof(Tnode));
|
||||
t->n = 0;
|
||||
t->root = newnode(t);
|
||||
while((line = Brdstr(b, '\n', 1)) != nil){
|
||||
vlen = strlen(line);
|
||||
while((line = readline(b, path)) != nil){
|
||||
vlen = Blinelen(b);
|
||||
if(memchr(line, '\0', vlen) != nil)
|
||||
die("NUL in map: %s", path);
|
||||
if(vlen > 0 && line[vlen-1] == '\r')
|
||||
line[--vlen] = '\0';
|
||||
if(line[0] == '\0' || line[0] == ';'){
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
tab = strchr(line, '\t');
|
||||
if(tab == nil || tab == line || tab[1] == '\0' ||
|
||||
strchr(tab+1, '\t') != nil)
|
||||
tab = memchr(line, '\t', vlen);
|
||||
if(tab == nil || tab == line || tab == line+vlen-1 ||
|
||||
memchr(tab+1, '\t', line+vlen-(tab+1)) != nil)
|
||||
die("malformed map: %s", path);
|
||||
*tab = '\0';
|
||||
key = line;
|
||||
klen = tab - line;
|
||||
if(utflen(key) > Maxrunes)
|
||||
die("map key too long: %s", path);
|
||||
if(!sinit(&s, key, klen))
|
||||
die("invalid or oversized map key: %s", path);
|
||||
val = tab + 1;
|
||||
vlen = strlen(val);
|
||||
if(utflen(val) > Maxrunes)
|
||||
die("map value too long: %s", path);
|
||||
vlen = line + vlen - val;
|
||||
if(!sinit(&s, val, vlen))
|
||||
die("invalid or oversized map value: %s", path);
|
||||
insert(t, key, klen, val, vlen);
|
||||
free(line);
|
||||
}
|
||||
Bterm(b);
|
||||
if(Bterm(b) < 0)
|
||||
die("can't close %s: %s", path, strerror(errno));
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -117,46 +140,30 @@ trieclose(Trie *t)
|
||||
free(t);
|
||||
}
|
||||
|
||||
char*
|
||||
trieget(Trie *t, char *key, int klen, int *vlen)
|
||||
{
|
||||
int ni;
|
||||
int i;
|
||||
|
||||
if(t == nil || klen < 0 || (klen > 0 && key == nil))
|
||||
return nil;
|
||||
ni = t->root;
|
||||
for(i = 0; i < klen; i++){
|
||||
ni = find(t, ni, key[i]);
|
||||
if(ni < 0)
|
||||
return nil;
|
||||
}
|
||||
if(t->nodes[ni].val == nil)
|
||||
return nil;
|
||||
if(vlen != nil)
|
||||
*vlen = t->nodes[ni].vlen;
|
||||
return t->nodes[ni].val;
|
||||
}
|
||||
|
||||
int
|
||||
trielookup(Trie *t, char *key, int klen, char **val, int *vlen)
|
||||
{
|
||||
int ni;
|
||||
int i;
|
||||
|
||||
if(val != nil)
|
||||
*val = nil;
|
||||
if(vlen != nil)
|
||||
*vlen = 0;
|
||||
if(t == nil || klen < 0 || (klen > 0 && key == nil))
|
||||
return 0;
|
||||
return TrieMiss;
|
||||
ni = t->root;
|
||||
for(i = 0; i < klen; i++){
|
||||
ni = find(t, ni, key[i]);
|
||||
if(ni < 0)
|
||||
return 0;
|
||||
return TrieMiss;
|
||||
}
|
||||
if(t->nodes[ni].val != nil){
|
||||
if(val != nil)
|
||||
*val = t->nodes[ni].val;
|
||||
if(vlen != nil)
|
||||
*vlen = t->nodes[ni].vlen;
|
||||
return TrieExact;
|
||||
}
|
||||
return 1;
|
||||
return TriePrefix;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user