add rangecheck.h

master
leitner 19 years ago
parent 8ccd1cdd5f
commit dbd9fe1ea5

@ -10,6 +10,7 @@
implement Nikola's idea to remove limit number of strings in errmsg implement Nikola's idea to remove limit number of strings in errmsg
add taia_half add taia_half
add cdb add cdb
add rangecheck.h
0.24: 0.24:
fix scan_to_sa (Tim Lorenz) fix scan_to_sa (Tim Lorenz)

@ -585,7 +585,7 @@ dep libsocket havealloca.h
INCLUDES=buffer.h byte.h fmt.h ip4.h ip6.h mmap.h scan.h socket.h str.h stralloc.h \ INCLUDES=buffer.h byte.h fmt.h ip4.h ip6.h mmap.h scan.h socket.h str.h stralloc.h \
uint16.h uint32.h uint64.h open.h textcode.h tai.h taia.h dns.h iopause.h case.h \ uint16.h uint32.h uint64.h open.h textcode.h tai.h taia.h dns.h iopause.h case.h \
openreadclose.h readclose.h ndelay.h array.h io.h safemult.h iob.h havealloca.h \ openreadclose.h readclose.h ndelay.h array.h io.h safemult.h iob.h havealloca.h \
errmsg.h cdb.h cdb_make.h errmsg.h cdb.h cdb_make.h rangecheck.h
install: libowfat.a install: libowfat.a
install -d $(INCLUDEDIR) $(MAN3DIR) $(LIBDIR) install -d $(INCLUDEDIR) $(MAN3DIR) $(LIBDIR)

@ -0,0 +1,20 @@
#include <rangecheck.h>
#include <safemult.h>
/* does an array of "elements" members of size "membersize" starting at
* "arraystart" lie inside buf1[0..len-1]? */
int range_arrayinbuf(const void* buf1,size_t len,
const void* arraystart,size_t elements,size_t membersize) {
size_t alen;
if (sizeof(alen)==8) {
uint64 x;
if (!umult64(elements,membersize,&x)) return 0;
alen=x;
} else {
unsigned long long t=(unsigned long long)elements*membersize;
alen=t;
if (alen!=t) return 0;
}
return range_bufinbuf(buf1,len,arraystart,alen);
}

@ -0,0 +1,13 @@
#include <rangecheck.h>
#include <inttypes.h>
/* does an UTF-16 string starting at "ptr" lie in buf[0..len-1]? */
int range_str2inbuf(const void* buf,size_t len,const void* stringstart) {
const uint16_t* x;
const uint16_t* y;
if (!range_ptrinbuf(buf,len,x=stringstart)) return 0;
y=(const uint16_t*)((char*)x+len);
for (; x+1<=y && *x; ++x);
return (x+1<=y);
}

@ -0,0 +1,13 @@
#include <rangecheck.h>
#include <inttypes.h>
/* does an UTF-32 string starting at "ptr" lie in buf[0..len-1]? */
int range_str4inbuf(const void* buf,size_t len,const void* stringstart) {
const uint32_t* x;
const uint32_t* y;
if (!range_ptrinbuf(buf,len,x=stringstart)) return 0;
y=(const uint32_t*)((char*)x+len);
for (; x+1<=y && *x; ++x);
return (x+1<=y);
}

@ -0,0 +1,12 @@
#include <rangecheck.h>
/* does an ASCIIZ string starting at "ptr" lie in buf[0..len-1]? */
int range_strinbuf(const void* buf,size_t len,const void* stringstart) {
const char* x;
const char* y;
if (!range_ptrinbuf(buf,len,x=stringstart)) return 0;
y=x+len;
for (; x<y && *x; ++x);
return (x<y);
}

