fix(data): reject partial and malformed map data
This commit is contained in:
46
dict.c
46
dict.c
@@ -1,6 +1,19 @@
|
||||
#include <errno.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;
|
||||
}
|
||||
|
||||
void
|
||||
dictlookup(Dictreq *req, Dictres *res)
|
||||
{
|
||||
@@ -33,7 +46,10 @@ dictlookup(Dictreq *req, Dictres *res)
|
||||
sp = p;
|
||||
while(p < e && *p != ' ')
|
||||
p++;
|
||||
sinit(&tmp, sp, p - sp);
|
||||
if(!sinit(&tmp, sp, p - sp)){
|
||||
res->nkouho = 0;
|
||||
return;
|
||||
}
|
||||
if(req->lang == LangEMOJI || scmp(&tmp, &req->key) != 0)
|
||||
res->kouho[res->nkouho++] = tmp;
|
||||
if(p < e)
|
||||
@@ -63,45 +79,49 @@ dictopen(char *path)
|
||||
{
|
||||
Hmap *h;
|
||||
Biobuf *b;
|
||||
Str key;
|
||||
Str key, tmp;
|
||||
char *line, *tab, *p, *e;
|
||||
int len, lineno;
|
||||
|
||||
b = Bopen(path, OREAD);
|
||||
if(b == nil)
|
||||
die("can't open: %s", path);
|
||||
die("can't open %s: %s", path, strerror(errno));
|
||||
h = hmapalloc(4096);
|
||||
lineno = 0;
|
||||
while((line = Brdstr(b, '\n', 1)) != nil){
|
||||
while((line = readline(b, path)) != nil){
|
||||
lineno++;
|
||||
len = strlen(line);
|
||||
len = Blinelen(b);
|
||||
if(memchr(line, '\0', len) != nil)
|
||||
die("NUL in dictionary: %s:%d", path, lineno);
|
||||
if(len > 0 && line[len-1] == '\r')
|
||||
line[--len] = '\0';
|
||||
if(len == 0 || line[0] == ';'){
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
tab = strchr(line, '\t');
|
||||
tab = memchr(line, '\t', len);
|
||||
if(tab == nil || tab == line || tab >= line + len - 1 ||
|
||||
strchr(tab+1, '\t') != nil)
|
||||
memchr(tab+1, '\t', line+len-(tab+1)) != nil)
|
||||
die("malformed dictionary: %s:%d", path, lineno);
|
||||
*tab = '\0';
|
||||
if(utflen(line) > Maxrunes)
|
||||
die("dictionary key too long: %s:%d", path, lineno);
|
||||
if(!sinit(&key, line, tab-line))
|
||||
die("invalid or oversized dictionary key: %s:%d",
|
||||
path, lineno);
|
||||
for(p = tab+1; p < line+len; p = e+1){
|
||||
e = memchr(p, ' ', line+len-p);
|
||||
if(e == nil)
|
||||
e = line+len;
|
||||
if(utfnlen(p, e-p) > Maxrunes)
|
||||
die("dictionary candidate too long: %s:%d", path, lineno);
|
||||
if(!sinit(&tmp, p, e-p))
|
||||
die("invalid or oversized dictionary candidate: %s:%d",
|
||||
path, lineno);
|
||||
if(e == line+len)
|
||||
break;
|
||||
}
|
||||
sinit(&key, line, tab - line);
|
||||
hmapset(&h, &key, tab+1, len - (tab - line) - 1);
|
||||
free(line);
|
||||
}
|
||||
Bterm(b);
|
||||
if(Bterm(b) < 0)
|
||||
die("can't close %s: %s", path, strerror(errno));
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user