fix(data): reject partial and malformed map data
This commit is contained in:
31
hash.c
31
hash.c
@@ -1,3 +1,4 @@
|
||||
#include <limits.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
@@ -27,7 +28,9 @@ hmapalloc(int nbuckets)
|
||||
if(nbuckets < 1)
|
||||
return nil;
|
||||
nsz = Tagsize;
|
||||
store = emalloc(sizeof(*h) + nbuckets * nsz);
|
||||
if((ulong)nbuckets > (ULONG_MAX-sizeof(*h))/(ulong)nsz)
|
||||
return nil;
|
||||
store = emalloc(sizeof(*h) + (ulong)nbuckets * nsz);
|
||||
h = store;
|
||||
h->nbs = nbuckets;
|
||||
h->nsz = nsz;
|
||||
@@ -56,14 +59,14 @@ hmapget(Hmap *h, Str *key)
|
||||
|
||||
if(h == nil || key == nil || key->n < 0 || key->n > Maxrunes)
|
||||
return nil;
|
||||
v = h->nodes + (hash(key) % h->nbs) * h->nsz;
|
||||
v = h->nodes + (hash(key) % h->nbs) * (ulong)h->nsz;
|
||||
for(;;){
|
||||
n = (Hnode*)v;
|
||||
if(n->filled && keycmp(n, key) == 0)
|
||||
return n;
|
||||
if(n->next == 0)
|
||||
break;
|
||||
v = h->nodes + n->next * h->nsz;
|
||||
v = h->nodes + (ulong)n->next * h->nsz;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@@ -76,7 +79,7 @@ sdup(Str *s, int *len)
|
||||
int n;
|
||||
|
||||
n = stoutf(s, buf, sizeof(buf));
|
||||
p = emalloc(n + 1);
|
||||
p = emalloc((ulong)n + 1);
|
||||
memmove(p, buf, n);
|
||||
p[n] = '\0';
|
||||
*len = n;
|
||||
@@ -90,7 +93,7 @@ memdup(const char *src, int n)
|
||||
|
||||
if(n == 0)
|
||||
return nil;
|
||||
p = emalloc(n + 1);
|
||||
p = emalloc((ulong)n + 1);
|
||||
memmove(p, src, n);
|
||||
p[n] = '\0';
|
||||
return p;
|
||||
@@ -105,7 +108,7 @@ hmapfree(Hmap *h)
|
||||
if(h == nil)
|
||||
return;
|
||||
for(i = 0; i < h->len; i++){
|
||||
n = (Hnode*)(h->nodes + i * h->nsz);
|
||||
n = (Hnode*)(h->nodes + (ulong)i * h->nsz);
|
||||
if(!n->filled)
|
||||
continue;
|
||||
free(n->key);
|
||||
@@ -122,7 +125,7 @@ hmapset(Hmap **store, Str *key, const char *val, int vlen)
|
||||
uchar *v;
|
||||
Hmap *h;
|
||||
int next;
|
||||
vlong diff;
|
||||
ulong diff;
|
||||
|
||||
if(store == nil || *store == nil || key == nil ||
|
||||
key->n < 0 || key->n > Maxrunes || vlen < 0 ||
|
||||
@@ -130,7 +133,7 @@ hmapset(Hmap **store, Str *key, const char *val, int vlen)
|
||||
return;
|
||||
newval = memdup(val, vlen);
|
||||
h = *store;
|
||||
v = h->nodes + (hash(key) % h->nbs) * h->nsz;
|
||||
v = h->nodes + (hash(key) % h->nbs) * (ulong)h->nsz;
|
||||
for(;;){
|
||||
n = (Hnode*)v;
|
||||
next = n->next;
|
||||
@@ -140,21 +143,25 @@ hmapset(Hmap **store, Str *key, const char *val, int vlen)
|
||||
goto replace;
|
||||
if(next == 0)
|
||||
break;
|
||||
v = h->nodes + next * h->nsz;
|
||||
v = h->nodes + (ulong)next * h->nsz;
|
||||
}
|
||||
if(h->cap == h->len){
|
||||
diff = v - h->nodes;
|
||||
if(h->cap > INT_MAX/2 ||
|
||||
(ulong)h->cap > (ULONG_MAX-sizeof(*h))/(2*(ulong)h->nsz))
|
||||
die("hash table is too large");
|
||||
h->cap *= 2;
|
||||
*store = erealloc(*store, sizeof(*h) + h->cap * h->nsz);
|
||||
*store = erealloc(*store,
|
||||
sizeof(*h) + (ulong)h->cap * h->nsz);
|
||||
h = *store;
|
||||
h->nodes = (uchar*)*store + sizeof(*h);
|
||||
v = h->nodes + diff;
|
||||
n = (Hnode*)v;
|
||||
}
|
||||
n->next = h->len;
|
||||
memset(h->nodes + h->len * h->nsz, 0, h->nsz);
|
||||
memset(h->nodes + (ulong)h->len * h->nsz, 0, h->nsz);
|
||||
h->len++;
|
||||
v = h->nodes + n->next * h->nsz;
|
||||
v = h->nodes + (ulong)n->next * h->nsz;
|
||||
n = (Hnode*)v;
|
||||
replace:
|
||||
if(n->filled == 0){
|
||||
|
||||
Reference in New Issue
Block a user