fix(data): reject partial and malformed map data
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
void
|
||||
dictionary_candidates(struct ct *t)
|
||||
{
|
||||
static char malformed[] = { 'o', 'k', ' ', (char)0x80 };
|
||||
char many[512], item[8];
|
||||
char *p;
|
||||
Dictreq req;
|
||||
@@ -53,6 +54,11 @@ dictionary_candidates(struct ct *t)
|
||||
CT_EQ_INT(t, 0, scmp(&req.pre, &res.key));
|
||||
checkstr(t, "first capped candidate", "c00", &res.kouho[0]);
|
||||
checkstr(t, "last capped candidate", "c31", &res.kouho[31]);
|
||||
key = mkstr("malformed");
|
||||
hmapset(&lang->dict, &key, malformed, sizeof malformed);
|
||||
req.key = key;
|
||||
dictlookup(&req, &res);
|
||||
CT_EQ_INT(t, 0, res.nkouho);
|
||||
cleanup:
|
||||
hmapfree(lang->dict);
|
||||
lang->dict = saved;
|
||||
|
||||
@@ -3,19 +3,48 @@
|
||||
void
|
||||
str_init_utf8(struct ct *t)
|
||||
{
|
||||
static char badtail[] = { 'a', (char)0x80 };
|
||||
static char incomplete[] = { (char)0xea, (char)0xb0 };
|
||||
static char overlong[] = { (char)0xc0, (char)0xaf };
|
||||
static char outofrange[] = {
|
||||
(char)0xf4, (char)0x90, (char)0x80, (char)0x80,
|
||||
};
|
||||
static char surrogate[] = {
|
||||
(char)0xed, (char)0xa0, (char)0x80,
|
||||
};
|
||||
static char unexpected[] = { (char)0x80 };
|
||||
static const struct {
|
||||
char *name;
|
||||
char *src;
|
||||
int n;
|
||||
int ok;
|
||||
char *want;
|
||||
} cases[] = {
|
||||
{ "canonical Runeerror", "\xef\xbf\xbd", 3, 1, "\xef\xbf\xbd" },
|
||||
{ "incomplete", incomplete, sizeof incomplete, 0, "" },
|
||||
{ "unexpected continuation", unexpected, sizeof unexpected, 0, "" },
|
||||
{ "overlong", overlong, sizeof overlong, 0, "" },
|
||||
{ "surrogate", surrogate, sizeof surrogate, 0, "" },
|
||||
{ "out of range", outofrange, sizeof outofrange, 0, "" },
|
||||
{ "bad tail", badtail, sizeof badtail, 0, "" },
|
||||
};
|
||||
char full[Maxrunes+2];
|
||||
char incomplete[] = { (char)0xea, (char)0xb0 };
|
||||
Str s;
|
||||
int i;
|
||||
|
||||
s = mkstr("A한😀");
|
||||
CT_EQ_INT(t, 3, s.n);
|
||||
checkstr(t, "round trip", "A한😀", &s);
|
||||
sinit(&s, incomplete, sizeof incomplete);
|
||||
CT_EQ_INT(t, 0, s.n);
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
memset(&s, 0xa5, sizeof s);
|
||||
if(sinit(&s, cases[i].src, cases[i].n) != cases[i].ok)
|
||||
CT_ERRORF(t, "%s: wrong validity", cases[i].name);
|
||||
checkstr(t, cases[i].name, cases[i].want, &s);
|
||||
}
|
||||
memset(full, 'a', sizeof full);
|
||||
full[sizeof full-1] = '\0';
|
||||
sinit(&s, full, strlen(full));
|
||||
CT_EQ_INT(t, Maxrunes, s.n);
|
||||
CT_CHECK(t, !sinit(&s, full, strlen(full)));
|
||||
CT_EQ_INT(t, 0, s.n);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -89,9 +118,9 @@ str_invalid_and_full_appends(struct ct *t)
|
||||
Str s;
|
||||
int i;
|
||||
|
||||
sinit(&s, nil, 1);
|
||||
CT_CHECK(t, !sinit(&s, nil, 1));
|
||||
CT_EQ_INT(t, 0, s.n);
|
||||
sinit(&s, "x", -1);
|
||||
CT_CHECK(t, !sinit(&s, "x", -1));
|
||||
CT_EQ_INT(t, 0, s.n);
|
||||
for(i = 0; i < Maxrunes; i++)
|
||||
s.r[i] = 'a';
|
||||
|
||||
@@ -3,29 +3,41 @@
|
||||
void
|
||||
trie_exact_prefix_and_duplicate(struct ct *t)
|
||||
{
|
||||
char *v, *sentinel;
|
||||
static const struct {
|
||||
char *key;
|
||||
int klen;
|
||||
int match;
|
||||
char *want;
|
||||
} cases[] = {
|
||||
{ "a", 1, TrieExact, "alpha" },
|
||||
{ "dupli", 5, TriePrefix, nil },
|
||||
{ "duplicate", 9, TrieExact, "second" },
|
||||
{ "missing", 7, TrieMiss, nil },
|
||||
{ nil, 1, TrieMiss, nil },
|
||||
{ "a", -1, TrieMiss, nil },
|
||||
};
|
||||
char *v;
|
||||
Trie *trie;
|
||||
int n;
|
||||
int i, match, n;
|
||||
|
||||
trie = trieopen("data/trie.map");
|
||||
v = trieget(trie, "a", 1, &n);
|
||||
if(!CT_CHECK(t, v != nil))
|
||||
goto cleanup;
|
||||
CT_EQ_INT(t, 5, n);
|
||||
CT_EQ_MEM(t, "alpha", v, n);
|
||||
sentinel = "unchanged";
|
||||
v = sentinel;
|
||||
n = 77;
|
||||
CT_CHECK(t, trielookup(trie, "dupli", 5, &v, &n));
|
||||
CT_EQ_PTR(t, sentinel, v);
|
||||
CT_EQ_INT(t, 77, n);
|
||||
v = trieget(trie, "duplicate", 9, &n);
|
||||
if(!CT_CHECK(t, v != nil))
|
||||
goto cleanup;
|
||||
CT_EQ_INT(t, 6, n);
|
||||
CT_EQ_MEM(t, "second", v, n);
|
||||
CT_EQ_PTR(t, nil, trieget(trie, "missing", 7, &n));
|
||||
cleanup:
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
v = "unchanged";
|
||||
n = 77;
|
||||
match = trielookup(trie, cases[i].key, cases[i].klen, &v, &n);
|
||||
if(match != cases[i].match){
|
||||
CT_ERRORF(t, "case %d: want match %d, got %d",
|
||||
i, cases[i].match, match);
|
||||
continue;
|
||||
}
|
||||
if(cases[i].want == nil){
|
||||
CT_EQ_PTR(t, nil, v);
|
||||
CT_EQ_INT(t, 0, n);
|
||||
}else{
|
||||
CT_EQ_INT(t, strlen(cases[i].want), n);
|
||||
CT_EQ_MEM(t, cases[i].want, v, n);
|
||||
}
|
||||
}
|
||||
trieclose(trie);
|
||||
}
|
||||
|
||||
@@ -37,18 +49,15 @@ trie_optional_outputs_and_invalid_lengths(struct ct *t)
|
||||
int n;
|
||||
|
||||
trie = trieopen("data/trie.map");
|
||||
CT_CHECK(t, trieget(trie, "a", 1, nil) != nil);
|
||||
v = nil;
|
||||
CT_CHECK(t, trielookup(trie, "a", 1, &v, nil));
|
||||
CT_EQ_INT(t, TrieExact, trielookup(trie, "a", 1, &v, nil));
|
||||
CT_CHECK(t, v != nil);
|
||||
n = -1;
|
||||
CT_CHECK(t, trielookup(trie, "a", 1, nil, &n));
|
||||
CT_EQ_INT(t, TrieExact, trielookup(trie, "a", 1, nil, &n));
|
||||
CT_EQ_INT(t, 5, n);
|
||||
CT_CHECK(t, trielookup(trie, "dupli", 5, nil, nil));
|
||||
CT_EQ_PTR(t, nil, trieget(trie, nil, 1, &n));
|
||||
CT_EQ_PTR(t, nil, trieget(trie, "a", -1, &n));
|
||||
CT_CHECK(t, !trielookup(trie, nil, 1, &v, &n));
|
||||
CT_CHECK(t, !trielookup(trie, "a", -1, &v, &n));
|
||||
CT_EQ_INT(t, TriePrefix,
|
||||
trielookup(trie, "dupli", 5, nil, nil));
|
||||
CT_EQ_INT(t, TriePrefix, trielookup(trie, nil, 0, &v, &n));
|
||||
CT_EQ_PTR(t, nil, v);
|
||||
CT_EQ_INT(t, 0, n);
|
||||
trieclose(trie);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user