@ -0,0 +1,65 @@
#ifndef RANGECHECK_H
#define RANGECHECK_H
#include <stddef.h>
/* return 0 for range error / overflow, 1 for ok */
#if defined(__GNUC__) && defined(__OPTIMIZE__)
#define __static extern
#else
#define __static static
#endif
/* does ptr point to one of buf[0], buf[1], ... buf[len-1]? */
__static inline int range_ptrinbuf(const void* buf,size_t len,const void* ptr) {
register const char* c=(const char*)buf; /* no pointer arithmetic on void* */
return (c && /* is buf non-NULL? */
#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 1)
((size_t)c)+len>(size_t)c && /* gcc 4.1 miscompiles this test */
#else
c+len>c && /* catch integer overflows and fail if buffer is 0 bytes long */
/* because then ptr can't point _in_ the buffer */
#endif
(size_t)((const char*)ptr-c)<len); /* this one is a little tricky.
"ptr-c" checks the offset of ptr in the buffer is inside the buffer size.
Now, ptr-c can underflow; say it is -1. When we cast it to size_t, it becomes
a very large number. */
}
/* Is this a plausible buffer?
* Check whether buf is NULL, and whether buf+len overflows.
* Does NOT check whether buf has a non-zero length! */
__static inline int range_validbuf(const void* buf,size_t len) {
#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 1)
return (buf && (size_t)buf+len>=(size_t)buf); /* gcc 4.1 miscompiles this test */
#else
return (buf && (const char*)buf+len>=(const char*)buf);
#endif
}
/* is buf2[0..len2-1] inside buf1[0..len-1]? */
__static inline int range_bufinbuf(const void* buf1,size_t len1,const void* buf2,size_t len2) {
return range_validbuf(buf1,len1) &&
range_validbuf(buf2,len2) &&
buf1<=buf2 &&
(ptrdiff_t)buf1+len1>=(ptrdiff_t)buf2+len2;
}
/* does an array of "elements" members of size "membersize" starting at
* "arraystart" lie inside buf1[0..len-1]? */
int range_arrayinbuf(const void* buf1,size_t len,
const void* arraystart,size_t elements,size_t membersize);
/* does an ASCIIZ string starting at "ptr" lie in buf[0..len-1]? */
int range_strinbuf(const void* buf,size_t len,const void* stringstart);
/* does an UTF-16 string starting at "ptr" lie in buf[0..len-1]? */
int range_str2inbuf(const void* buf,size_t len,const void* stringstart);
/* does an UTF-32 string starting at "ptr" lie in buf[0..len-1]? */
int range_str4inbuf(const void* buf,size_t len,const void* stringstart);
#undef __static
#endif

4
t.c

