summaryrefslogtreecommitdiff
path: root/ext/ereg
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2009-05-28 21:57:24 +0000
committerScott MacVicar <scottmac@php.net>2009-05-28 21:57:24 +0000
commit4044f880e80df4c2f7723805f7edde30d3487710 (patch)
tree11d0dcb7cb3a84505e37587aeb5d7f71f14e8d44 /ext/ereg
parent19194ff51bbfffb71b9f91b4de3f3d0ba777a614 (diff)
downloadphp-git-4044f880e80df4c2f7723805f7edde30d3487710.tar.gz
MFH: Fix bug #48416 - Force a cache size for ereg to stop it getting out of control. Lazy LRU here.
Diffstat (limited to 'ext/ereg')
-rw-r--r--ext/ereg/ereg.c51
-rw-r--r--ext/ereg/php_ereg.h1
2 files changed, 51 insertions, 1 deletions
diff --git a/ext/ereg/ereg.c b/ext/ereg/ereg.c
index ed9dfaec2b..67460bf9fd 100644
--- a/ext/ereg/ereg.c
+++ b/ext/ereg/ereg.c
@@ -67,8 +67,10 @@ const zend_function_entry ereg_functions[] = {
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 @@ zend_module_entry ereg_module_entry = {
};
/* }}} */
+/* {{{ 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 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
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 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
*/
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 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
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 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
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 _free_ereg_cache(reg_cache *rc)
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)
diff --git a/ext/ereg/php_ereg.h b/ext/ereg/php_ereg.h
index fdadd1d3f5..2d148e2624 100644
--- a/ext/ereg/php_ereg.h
+++ b/ext/ereg/php_ereg.h
@@ -39,6 +39,7 @@ PHPAPI PHP_FUNCTION(sql_regcase);
ZEND_BEGIN_MODULE_GLOBALS(ereg)
HashTable ht_rc;
+ unsigned int lru_counter;
ZEND_END_MODULE_GLOBALS(ereg)
/* Module functions */