ref: 99e2d549e86cbdf4c364a476b8eb008c8fcff6ec
parent: e8242918f4073dfff640da6b4a01287664ccb9f0
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Nov 25 14:08:21 EST 2023
libndb: do some extra robustness checks around hash files - make sure the hash-file has non-zero hlen field (avoid division by zero) - bound the chain walking by hlen, so we wont end up in a infinite loop - always check for NDBNAP (nil) pointer while walking chain - verify chain pointers (must be multiple of NDBPLEN and not overlap hashtable)
--- a/sys/src/libndb/ndbhash.c
+++ b/sys/src/libndb/ndbhash.c
@@ -29,13 +29,13 @@
* read a hash file with buffering
*/
static uchar*
-hfread(Ndbhf *hf, long off, int len)
+hfread(Ndbhf *hf, ulong off, int len)
{
if(off < hf->off || off + len > hf->off + hf->len){
- if(seek(hf->fd, off, 0) < 0
- || (hf->len = read(hf->fd, hf->buf, sizeof(hf->buf))) < len){
- hf->off = -1;
- return 0;
+ if((hf->len = pread(hf->fd, hf->buf, sizeof(hf->buf), off)) < len){
+ hf->off = 0;
+ hf->len = 0;
+ return nil;
}
hf->off = off;
}
@@ -95,7 +95,7 @@
if(p != nil){
hf->dbmtime = NDBGETUL(p);
hf->hlen = NDBGETUL(p+NDBULLEN);
- if(hf->dbmtime == db->mtime){
+ if(hf->hlen > 0 && hf->dbmtime == db->mtime){
hf->next = db->hf;
db->hf = hf;
return hf;
@@ -174,12 +174,11 @@
Ndbtuple *t;
Ndb *db;
uchar *p;
+ ulong nchain;
+ nchain = 0;
db = s->db;
- if(s->ptr == NDBNAP)
- goto nextfile;
-
- for(;;){
+ for(;;) {
if(s->type == Dptr){
if(Bseek(&db->b, s->ptr, 0) < 0)
break;
@@ -203,7 +202,18 @@
ndbfree(t);
} else if(s->type == Cptr1){
if(s->ptr & NDBCHAIN){ /* hash chain continuation */
+ if(s->ptr == NDBNAP)
+ break;
+ /* chain in a loop? */
+ if(++nchain > s->hf->hlen)
+ break;
s->ptr &= ~NDBCHAIN;
+ /* must be multiple of NDBPLEN */
+ if(s->ptr % NDBPLEN)
+ break;
+ /* must not overlap hash table */
+ if(s->ptr / NDBPLEN < s->hf->hlen)
+ break;
p = hfread(s->hf, s->ptr+NDBHLEN, 2*NDBPLEN);
if(p == nil)
break;
@@ -222,10 +232,12 @@
ndbfree(t);
break;
}
+ } else {
+ /* shouldnt happen */
+ break;
}
}
-nextfile:
/* nothing left to search? */
s->ptr = NDBNAP;
if(db->next == nil)
--- a/sys/src/libndb/ndbhf.h
+++ b/sys/src/libndb/ndbhf.h
@@ -9,7 +9,7 @@
char attr[Ndbalen]; /* attribute hashed */
uchar buf[256]; /* hash file buffer */
- long off; /* offset of first byte of buffer */
+ ulong off; /* offset of first byte of buffer */
int len; /* length of valid data in buffer */
};