Hi Andrei, Antony, ... Attached is a patch for zend_u_strtol() and HANDLE_U_NUMERIC() to only allow ASCII digits and not use u_digit(). (Also switched to hex values for sign characters, etc.) I tested the changes quickly and all appears fine. Provides a pretty good performance increase too. :-)
Matt
Index: zend_hash.c =================================================================== RCS file: /repository/ZendEngine2/zend_hash.c,v retrieving revision 1.144 diff -u -r1.144 zend_hash.c --- zend_hash.c 8 Nov 2006 16:02:29 -0000 1.144 +++ zend_hash.c 7 Dec 2006 10:16:21 -0000 @@ -1880,35 +1880,33 @@ } while (0); \ } -#define HANDLE_U_NUMERIC(key, length, func) { \ - register UChar *tmp=key; \ - register int val; \ +#define HANDLE_U_NUMERIC(key, length, func) { \ + register UChar *tmp=key; \ \ - if (*tmp=='-') { \ + if (*tmp==0x2D /*'-'*/) { \ tmp++; \ } \ - if ((val = u_digit(*tmp, 10)) >= 0) do { /* possibly a numeric index */ \ - UChar *end=key+length-1; \ + if ((*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) do { /* possibly a numeric index */ \ + UChar *end=key+length-1; \ long idx; \ \ - if (val==0 && length>2) { /* don't accept numbers with leading zeros */ \ + if (*tmp++==0x30 && length>2) { /* don't accept numbers with leading zeros */ \ break; \ - } \ - tmp++; \ + } \ while (tmp<end) { \ - if (u_digit(*tmp, 10) < 0) { \ + if (!(*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { \ break; \ } \ tmp++; \ } \ if (tmp==end && *tmp==0) { /* a numeric index */ \ - if (*key=='-') { \ - idx = zend_u_strtol(key, NULL, 10); \ + if (*key==0x2D /*'-'*/) { \ + idx = zend_u_strtol(key, NULL, 10); \ if (idx!=LONG_MIN) { \ return func; \ } \ } else { \ - idx = zend_u_strtol(key, NULL, 10); \ + idx = zend_u_strtol(key, NULL, 10); \ if (idx!=LONG_MAX) { \ return func; \ } \ Index: zend_strtol.c =================================================================== RCS file: /repository/ZendEngine2/zend_strtol.c,v retrieving revision 1.3 diff -u -r1.3 zend_strtol.c --- zend_strtol.c 6 Oct 2006 17:23:05 -0000 1.3 +++ zend_strtol.c 7 Dec 2006 10:16:21 -0000 @@ -55,7 +55,6 @@ register UChar c; register unsigned long cutoff; register int neg = 0, any, cutlim; - register int val; /* * Skip white space and pick up leading +/- sign if any. @@ -65,20 +64,20 @@ do { c = *s++; } while (u_isspace(c)); - if (c == '-') { + if (c == 0x2D /*'-'*/) { neg = 1; c = *s++; - } else if (c == '+') + } else if (c == 0x2B /*'+'*/) c = *s++; if ((base == 0 || base == 16) && - (c == '0') - && (*s == 'x' || *s == 'X')) { + (c == 0x30 /*'0'*/) + && (*s == 0x78 /*'x'*/ || *s == 0x58 /*'X'*/)) { c = s[1]; s += 2; base = 16; } if (base == 0) - base = (c == '0') ? 8 : 10; + base = (c == 0x30 /*'0'*/) ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal @@ -101,14 +100,23 @@ cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { - if ((val = u_digit(c, base)) < 0) + if (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) + c -= 0x30 /*'0'*/; + else if (c >= 0x41 /*'A'*/ && c <= 0x5A /*'Z'*/) + c -= 0x41 /*'A'*/ - 10; + else if (c >= 0x61 /*'a'*/ && c <= 0x7A /*'z'*/) + c -= 0x61 /*'a'*/ - 10; + else break; - if (any < 0 || acc > cutoff || (acc == cutoff && val > cutlim)) + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; - acc += val; + acc += c; } } if (any < 0) { @@ -116,7 +124,7 @@ errno = ERANGE; } else if (neg) acc = -acc; - if (endptr != 0) + if (endptr != NULL) *endptr = (UChar *)(any ? s - 1 : nptr); return (acc); }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php