From 18afec7d68117a6f4f6d622fde88135982725881 Mon Sep 17 00:00:00 2001 From: leitner Date: Fri, 14 Mar 2014 01:33:03 +0000 Subject: [PATCH] scan_*longlong now properly abort if the number would not fit --- CHANGES | 5 +++++ scan/scan_8longlong.c | 14 ++++++++++++++ scan/scan_longlong.c | 7 +++++++ scan/scan_xlonglong.c | 2 +- test/marshal.c | 23 +++++++++++++++++++---- 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 scan/scan_8longlong.c diff --git a/CHANGES b/CHANGES index 8e8bbb7..1065a5c 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,11 @@ change buffer to have a destructor function pointer SECURITY: fmt_strn would write one byte too many (returned right length though, so usually not a problem as that byte would be overwritten with \0 by the caller anyway) fmt_pad and fmt_fill fail more gracefully when srclen > maxlen + You can now say $ make WERROR=-Werror (compiling t.c will fail but that's not part of the library) + scan_html now decodes HTML entities based on the actual w3c list (from entities.json, say gmake update to fetch the current version) + added fmt_escapechar* to fmt.h (implement various escaping mechanisms also found in textcode but for a single char not a whole string, and they always escape, not just when they think it's needed) + scan_ushort was supposed to abort early and return 5 when attempting to parse "65536", because the result does not fit. It did not. Now it does. + scan_*long, scan_*int, scan_*short now properly abort if the number would not fit 0.29: save 8 bytes in taia.h for 64-bit systems diff --git a/scan/scan_8longlong.c b/scan/scan_8longlong.c new file mode 100644 index 0000000..e32db8d --- /dev/null +++ b/scan/scan_8longlong.c @@ -0,0 +1,14 @@ +#include "scan.h" + +size_t scan_8longlong(const char *src,unsigned long long *dest) { + register const char *tmp=src; + register unsigned long long 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; + return tmp-src; +} diff --git a/scan/scan_longlong.c b/scan/scan_longlong.c index c089ab3..8aa0537 100644 --- a/scan/scan_longlong.c +++ b/scan/scan_longlong.c @@ -1,11 +1,18 @@ #include "scan.h" +static const unsigned long maxlong = ((unsigned long)-1)>>1; + size_t scan_longlong(const char* src,signed long long* dest) { unsigned int i,o; unsigned long long l; char c=src[0]; + int neg=c=='-'; o=c=='-' || c=='+'; if ((i=scan_ulonglong(src+o,&l))) { + if (i>0 && l>maxlong+neg) { + l/=10; + --i; + } if (i+o) *dest=c=='-'?-l:l; return i+o; } return 0; diff --git a/scan/scan_xlonglong.c b/scan/scan_xlonglong.c index bd6d9b9..ccf1e54 100644 --- a/scan/scan_xlonglong.c +++ b/scan/scan_xlonglong.c @@ -4,7 +4,7 @@ size_t scan_xlonglong(const char* src,unsigned long long* dest) { register const char *tmp=src; register long long l=0; register unsigned char c; - while ((c=scan_fromhex(*tmp))<16) { + while ((l>>(sizeof(l)*8-4))==0 && (c=scan_fromhex(*tmp))<16) { l=(l<<4)+c; ++tmp; } diff --git a/test/marshal.c b/test/marshal.c index 9b060c1..b4bf813 100644 --- a/test/marshal.c +++ b/test/marshal.c @@ -15,12 +15,10 @@ int main() { 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 zap(); assert(fmt_utf8(NULL,12345) == 3); @@ -172,8 +170,7 @@ int main() { 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("-9223372036854775808",&l)==20 && l==(signed long long)0x8000000000000000ull); assert(scan_long("-9223372036854775809",&l)==19 && l==-922337203685477580ll); } @@ -206,4 +203,22 @@ int main() { assert(scan_short("+032767",&s)==7 && s==32767); assert(scan_short("-32768",&s)==6 && s==-32768); assert(scan_short("-032769",&s)==6 && s==-3276); + + assert(scan_ulonglong("18446744073709551615",&ull)==20 && ull==0xffffffffffffffffull); + assert(scan_ulonglong("18446744073709551616",&ull)==19 && ull==1844674407370955161ull); + assert(scan_xlonglong("ffffffffffffffff",&ull)==16 && ull==0xffffffffffffffffull); + assert(scan_xlonglong("ffffffffffffffff0",&ull)==16 && ull==0xffffffffffffffffull); + assert(scan_8longlong("1777777777777777777777",&ull)==22 && ull==0xffffffffffffffffull); + assert(scan_8longlong("17777777777777777777770",&ull)==22 && ull==0xffffffffffffffffull); + + assert(scan_longlong("9223372036854775807",&ll)==19 && ll==0x7fffffffffffffffll); + assert(scan_longlong("09223372036854775807",&ll)==20 && ll==0x7fffffffffffffffll); + assert(scan_longlong("092233720368547758070",&ll)==20 && ll==0x7fffffffffffffffll); + assert(scan_longlong("+9223372036854775807",&ll)==20 && ll==0x7fffffffffffffffll); + assert(scan_longlong("+9223372036854775808",&ll)==19 && ll==922337203685477580ll); + assert(scan_longlong("-9223372036854775807",&ll)==20 && ll==-9223372036854775807ll); + assert(scan_longlong("-9223372036854775808",&ll)==20 && ll==(signed long long)0x8000000000000000ull); + assert(scan_longlong("-9223372036854775809",&ll)==19 && ll==-922337203685477580ll); + + return 0; }