ref: 57188959af6a3e40787078503c3130436f352007
parent: 952c0dad4de37f337b252818a2060b57e58cbead
	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 */
};
--
⑨