diff --git a/CHANGES b/CHANGES index c1b840b..9245259 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ add cross references to open_* and mmap_* man pages add fmt_strm_alloca and fmt_strm_malloc man pages add buffer_init_allocbuf, buffer_init_read, buffer_init_write, buffer_init_read_allocbuf, buffer_init_write_allocbuf + fix buffer overread for len=0 in scan_longn (Martin Castillo) 0.32: remove OpenBSD #warning (obsd maintainer says no longer needed) diff --git a/scan/scan_long.c b/scan/scan_long.c index 0a7a7a8..a81b72e 100644 --- a/scan/scan_long.c +++ b/scan/scan_long.c @@ -28,6 +28,13 @@ int main() { assert(scan_long("9223372036854775807",&i)==19 && i==0x7fffffffffffffffull); // LONG_MAX assert(scan_long("-9223372036854775808",&i)==20 && i==(long long)0x8000000000000000ull); // LONG_MIN } + i=42; + assert(scan_longn("7",0,&i)==0 && i==42); + assert(scan_longn("-7",1,&i)==0 && i==42); + assert(scan_longn("+7",1,&i)==0 && i==42); + assert(scan_longn("7",1,&i)==1 && i==7); + assert(scan_longn("-7",2,&i)==2 && i==-7); + assert(scan_longn("+7",2,&i)==2 && i==7); return 0; } #endif diff --git a/scan/scan_longn.c b/scan/scan_longn.c index f09ac40..bc00c0d 100644 --- a/scan/scan_longn.c +++ b/scan/scan_longn.c @@ -2,19 +2,19 @@ static const unsigned long maxlong = ((unsigned long)-1)>>1; -size_t scan_longn(const char *src,size_t n,long *dest) { +size_t scan_longn(const char *src,size_t len,long *dest) { register const char *tmp; register long int l; register unsigned char c; unsigned int neg; int ok; - if (!n--) return 0; + if (!len) return 0; tmp=src; l=0; ok=0; neg=0; switch (*tmp) { case '-': neg=1; /* fall through */ - case '+': ++tmp; + case '+': ++tmp; --len; } - while (n-->0 && (c=(unsigned char)(*tmp-'0'))<10) { + while (len-->0 && (c=(unsigned char)(*tmp-'0'))<10) { unsigned long int n; #if defined(__GNUC__) && (__GNUC__ >= 5) if (__builtin_mul_overflow(l,10,&n) || __builtin_add_overflow(n,c,&n))