fix(data): reject partial and malformed map data

This commit is contained in:
2026-08-14 23:09:55 +09:00
parent 38475318db
commit bfe83d0119
10 changed files with 220 additions and 125 deletions

46
dict.c
View File

@@ -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;
}