@ -64,7 +64,7 @@ int main(int argc,char* argv[]) {
#if 0 #if 0
buffer_putmflush(buffer_1,"foo ","bar ","baz.\n"); buffer_putmflush(buffer_1,"foo ","bar ","baz.\n");
#endif #endif
#if 1 #if 0
char* c="fnord"; char* c="fnord";
int fd=open_read(c); int fd=open_read(c);
errmsg_iam(argv[0]); errmsg_iam(argv[0]);
@ -318,7 +318,7 @@ int main(int argc,char* argv[]) {
rdtscl(c); rdtscl(c);
printf("%lu %lu\n",b-a,c-b); printf("%lu %lu\n",b-a,c-b);
#endif #endif
#if 0 #if 1
unsigned long size; unsigned long size;
char* buf=mmap_read(argv[1],&size); char* buf=mmap_read(argv[1],&size);
if (buf) { if (buf) {

@ -0,0 +1,90 @@
#include "rangecheck.h"
#include <assert.h>
#include <stdio.h>
int main() {
char buf[1000];
/* does range_ptrinbuf check all the incoming pointer cases right? */
assert(range_ptrinbuf(buf,sizeof(buf),0)==0);
assert(range_ptrinbuf(buf,sizeof(buf),buf-1)==0);
assert(range_ptrinbuf(buf,sizeof(buf),buf)==1);
assert(range_ptrinbuf(buf,sizeof(buf),buf+50)==1);
assert(range_ptrinbuf(buf,sizeof(buf),buf+sizeof(buf))==0);
/* what if we give it an invalid buffer? */
assert(range_ptrinbuf(0,sizeof(buf),0)==0);
assert(range_ptrinbuf(buf,(unsigned long)-1,buf+1)==0);
/* see if range_validbuf works */
assert(range_validbuf(buf,sizeof(buf))==1);
assert(range_validbuf(0,sizeof(buf))==0);
assert(range_validbuf(buf,(unsigned long)-1)==0);
/* range_bufinbuf */
assert(range_bufinbuf(buf,sizeof(buf),buf,sizeof(buf))==1);
assert(range_bufinbuf(buf,sizeof(buf),buf,sizeof(buf)+1)==0);
assert(range_bufinbuf(buf,sizeof(buf),buf-1,sizeof(buf))==0);
assert(range_bufinbuf(buf-1,sizeof(buf)+1,buf,sizeof(buf))==1);
assert(range_bufinbuf(buf-1,sizeof(buf)+2,buf,sizeof(buf))==1);
assert(range_bufinbuf(0,sizeof(buf),(void*)1,1)==0);
assert(range_bufinbuf(buf,(unsigned long)-1,buf,1)==0);
/* the quintessential integer overflow exploit scenario */
assert(range_bufinbuf(buf,sizeof(buf),buf+10,(unsigned long)-5)==0);
assert(range_bufinbuf(buf,sizeof(buf),buf+10,sizeof(buf))==0);
assert(range_bufinbuf(buf,sizeof(buf),buf+10,sizeof(buf)-10)==1);
/* range_arrayinbuf */
assert(range_arrayinbuf(buf,sizeof(buf),buf,1,10)==1);
assert(range_arrayinbuf(buf,sizeof(buf),buf+sizeof(buf)-10,1,10)==1);
assert(range_arrayinbuf(buf,sizeof(buf),buf-1,1,10)==0);
assert(range_arrayinbuf(buf,sizeof(buf),buf+1,1,1000)==0);
assert(range_arrayinbuf(buf,sizeof(buf),buf-1,1,1002)==0);
/* now overflow the array parameters */
assert(range_arrayinbuf(buf,sizeof(buf),buf+10,0x10000,0x10000)==0);
assert(range_arrayinbuf(buf,sizeof(buf),buf+10,0x80000000,2)==0);
assert(range_arrayinbuf(buf,sizeof(buf),buf+10,0xffffffff,1)==0);
/* range_strinbuf */
assert(range_strinbuf(buf,sizeof(buf),0)==0);
assert(range_strinbuf(buf,sizeof(buf),buf+sizeof(buf))==0);
{
char* x="fnord";
assert(range_strinbuf(x,5,x)==0);
assert(range_strinbuf(x,6,x)==1);
assert(range_strinbuf(x,6,x+5)==1);
assert(range_strinbuf(x,6,x+6)==0);
}
/* range_str2inbuf */
assert(range_str2inbuf(buf,sizeof(buf),0)==0);
assert(range_str2inbuf(buf,sizeof(buf),buf+sizeof(buf))==0);
{
uint16_t y[6];
int i;
for (i=0; i<7; ++i) y[i]="fnord"[i];
assert(range_str2inbuf(y,5*2,y)==0);
assert(range_str2inbuf(y,5*2+1,y)==0);
assert(range_str2inbuf(y,sizeof(y),y)==1);
assert(range_str2inbuf(y,sizeof(y),y+5)==1);
assert(range_str2inbuf(y,sizeof(y),y+6)==0);
}
/* range_str4inbuf */
assert(range_str4inbuf(buf,sizeof(buf),0)==0);
assert(range_str4inbuf(buf,sizeof(buf),buf+sizeof(buf))==0);
{
uint32_t y[6];
int i;
for (i=0; i<7; ++i) y[i]="fnord"[i];
assert(range_str4inbuf(y,5*4,y)==0);
assert(range_str4inbuf(y,5*4+3,y)==0);
assert(range_str4inbuf(y,sizeof(y),y)==1);
assert(range_str4inbuf(y,sizeof(y),y+5)==1);
assert(range_str4inbuf(y,sizeof(y),y+6)==0);
}
puts("all tests ok");
return 0;
}
Loading…
Cancel
Save