]> granicus.if.org Git - php/commitdiff
Added support for glob symbols in blacklist entries (?, *, **)
authorDmitry Stogov <dmitry@zend.com>
Tue, 30 Jul 2013 23:01:19 +0000 (03:01 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 30 Jul 2013 23:01:19 +0000 (03:01 +0400)
NEWS
ext/opcache/tests/blacklist.inc [new file with mode: 0644]
ext/opcache/tests/blacklist.phpt
ext/opcache/tests/opcache-2.blacklist
ext/opcache/zend_accelerator_blacklist.c

diff --git a/NEWS b/NEWS
index d21126d45a14b65fb3440727255aa49e665dd449..60b2760b390fd9d2b7b8492f457546c9baee7c19 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ PHP                                                                        NEWS
     limited case). (Arpad)
 
 - OPcahce:
+  . Added support for glob symbols in blacklist entries (?, *, **).
+    (Terry Elison, Dmitry)
   . Fixed bug #65338 (Enabling both php_opcache and php_wincache AVs on
     shutdown). (Dmitry)
 
diff --git a/ext/opcache/tests/blacklist.inc b/ext/opcache/tests/blacklist.inc
new file mode 100644 (file)
index 0000000..a9db751
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+       echo "ok\n";
+?>
index f4a34723ada8997d6a09cc9382ba6319053d7648..57e4c306dd7f7762f7ee612fbef6baf64eb8027f 100644 (file)
@@ -9,7 +9,13 @@ opcache.blacklist_filename={PWD}/opcache-*.blacklist
 --FILE--
 <?php
 $conf = opcache_get_configuration();
-print_r($conf['blacklist']);
+$conf = $conf['blacklist'];
+$conf[3] = preg_replace("!^\\Q".dirname(__FILE__)."\\E!", "__DIR__", $conf[3]); 
+$conf[4] = preg_replace("!^\\Q".dirname(__FILE__)."\\E!", "__DIR__", $conf[4]); 
+print_r($conf);
+include("blacklist.inc");
+$status = opcache_get_status();
+print_r(count($status['scripts']));
 ?>
 --EXPECT--
 Array
@@ -17,4 +23,10 @@ Array
     [0] => /path/to/foo
     [1] => /path/to/foo2
     [2] => /path/to/bar
