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

Reply via email to