Skip to content

Commit 3d29448

Browse files
author
Andrei Zmievski
committed
Do a cache flush if we detect possible cache corruption (same as for
PCRE).
1 parent 9b3929a commit 3d29448

File tree

2 files changed

+58
-24
lines changed

2 files changed

+58
-24
lines changed

ext/ereg/ereg.c

+29-12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ typedef struct {
3333
int cflags;
3434
} reg_cache;
3535

36+
static int reg_magic = 0;
37+
3638
/* {{{ _php_regcomp
3739
*/
3840
static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
@@ -42,19 +44,34 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
4244
reg_cache *rc = NULL;
4345
TSRMLS_FETCH();
4446

45-
if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE ||
46-
rc->cflags != cflags) {
47-
r = regcomp(preg, pattern, cflags);
48-
if(!r) {
49-
reg_cache rcp;
50-
51-
rcp.cflags = cflags;
52-
memcpy(&rcp.preg, preg, sizeof(*preg));
53-
zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
54-
(void *) &rcp, sizeof(rcp), NULL);
47+
if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS
48+
&& rc->cflags == cflags) {
49+
/*
50+
* We use a saved magic number to see whether cache is corrupted, and if it
51+
* is, we flush it and compile the pattern from scratch.
52+
*/
53+
if (rc->preg.re_magic != reg_magic) {
54+
zend_hash_clean(&REG(ht_rc));
55+
} else {
56+
memcpy(preg, &rc->preg, sizeof(*preg));
57+
return r;
5558
}
56-
} else {
57-
memcpy(preg, &rc->preg, sizeof(*preg));
59+
}
60+
61+
r = regcomp(preg, pattern, cflags);
62+
if(!r) {
63+
reg_cache rcp;
64+
65+
rcp.cflags = cflags;
66+
memcpy(&rcp.preg, preg, sizeof(*preg));
67+
/*
68+
* Since we don't have access to the actual MAGIC1 definition in the private
69+
* header file, we save the magic value immediately after compilation. Hopefully,
70+
* it's good.
71+
*/
72+
if (!reg_magic) reg_magic = preg->re_magic;
73+
zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
74+
(void *) &rcp, sizeof(rcp), NULL);
5875
}
5976

6077
return r;

ext/standard/reg.c

+29-12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ typedef struct {
3333
int cflags;
3434
} reg_cache;
3535

36+
static int reg_magic = 0;
37+
3638
/* {{{ _php_regcomp
3739
*/
3840
static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
@@ -42,19 +44,34 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
4244
reg_cache *rc = NULL;
4345
TSRMLS_FETCH();
4446

45-
if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE ||
46-
rc->cflags != cflags) {
47-
r = regcomp(preg, pattern, cflags);
48-
if(!r) {
49-
reg_cache rcp;
50-
51-
rcp.cflags = cflags;
52-
memcpy(&rcp.preg, preg, sizeof(*preg));
53-
zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
54-
(void *) &rcp, sizeof(rcp), NULL);
47+
if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS
48+
&& rc->cflags == cflags) {
49+
/*
50+
* We use a saved magic number to see whether cache is corrupted, and if it
51+
* is, we flush it and compile the pattern from scratch.
52+
*/
53+
if (rc->preg.re_magic != reg_magic) {
54+
zend_hash_clean(&REG(ht_rc));
55+
} else {
56+
memcpy(preg, &rc->preg, sizeof(*preg));
57+
return r;
5558
}
56-
} else {
57-
memcpy(preg, &rc->preg, sizeof(*preg));
59+
}
60+
61+
r = regcomp(preg, pattern, cflags);
62+
if(!r) {
63+
reg_cache rcp;
64+
65+
rcp.cflags = cflags;
66+
memcpy(&rcp.preg, preg, sizeof(*preg));
67+
/*
68+
* Since we don't have access to the actual MAGIC1 definition in the private
69+
* header file, we save the magic value immediately after compilation. Hopefully,
70+
* it's good.
71+
*/
72+
if (!reg_magic) reg_magic = preg->re_magic;
73+
zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
74+
(void *) &rcp, sizeof(rcp), NULL);
5875
}
5976

6077
return r;

0 commit comments

Comments
 (0)