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
