scottmac Fri May 29 00:03:28 2009 UTC
Modified files: (Branch: PHP_5_2)
/php-src/ext/standard reg.c reg.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/standard/reg.c?r1=1.82.2.3.2.6&r2=1.82.2.3.2.7&diff_format=u
Index: php-src/ext/standard/reg.c
diff -u php-src/ext/standard/reg.c:1.82.2.3.2.6
php-src/ext/standard/reg.c:1.82.2.3.2.7
--- php-src/ext/standard/reg.c:1.82.2.3.2.6 Wed Dec 31 11:17:45 2008
+++ php-src/ext/standard/reg.c Fri May 29 00:03:28 2009
@@ -17,7 +17,7 @@
| Jaakko Hyvätti <[email protected]> |
+----------------------------------------------------------------------+
*/
-/* $Id: reg.c,v 1.82.2.3.2.6 2008/12/31 11:17:45 sebastian Exp $ */
+/* $Id: reg.c,v 1.82.2.3.2.7 2009/05/29 00:03:28 scottmac Exp $ */
#include <stdio.h>
#include <ctype.h>
@@ -31,9 +31,43 @@
typedef struct {
regex_t preg;
int cflags;
+ unsigned int lastuse;
} reg_cache;
static int reg_magic = 0;
+#define EREG_CACHE_SIZE 4096
+
+/* {{{ 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
*/
@@ -43,7 +77,17 @@
int patlen = strlen(pattern);
reg_cache *rc = NULL;
TSRMLS_FETCH();
-
+
+ if (zend_hash_num_elements(®(ht_rc)) >= EREG_CACHE_SIZE) {
+ if (REG(lru_counter) >= (1 << 31) ||
zend_hash_sort(®(ht_rc), zend_qsort, ereg_lru_cmp, 0 TSRMLS_CC) == FAILURE) {
+ zend_hash_clean(®(ht_rc));
+ REG(lru_counter) = 0;
+ } else {
+ int num_clean = EREG_CACHE_SIZE / 2;
+ zend_hash_apply_with_argument(®(ht_rc),
ereg_clean_cache, &num_clean TSRMLS_CC);
+ }
+ }
+
if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **)
&rc) == SUCCESS
&& rc->cflags == cflags) {
#ifdef HAVE_REGEX_T_RE_MAGIC
@@ -53,6 +97,7 @@
*/
if (rc->preg.re_magic != reg_magic) {
zend_hash_clean(®(ht_rc));
+ REG(lru_counter) = 0;
} else {
memcpy(preg, &rc->preg, sizeof(*preg));
return r;
@@ -64,6 +109,7 @@
reg_cache rcp;
rcp.cflags = cflags;
+ rcp.lastuse = ++(REG(lru_counter));
memcpy(&rcp.preg, preg, sizeof(*preg));
/*
* Since we don't have access to the actual MAGIC1 definition
in the private
@@ -82,6 +128,7 @@
reg_cache rcp;
rcp.cflags = cflags;
+ rcp.lastuse = ++(REG(lru_counter));
memcpy(&rcp.preg, preg, sizeof(*preg));
zend_hash_update(®(ht_rc), (char *) pattern,
patlen+1,
(void *) &rcp,
sizeof(rcp), NULL);
@@ -105,6 +152,7 @@
static void php_reg_init_globals(zend_reg_globals *reg_globals TSRMLS_DC)
{
zend_hash_init(®_globals->ht_rc, 0, NULL, (void (*)(void *))
_free_reg_cache, 1);
+ reg_globals->lru_counter = 0;
}
static void php_reg_destroy_globals(zend_reg_globals *reg_globals TSRMLS_DC)
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/reg.h?r1=1.21.2.1.2.3&r2=1.21.2.1.2.4&diff_format=u
Index: php-src/ext/standard/reg.h
diff -u php-src/ext/standard/reg.h:1.21.2.1.2.3
php-src/ext/standard/reg.h:1.21.2.1.2.4
--- php-src/ext/standard/reg.h:1.21.2.1.2.3 Wed Dec 31 11:17:45 2008
+++ php-src/ext/standard/reg.h Fri May 29 00:03:28 2009
@@ -17,7 +17,7 @@
*/
-/* $Id: reg.h,v 1.21.2.1.2.3 2008/12/31 11:17:45 sebastian Exp $ */
+/* $Id: reg.h,v 1.21.2.1.2.4 2009/05/29 00:03:28 scottmac Exp $ */
#ifndef REG_H
#define REG_H
@@ -34,6 +34,7 @@
ZEND_BEGIN_MODULE_GLOBALS(reg)
HashTable ht_rc;
+ unsigned int lru_counter;
ZEND_END_MODULE_GLOBALS(reg)
PHP_MINIT_FUNCTION(regex);
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php