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