do proper early abort in the other scan_* routines if the numeric value
is too large
This commit is contained in:
parent
35942878c2
commit
01ffc04006
@ -1,8 +1,14 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
size_t scan_8int(const char* src,unsigned int* dest) {
|
size_t scan_8int(const char* src,unsigned int* dest) {
|
||||||
unsigned long l;
|
register const char *tmp=src;
|
||||||
size_t len=scan_8long(src,&l);
|
register unsigned int l=0;
|
||||||
|
register unsigned char c;
|
||||||
|
while ((c=*tmp-'0')<8) {
|
||||||
|
if (l>>(sizeof(l)*8-3)) break;
|
||||||
|
l=l*8+c;
|
||||||
|
++tmp;
|
||||||
|
}
|
||||||
*dest=l;
|
*dest=l;
|
||||||
return len;
|
return tmp-src;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ size_t scan_8longn(const char *src,size_t n,unsigned long *dest) {
|
|||||||
register unsigned long l=0;
|
register unsigned long l=0;
|
||||||
register unsigned char c;
|
register unsigned char c;
|
||||||
while (n-->0 && (c=*tmp-'0')<8) {
|
while (n-->0 && (c=*tmp-'0')<8) {
|
||||||
|
if (l>>(sizeof(l)*8-3)) break;
|
||||||
l=l*8+c;
|
l=l*8+c;
|
||||||
++tmp;
|
++tmp;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
size_t scan_8short(const char* src,unsigned short* dest) {
|
size_t scan_8short(const char* src,unsigned short* dest) {
|
||||||
unsigned long l;
|
register const char *tmp=src;
|
||||||
size_t len=scan_8long(src,&l);
|
register unsigned short l=0;
|
||||||
|
register unsigned char c;
|
||||||
|
while ((c=*tmp-'0')<8) {
|
||||||
|
if (l>>(sizeof(l)*8-3)) break;
|
||||||
|
l=l*8+c;
|
||||||
|
++tmp;
|
||||||
|
}
|
||||||
*dest=l;
|
*dest=l;
|
||||||
return len;
|
return tmp-src;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,38 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
|
static const unsigned int maxint = ((unsigned int)-1)>>1;
|
||||||
|
|
||||||
size_t scan_int(const char* src,int* dest) {
|
size_t scan_int(const char* src,int* dest) {
|
||||||
long l;
|
register const char *tmp;
|
||||||
size_t len=scan_long(src,&l);
|
register int l;
|
||||||
if (len) *dest=l;
|
register unsigned char c;
|
||||||
return len;
|
int neg;
|
||||||
|
int ok;
|
||||||
|
tmp=src; l=0; ok=neg=0;
|
||||||
|
switch (*tmp) {
|
||||||
|
case '-': neg=1;
|
||||||
|
case '+': ++tmp;
|
||||||
|
}
|
||||||
|
while ((c=(unsigned char)(*tmp-'0'))<10) {
|
||||||
|
unsigned long int n;
|
||||||
|
/* we want to do: l=l*10+c
|
||||||
|
* but we need to check for integer overflow.
|
||||||
|
* to check whether l*10 overflows, we could do
|
||||||
|
* if ((l*10)/10 != l)
|
||||||
|
* however, multiplication and division are expensive.
|
||||||
|
* so instead of *10 we do (l<<3) (i.e. *8) + (l<<1) (i.e. *2)
|
||||||
|
* and check for overflow on all the intermediate steps */
|
||||||
|
n=(unsigned int)l<<3; if ((n>>3)!=(unsigned int)l) break;
|
||||||
|
if (n+(l<<1) < n) break;
|
||||||
|
n+=l<<1;
|
||||||
|
if (n+c < n) break;
|
||||||
|
n+=c;
|
||||||
|
if (n > maxint+neg) break;
|
||||||
|
l=n;
|
||||||
|
++tmp;
|
||||||
|
ok=1;
|
||||||
|
}
|
||||||
|
if (!ok) return 0;
|
||||||
|
*dest=(neg?-l:l);
|
||||||
|
return (size_t)(tmp-src);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
|
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 n,long *dest) {
|
||||||
register const char *tmp;
|
register const char *tmp;
|
||||||
register long int l;
|
register long int l;
|
||||||
@ -12,12 +14,26 @@ size_t scan_longn(const char *src,size_t n,long *dest) {
|
|||||||
case '-': neg=1;
|
case '-': neg=1;
|
||||||
case '+': ++tmp;
|
case '+': ++tmp;
|
||||||
}
|
}
|
||||||
while (n-->0 && (c=*tmp-'0')<10) {
|
while (n-->0 && (c=(unsigned char)(*tmp-'0'))<10) {
|
||||||
l=l*10+c;
|
unsigned long int n;
|
||||||
|
/* we want to do: l=l*10+c
|
||||||
|
* but we need to check for integer overflow.
|
||||||
|
* to check whether l*10 overflows, we could do
|
||||||
|
* if ((l*10)/10 != l)
|
||||||
|
* however, multiplication and division are expensive.
|
||||||
|
* so instead of *10 we do (l<<3) (i.e. *8) + (l<<1) (i.e. *2)
|
||||||
|
* and check for overflow on all the intermediate steps */
|
||||||
|
n=(unsigned long)l<<3; if ((n>>3)!=(unsigned long)l) break;
|
||||||
|
if (n+(l<<1) < n) break;
|
||||||
|
n+=l<<1;
|
||||||
|
if (n+c < n) break;
|
||||||
|
n+=c;
|
||||||
|
if (n > maxlong+neg) break;
|
||||||
|
l=n;
|
||||||
++tmp;
|
++tmp;
|
||||||
ok=1;
|
ok=1;
|
||||||
}
|
}
|
||||||
if (!ok) return 0;
|
if (!ok) return 0;
|
||||||
*dest=(neg?-l:l);
|
*dest=(neg?-l:l);
|
||||||
return tmp-src;
|
return (size_t)(tmp-src);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,38 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
|
static const unsigned int maxshort = ((unsigned short)-1)>>1;
|
||||||
|
|
||||||
size_t scan_short(const char* src,short* dest) {
|
size_t scan_short(const char* src,short* dest) {
|
||||||
long l;
|
register const char *tmp;
|
||||||
size_t len=scan_long(src,&l);
|
register short l;
|
||||||
*dest=l;
|
register unsigned char c;
|
||||||
return len;
|
int neg;
|
||||||
|
int ok;
|
||||||
|
tmp=src; l=0; ok=neg=0;
|
||||||
|
switch (*tmp) {
|
||||||
|
case '-': neg=1;
|
||||||
|
case '+': ++tmp;
|
||||||
|
}
|
||||||
|
while ((c=(unsigned char)(*tmp-'0'))<10) {
|
||||||
|
unsigned long int n;
|
||||||
|
/* we want to do: l=l*10+c
|
||||||
|
* but we need to check for integer overflow.
|
||||||
|
* to check whether l*10 overflows, we could do
|
||||||
|
* if ((l*10)/10 != l)
|
||||||
|
* however, multiplication and division are expensive.
|
||||||
|
* so instead of *10 we do (l<<3) (i.e. *8) + (l<<1) (i.e. *2)
|
||||||
|
* and check for overflow on all the intermediate steps */
|
||||||
|
n=(unsigned int)l<<3; if ((n>>3)!=(unsigned int)l) break;
|
||||||
|
if (n+(l<<1) < n) break;
|
||||||
|
n+=l<<1;
|
||||||
|
if (n+c < n) break;
|
||||||
|
n+=c;
|
||||||
|
if (n > maxshort+neg) break;
|
||||||
|
l=n;
|
||||||
|
++tmp;
|
||||||
|
ok=1;
|
||||||
|
}
|
||||||
|
if (!ok) return 0;
|
||||||
|
*dest=(neg?-l:l);
|
||||||
|
return (size_t)(tmp-src);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ size_t scan_ushort(const char* src,unsigned short* dest) {
|
|||||||
n=l<<3; if ((n>>3)!=l) break;
|
n=l<<3; if ((n>>3)!=l) break;
|
||||||
if (n+(l<<1) < n) break;
|
if (n+(l<<1) < n) break;
|
||||||
n+=l<<1;
|
n+=l<<1;
|
||||||
if (n+c < n) break;
|
if ((unsigned short)(n+c) < n) break;
|
||||||
l=n+c;
|
l=n+c;
|
||||||
++tmp;
|
++tmp;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
size_t scan_xint(const char* src,unsigned int* dest) {
|
size_t scan_xint(const char* src,unsigned int* dest) {
|
||||||
unsigned long l;
|
register const char *tmp=src;
|
||||||
register int len=scan_xlong(src,&l);
|
register unsigned int l=0;
|
||||||
|
register unsigned char c;
|
||||||
|
while ((l>>(sizeof(l)*8-4))==0 && (c=scan_fromhex(*tmp))<16) {
|
||||||
|
l=(l<<4)+c;
|
||||||
|
++tmp;
|
||||||
|
}
|
||||||
*dest=l;
|
*dest=l;
|
||||||
return len;
|
return tmp-src;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ size_t scan_xlongn(const char *src,size_t n,unsigned long *dest) {
|
|||||||
register const char *tmp=src;
|
register const char *tmp=src;
|
||||||
register unsigned long l=0;
|
register unsigned long l=0;
|
||||||
register unsigned char c;
|
register unsigned char c;
|
||||||
while (n-->0 && (c=scan_fromhex(*tmp))<16) {
|
while (n-->0 && (l>>(sizeof(l)*8-4))==0 && (c=scan_fromhex(*tmp))<16) {
|
||||||
l=(l<<4)+c;
|
l=(l<<4)+c;
|
||||||
++tmp;
|
++tmp;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
size_t scan_xshort(const char* src,unsigned short* dest) {
|
size_t scan_xshort(const char* src,unsigned short* dest) {
|
||||||
unsigned long l;
|
register const char *tmp=src;
|
||||||
size_t len=scan_xlong(src,&l);
|
register unsigned short l=0;
|
||||||
|
register unsigned char c;
|
||||||
|
while ((l>>(sizeof(l)*8-4))==0 && (c=scan_fromhex(*tmp))<16) {
|
||||||
|
l=(l<<4)+c;
|
||||||
|
++tmp;
|
||||||
|
}
|
||||||
*dest=l;
|
*dest=l;
|
||||||
return len;
|
return tmp-src;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,17 @@ void zap() { size_t i; for (i=0; i<sizeof(buf); ++i) buf[i]='_'; }
|
|||||||
int main() {
|
int main() {
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
|
|
||||||
|
unsigned long long ull;
|
||||||
|
unsigned long ul;
|
||||||
|
unsigned int ui;
|
||||||
|
unsigned short us;
|
||||||
|
unsigned char uc;
|
||||||
|
signed long long ll;
|
||||||
|
signed long l;
|
||||||
|
signed int i;
|
||||||
|
signed short s;
|
||||||
|
signed char c;
|
||||||
|
|
||||||
// check utf8 encoding
|
// check utf8 encoding
|
||||||
zap(); assert(fmt_utf8(NULL,12345) == 3);
|
zap(); assert(fmt_utf8(NULL,12345) == 3);
|
||||||
zap(); assert(fmt_utf8(buf,12345) == 3 && byte_equal(buf,4,"\xe3\x80\xb9_"));
|
zap(); assert(fmt_utf8(buf,12345) == 3 && byte_equal(buf,4,"\xe3\x80\xb9_"));
|
||||||
@ -128,4 +139,71 @@ int main() {
|
|||||||
assert(fmt_escapecharquotedprintableutf8(NULL,0xf6)==6); // =c3=b6
|
assert(fmt_escapecharquotedprintableutf8(NULL,0xf6)==6); // =c3=b6
|
||||||
zap(); assert(fmt_escapecharquotedprintableutf8(buf,0xf6)==6 && byte_equal(buf,7,"=c3=b6_"));
|
zap(); assert(fmt_escapecharquotedprintableutf8(buf,0xf6)==6 && byte_equal(buf,7,"=c3=b6_"));
|
||||||
|
|
||||||
|
assert(scan_ulong("23",&ul)==2 && ul==23);
|
||||||
|
assert(scan_ulong("46halbe",&ul)==2 && ul==46);
|
||||||
|
if (sizeof(ul)==4) {
|
||||||
|
assert(scan_ulong("4294967295",&ul)==10 && ul==0xffffffff);
|
||||||
|
assert(scan_ulong("4294967296",&ul)==9 && ul==429496729);
|
||||||
|
assert(scan_xlong("ffffffff",&ul)==8 && ul==0xffffffff);
|
||||||
|
assert(scan_xlong("ffffffff0",&ul)==8 && ul==0xffffffff);
|
||||||
|
assert(scan_8long("37777777777",&ul)==11 && ul==0xffffffff);
|
||||||
|
assert(scan_8long("377777777771",&ul)==11 && ul==0xffffffff);
|
||||||
|
|
||||||
|
assert(scan_long("2147483647",&l)==10 && l==0x7fffffff);
|
||||||
|
assert(scan_long("02147483647",&l)==11 && l==0x7fffffff);
|
||||||
|
assert(scan_long("021474836470",&l)==11 && l==0x7fffffff);
|
||||||
|
assert(scan_long("+2147483647",&l)==11 && l==0x7fffffff);
|
||||||
|
assert(scan_long("+2147483648",&l)==10 && l==214748364);
|
||||||
|
assert(scan_long("-2147483647",&l)==11 && l==-2147483647);
|
||||||
|
assert(scan_long("-2147483648",&l)==11 && l==-2147483648);
|
||||||
|
assert(scan_long("-2147483649",&l)==10 && l==-214748364);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
assert(scan_ulong("18446744073709551615",&ul)==20 && ul==0xffffffffffffffffull);
|
||||||
|
assert(scan_ulong("18446744073709551616",&ul)==19 && ul==1844674407370955161ull);
|
||||||
|
assert(scan_xlong("ffffffffffffffff",&ul)==16 && ul==0xffffffffffffffffull);
|
||||||
|
assert(scan_xlong("ffffffffffffffff0",&ul)==16 && ul==0xffffffffffffffffull);
|
||||||
|
assert(scan_8long("1777777777777777777777",&ul)==22 && ul==0xffffffffffffffffull);
|
||||||
|
assert(scan_8long("17777777777777777777770",&ul)==22 && ul==0xffffffffffffffffull);
|
||||||
|
|
||||||
|
assert(scan_long("9223372036854775807",&l)==19 && l==0x7fffffffffffffffll);
|
||||||
|
assert(scan_long("09223372036854775807",&l)==20 && l==0x7fffffffffffffffll);
|
||||||
|
assert(scan_long("092233720368547758070",&l)==20 && l==0x7fffffffffffffffll);
|
||||||
|
assert(scan_long("+9223372036854775807",&l)==20 && l==0x7fffffffffffffffll);
|
||||||
|
assert(scan_long("+9223372036854775808",&l)==19 && l==922337203685477580ll);
|
||||||
|
assert(scan_long("-9223372036854775807",&l)==20 && l==-9223372036854775807ll);
|
||||||
|
x=scan_long("-9223372036854775808",&l);
|
||||||
|
assert(scan_long("-9223372036854775808",&l)==20 && l==0x8000000000000000);
|
||||||
|
assert(scan_long("-9223372036854775809",&l)==19 && l==-922337203685477580ll);
|
||||||
|
|
||||||
|
}
|
||||||
|
assert(scan_uint("4294967295",&ui)==10 && ui==0xffffffff);
|
||||||
|
assert(scan_uint("4294967296",&ui)==9 && ui==429496729);
|
||||||
|
assert(scan_ushort("65535",&us)==5 && us==0xffff);
|
||||||
|
assert(scan_ushort("65536",&us)==4 && us==6553);
|
||||||
|
|
||||||
|
assert(scan_xint("0ffffffff",&ui)==9 && ui==0xffffffff);
|
||||||
|
assert(scan_xint("ffffffff0",&ui)==8 && ui==0xffffffff);
|
||||||
|
assert(scan_xshort("0ffff",&us)==5 && us==0xffff);
|
||||||
|
assert(scan_xshort("ffff1",&us)==4 && us==0xffff);
|
||||||
|
|
||||||
|
assert(scan_8int("037777777777",&ui)==12 && ui==0xffffffff);
|
||||||
|
assert(scan_8int("377777777771",&ui)==11 && ui==0xffffffff);
|
||||||
|
assert(scan_8short("00177777",&us)==8 && us==0xffff);
|
||||||
|
assert(scan_8short("1777771",&us)==6 && us==0xffff);
|
||||||
|
|
||||||
|
assert(scan_int("2147483647",&i)==10 && i==0x7fffffff);
|
||||||
|
assert(scan_int("02147483647",&i)==11 && i==0x7fffffff);
|
||||||
|
assert(scan_int("021474836470",&i)==11 && i==0x7fffffff);
|
||||||
|
assert(scan_int("+2147483647",&i)==11 && i==0x7fffffff);
|
||||||
|
assert(scan_int("+2147483648",&i)==10 && i==214748364);
|
||||||
|
assert(scan_int("-2147483647",&i)==11 && i==-2147483647);
|
||||||
|
assert(scan_int("-2147483648",&i)==11 && i==-2147483648);
|
||||||
|
assert(scan_int("-2147483649",&i)==10 && i==-214748364);
|
||||||
|
|
||||||
|
assert(scan_short("32767",&s)==5 && s==32767);
|
||||||
|
assert(scan_short("32768",&s)==4 && s==3276);
|
||||||
|
assert(scan_short("+032767",&s)==7 && s==32767);
|
||||||
|
assert(scan_short("-32768",&s)==6 && s==-32768);
|
||||||
|
assert(scan_short("-032769",&s)==6 && s==-3276);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user