-)
\ No newline at end of file
+    [3] => __DIR__/blacklist.inc
+    [4] => __DIR__/current.php
+    [5] => /tmp/path/?nocache.inc
+    [6] => /tmp/path/*/somedir
+)
+ok
+1
index 4f6580a773b19e87d81a861891326ad8b0765a28..575d9fab304d99a97c65b06246bbb03782de0309 100644 (file)
@@ -1 +1,6 @@
 /path/to/bar
+; wildcard and relative entires
+blacklist.inc
+./current.php
+/tmp/path/?nocache.inc
+/tmp/path/*/somedir
index b09d0e54c3bf2959e194e0513f76043eec2fccc7..b11d41e1ecbd0f53fe73107f4c071a1114b3e796 100644 (file)
@@ -86,9 +86,9 @@ static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err)
 
 static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
 {
-       char *regexp;
-       int i, j, clen, reg_err, end = 0, rlen = 6;
+       int i, reg_err;
        zend_regexp_list **regexp_list_it, *it;
+       char regexp[12*1024], *p, *end, *c, *backtrack = NULL;
 
        if (blacklist->pos == 0) {
                /* we have no blacklist to talk about */
@@ -96,36 +96,91 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
        }
 
        regexp_list_it = &(blacklist->regexp_list);
-       for (i = 0; i < blacklist->pos; i++) {
-               rlen += blacklist->entries[i].path_length * 2 + 2;
 
-               /* don't create a regexp buffer bigger than 12K)*/
-               if ((i + 1 == blacklist->pos) || ((rlen + blacklist->entries[i + 1].path_length * 2 + 2) > (12 * 1024))) {
-                       regexp = (char *)malloc(rlen);
-                       if (!regexp) {
-                               zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
-                               return;
+       regexp[0] = '^';
+       regexp[1] = '(';
+       p = regexp + 2;
+       end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0");
+
+       for (i = 0; i < blacklist->pos; ) {
+               c = blacklist->entries[i].path;
+               if (p + blacklist->entries[i].path_length < end) {
+                       while (*c && p < end) {
+                               switch (*c) {
+                                       case '?':
+                                               c++;
+#ifdef ZEND_WIN32
+                                               p[0] = '[';                     /* * => [^\\] on Win32 */
+                                               p[1] = '^';
+                                               p[2] = '\\';
+                                               p[3] = '\\';
+                                               p[4] = ']';
+                                               p += 5;
+#else
+                                               p[0] = '[';                     /* * => [^/] on *nix */
+                                               p[1] = '^';
+                                               p[2] = '/';
+                                               p[3] = ']';
+                                               p += 4;
+#endif
+                                               break;
+                                       case '*':
+                                               c++;
+                                               if (*c == '*') {
+                                                       c++;
+                                                       p[0] = '.';                     /* ** => .* */
+                                                       p[1] = '*';
+                                                       p += 2;
+                                               } else {
+#ifdef ZEND_WIN32
+                                                       p[0] = '[';                     /* * => [^\\]* on Win32 */
+                                                       p[1] = '^';
+                                                       p[2] = '\\';
+                                                       p[3] = '\\';
+                                                       p[4] = ']';
+                                                       p[5] = '*';
+                                                       p += 6;
+#else
+                                                       p[0] = '[';                     /* * => [^/]* on *nix */
+                                                       p[1] = '^';
+                                                       p[2] = '/';
+                                                       p[3] = ']';
+                                                       p[4] = '*';
+                                                       p += 5;
+#endif
+                                               }
+                                               break;
+                                       case '^':
+                                       case '.':
+                                       case '[':
+                                       case ']':
+                                       case '$':
+                                       case '(':
+                                       case ')':
+                                       case '|':
+                                       case '+':
+                                       case '{':
+                                       case '}':
+                                       case '\\':
+                                               *p++ = '\\';
+                                               /* break missing intentionally */
+                                       default:
+                                               *p++ = *c++;
+                               }
                        }
-                       regexp[0] = '^';
-                       regexp[1] = '(';
-
-                       clen = 2;
-                       for (j = end; j <= i; j++) {
+               }
 
-                               int c;
-                               if (j != end) {
-                                       regexp[clen++] = '|';
-                               }
-                               /* copy mangled filename */
-                               for (c = 0; c < blacklist->entries[j].path_length; c++) {
-                                       if (strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) {
-                                               regexp[clen++] = '\\';
-                                       }
-                                       regexp[clen++] = blacklist->entries[j].path[c];
+               if (*c || i == blacklist->pos - 1) {
+                       if (*c) {
+                               if (!backtrack) {
+                                       zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
                                }
+                               p = backtrack;
+                       } else {
+                               i++;
                        }
-                       regexp[clen++] = ')';
-                       regexp[clen] = '\0';
+                       *p++ = ')';
+                       *p++ = '\0';
 
                        it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
                        if (!it) {
@@ -138,11 +193,13 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
                                blacklist_report_regexp_error(&it->comp_regex, reg_err);
                        }
                        /* prepare for the next iteration */
-                       free(regexp);
-                       end = i + 1;
-                       rlen = 6;
+                       p = regexp + 2;
                        *regexp_list_it = it;
                        regexp_list_it = &it->next;
+               } else {
+                       backtrack = p;
+                       *p++ = '|';
+                       i++;
                }
        }
 }
@@ -182,9 +239,9 @@ static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filena
 void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
 #endif
 {
-       char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1];
+       char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL;
        FILE *fp;
-       int path_length;
+       int path_length, blacklist_path_length;
        TSRMLS_FETCH();
 
        if ((fp = fopen(filename, "r")) == NULL) {
@@ -194,6 +251,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
 
        zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file:  '%s'", filename);
 
+       if (VCWD_REALPATH(filename, buf)) {
+               blacklist_path_length = zend_dirname(buf, strlen(buf));
+               blacklist_path = zend_strndup(buf, blacklist_path_length);
+       }
+
        memset(buf, 0, sizeof(buf));
        memset(real_path, 0, sizeof(real_path));
 
@@ -230,7 +292,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
                }
 
                path_dup = zend_strndup(pbuf, path_length);
-               expand_filepath(path_dup, real_path TSRMLS_CC);
+               if (blacklist_path) {
+                       expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length TSRMLS_CC);
+               } else {
+                       expand_filepath(path_dup, real_path TSRMLS_CC);
+               }
                path_length = strlen(real_path);
 
                free(path_dup);
@@ -247,6 +313,9 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
                blacklist->pos++;
        }
        fclose(fp);
+       if (blacklist_path) {
+               free(blacklist_path);
+       }
        zend_accel_blacklist_update_regexp(blacklist);
 }
 
@@ -254,7 +323,8 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
 void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
 {
        glob_t globbuf;
-       int    ret, i;
+       int    ret;
+       unsigned int i;
 
        memset(&globbuf, 0, sizeof(glob_t));