From 3d2944863c0d33ce27014376bbf33fec30debcb7 Mon Sep 17 00:00:00 2001
From: Andrei Zmievski <andrei@php.net>
Date: Thu, 26 May 2005 21:48:35 +0000
Subject: [PATCH] Do a cache flush if we detect possible cache corruption (same
 as for PCRE).

---
 ext/ereg/ereg.c    | 41 +++++++++++++++++++++++++++++------------
 ext/standard/reg.c | 41 +++++++++++++++++++++++++++++------------
 2 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/ext/ereg/ereg.c b/ext/ereg/ereg.c
index 02d1903539..c8afdc80f9 100644
--- a/ext/ereg/ereg.c
+++ b/ext/ereg/ereg.c
@@ -33,6 +33,8 @@ typedef struct {
 	int cflags;
 } reg_cache;
 
+static int reg_magic = 0;
+
 /* {{{ _php_regcomp
  */
 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)
 	reg_cache *rc = NULL;
 	TSRMLS_FETCH();
 	
-	if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE ||
-			rc->cflags != cflags) {
-		r = regcomp(preg, pattern, cflags);
-		if(!r) {
-			reg_cache rcp;
-
-			rcp.cflags = cflags;
-			memcpy(&rcp.preg, preg, sizeof(*preg));
-			zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
-					(void *) &rcp, sizeof(rcp), NULL);
+	if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS
+	   && rc->cflags == cflags) {
+		/*
+		 * We use a saved magic number to see whether cache is corrupted, and if it
+		 * is, we flush it and compile the pattern from scratch.
+		 */
+		if (rc->preg.re_magic != reg_magic) {
+			zend_hash_clean(&REG(ht_rc));
+		} else {
+			memcpy(preg, &rc->preg, sizeof(*preg));
+			return r;
 		}
-	} else {
-		memcpy(preg, &rc->preg, sizeof(*preg));
+	}
+
+	r = regcomp(preg, pattern, cflags);
+	if(!r) {
+		reg_cache rcp;
+
+		rcp.cflags = cflags;
+		memcpy(&rcp.preg, preg, sizeof(*preg));
+		/*
+		 * Since we don't have access to the actual MAGIC1 definition in the private
+		 * header file, we save the magic value immediately after compilation. Hopefully,
+		 * it's good.
+		 */
+		if (!reg_magic) reg_magic = preg->re_magic;
+		zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
+						 (void *) &rcp, sizeof(rcp), NULL);
 	}
 	
 	return r;
diff --git a/ext/standard/reg.c b/ext/standard/reg.c
index 02d1903539..c8afdc80f9 100644
--- a/ext/standard/reg.c
+++ b/ext/standard/reg.c
@@ -33,6 +33,8 @@ typedef struct {
 	int cflags;
 } reg_cache;
 
+static int reg_magic = 0;
+
 /* {{{ _php_regcomp
  */
 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)
 	reg_cache *rc = NULL;
 	TSRMLS_FETCH();
 	
-	if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE ||
-			rc->cflags != cflags) {
-		r = regcomp(preg, pattern, cflags);
-		if(!r) {
-			reg_cache rcp;
-
-			rcp.cflags = cflags;
-			memcpy(&rcp.preg, preg, sizeof(*preg));
-			zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
-					(void *) &rcp, sizeof(rcp), NULL);
+	if(zend_hash_find(&REG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS
+	   && rc->cflags == cflags) {
+		/*
+		 * We use a saved magic number to see whether cache is corrupted, and if it
+		 * is, we flush it and compile the pattern from scratch.
+		 */
+		if (rc->preg.re_magic != reg_magic) {
+			zend_hash_clean(&REG(ht_rc));
+		} else {
+			memcpy(preg, &rc->preg, sizeof(*preg));
+			return r;
 		}
-	} else {
-		memcpy(preg, &rc->preg, sizeof(*preg));
+	}
+
+	r = regcomp(preg, pattern, cflags);
+	if(!r) {
+		reg_cache rcp;
+
+		rcp.cflags = cflags;
+		memcpy(&rcp.preg, preg, sizeof(*preg));
+		/*
+		 * Since we don't have access to the actual MAGIC1 definition in the private
+		 * header file, we save the magic value immediately after compilation. Hopefully,
+		 * it's good.
+		 */
+		if (!reg_magic) reg_magic = preg->re_magic;
+		zend_hash_update(&REG(ht_rc), (char *) pattern, patlen+1,
+						 (void *) &rcp, sizeof(rcp), NULL);
 	}
 	
 	return r;
-- 
2.40.0