scottmac                Thu May 28 21:57:24 2009 UTC

  Modified files:              (Branch: PHP_5_3)
    /php-src/ext/ereg   ereg.c php_ereg.h 
  Log:
  MFH: Fix bug #48416 - Force a cache size for ereg to stop it getting out of 
control. Lazy LRU here.
  
  
  
http://cvs.php.net/viewvc.cgi/php-src/ext/ereg/ereg.c?r1=1.90.2.12&r2=1.90.2.13&diff_format=u
Index: php-src/ext/ereg/ereg.c
diff -u php-src/ext/ereg/ereg.c:1.90.2.12 php-src/ext/ereg/ereg.c:1.90.2.13
--- php-src/ext/ereg/ereg.c:1.90.2.12   Thu Jan  8 00:37:39 2009
+++ php-src/ext/ereg/ereg.c     Thu May 28 21:57:24 2009
@@ -17,7 +17,7 @@
    |          Jaakko Hyvätti <jaa...@hyvatti.iki.fi>                      | 
    +----------------------------------------------------------------------+
  */
-/* $Id: ereg.c,v 1.90.2.12 2009/01/08 00:37:39 iliaa Exp $ */
+/* $Id: ereg.c,v 1.90.2.13 2009/05/28 21:57:24 scottmac Exp $ */
 
 #include <stdio.h>
 #include <ctype.h>
@@ -67,8 +67,10 @@
 typedef struct {
        regex_t preg;
        int cflags;
+       unsigned long lastuse;
 } reg_cache;
 static int reg_magic = 0;
+#define EREG_CACHE_SIZE 4096
 /* }}} */
 
 ZEND_DECLARE_MODULE_GLOBALS(ereg)
@@ -88,6 +90,38 @@
 };
 /* }}} */
 
+/* {{{ ereg_lru_cmp */
+static int ereg_lru_cmp(const void *a, const void *b TSRMLS_DC)
+{
+       Bucket *f = *((Bucket **) a);
+       Bucket *s = *((Bucket **) b);
+
+       if (((reg_cache *)f->pData)->lastuse <
+                               ((reg_cache *)s->pData)->lastuse) {
+               return -1;
+       } else if (((reg_cache *)f->pData)->lastuse ==
+                               ((reg_cache *)s->pData)->lastuse) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+/* }}} */
+
+/* {{{ static ereg_clean_cache */
+static int ereg_clean_cache(void *data, void *arg TSRMLS_DC)
+{
+       int *num_clean = (int *)arg;
+
+       if (*num_clean > 0) {
+               (*num_clean)--;
+               return ZEND_HASH_APPLY_REMOVE;
+       } else {
+               return ZEND_HASH_APPLY_STOP;
+       }
+}
+/* }}} */
+
 /* {{{ _php_regcomp
  */
 static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
@@ -96,7 +130,18 @@
        int patlen = strlen(pattern);
        reg_cache *rc = NULL;
        TSRMLS_FETCH();
-       
+
+       if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) {
+               /* easier than dealing with overflow as it happens */
+               if (EREG(lru_counter) >= (1 << 31) || 
zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0 TSRMLS_CC) == FAILURE) 
{
+                       zend_hash_clean(&EREG(ht_rc));
+                       EREG(lru_counter) = 0;
+               } else {
+                       int num_clean = EREG_CACHE_SIZE / 4;
+                       zend_hash_apply_with_argument(&EREG(ht_rc), 
ereg_clean_cache, &num_clean TSRMLS_CC);
+               }
+       }
+
        if(zend_hash_find(&EREG(ht_rc), (char *) pattern, patlen+1, (void **) 
&rc) == SUCCESS
           && rc->cflags == cflags) {
 #ifdef HAVE_REGEX_T_RE_MAGIC
@@ -106,6 +151,7 @@
                 */
                if (rc->preg.re_magic != reg_magic) {
                        zend_hash_clean(&EREG(ht_rc));
+                       EREG(lru_counter) = 0;
                } else {
                        memcpy(preg, &rc->preg, sizeof(*preg));
                        return r;
@@ -117,6 +163,7 @@
                reg_cache rcp;
 
                rcp.cflags = cflags;
+               rcp.lastuse = ++(EREG(lru_counter));
                memcpy(&rcp.preg, preg, sizeof(*preg));
                /*
                 * Since we don't have access to the actual MAGIC1 definition 
in the private
@@ -135,6 +182,7 @@
                        reg_cache rcp;
 
                        rcp.cflags = cflags;
+                       rcp.lastuse = ++(EREG(lru_counter));
                        memcpy(&rcp.preg, preg, sizeof(*preg));
                        zend_hash_update(&EREG(ht_rc), (char *) pattern, 
patlen+1,
                                                         (void *) &rcp, 
sizeof(rcp), NULL);
@@ -158,6 +206,7 @@
 static void php_ereg_init_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
 {
        zend_hash_init(&ereg_globals->ht_rc, 0, NULL, (void (*)(void *)) 
_free_ereg_cache, 1);
+       ereg_globals->lru_counter = 0;
 }
 
 static void php_ereg_destroy_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
http://cvs.php.net/viewvc.cgi/php-src/ext/ereg/php_ereg.h?r1=1.24.2.4&r2=1.24.2.5&diff_format=u
Index: php-src/ext/ereg/php_ereg.h
diff -u php-src/ext/ereg/php_ereg.h:1.24.2.4 
php-src/ext/ereg/php_ereg.h:1.24.2.5
--- php-src/ext/ereg/php_ereg.h:1.24.2.4        Wed Dec 31 11:15:36 2008
+++ php-src/ext/ereg/php_ereg.h Thu May 28 21:57:24 2009
@@ -17,7 +17,7 @@
 */
 
 
-/* $Id: php_ereg.h,v 1.24.2.4 2008/12/31 11:15:36 sebastian Exp $ */
+/* $Id: php_ereg.h,v 1.24.2.5 2009/05/28 21:57:24 scottmac Exp $ */
 
 #ifndef EREG_H
 #define EREG_H
@@ -39,6 +39,7 @@
 
 ZEND_BEGIN_MODULE_GLOBALS(ereg)
        HashTable ht_rc;
+       unsigned int lru_counter;
 ZEND_END_MODULE_GLOBALS(ereg)
 
 /* Module functions */



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to