PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/opcache - zend_accelerator_blacklist.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 133 164 81.1 %
Date: 2016-09-27 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "main/php.h"
      23             : #include "main/fopen_wrappers.h"
      24             : #include "ZendAccelerator.h"
      25             : #include "zend_accelerator_blacklist.h"
      26             : 
      27             : #ifdef ZEND_WIN32
      28             : # define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE)
      29             : #else
      30             : # define REGEX_MODE (REG_EXTENDED|REG_NOSUB)
      31             : #endif
      32             : 
      33             : #ifdef HAVE_GLOB
      34             : #ifdef PHP_WIN32
      35             : #include "win32/glob.h"
      36             : #else
      37             : #include <glob.h>
      38             : #endif
      39             : #endif
      40             : 
      41             : #include "ext/pcre/php_pcre.h"
      42             : 
      43             : #define ZEND_BLACKLIST_BLOCK_SIZE       32
      44             : 
      45             : struct _zend_regexp_list {
      46             :         pcre             *re;
      47             :         zend_regexp_list *next;
      48             : };
      49             : 
      50             : zend_blacklist accel_blacklist;
      51             : 
      52           3 : void zend_accel_blacklist_init(zend_blacklist *blacklist)
      53             : {
      54           3 :         blacklist->pos = 0;
      55           3 :         blacklist->size = ZEND_BLACKLIST_BLOCK_SIZE;
      56             : 
      57           3 :         if (blacklist->entries != NULL) {
      58           0 :                 zend_accel_blacklist_shutdown(blacklist);
      59             :         }
      60             : 
      61           3 :         blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size);
      62           3 :         if (!blacklist->entries) {
      63           0 :                 zend_accel_error(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n");
      64           0 :                 return;
      65             :         }
      66           3 :         blacklist->regexp_list = NULL;
      67             : }
      68             : 
      69           0 : static void blacklist_report_regexp_error(const char *pcre_error, int pcre_error_offset)
      70             : {
      71           0 :         zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation failed (offset: %d), %s\n", pcre_error_offset, pcre_error);
      72           0 : }
      73             : 
      74           6 : static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
      75             : {
      76             :         const char *pcre_error;
      77             :         int i, pcre_error_offset;
      78             :         zend_regexp_list **regexp_list_it, *it;
      79           6 :         char regexp[12*1024], *p, *end, *c, *backtrack = NULL;
      80             : 
      81           6 :         if (blacklist->pos == 0) {
      82             :                 /* we have no blacklist to talk about */
      83           0 :                 return;
      84             :         }
      85             : 
      86           6 :         regexp_list_it = &(blacklist->regexp_list);
      87             : 
      88           6 :         regexp[0] = '^';
      89           6 :         regexp[1] = '(';
      90           6 :         p = regexp + 2;
      91           6 :         end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0");
      92             : 
      93          39 :         for (i = 0; i < blacklist->pos; ) {
      94          27 :                 c = blacklist->entries[i].path;
      95          27 :                 if (p + blacklist->entries[i].path_length < end) {
      96         681 :                         while (*c && p < end) {
      97         627 :                                 switch (*c) {
      98             :                                         case '?':
      99           3 :                                                 c++;
     100             : #ifdef ZEND_WIN32
     101             :                                                 p[0] = '[';                     /* * => [^\\] on Win32 */
     102             :                                                 p[1] = '^';
     103             :                                                 p[2] = '\\';
     104             :                                                 p[3] = '\\';
     105             :                                                 p[4] = ']';
     106             :                                                 p += 5;
     107             : #else
     108           3 :                                                 p[0] = '[';                     /* * => [^/] on *nix */
     109           3 :                                                 p[1] = '^';
     110           3 :                                                 p[2] = '/';
     111           3 :                                                 p[3] = ']';
     112           3 :                                                 p += 4;
     113             : #endif
     114           3 :                                                 break;
     115             :                                         case '*':
     116           3 :                                                 c++;
     117           3 :                                                 if (*c == '*') {
     118           0 :                                                         c++;
     119           0 :                                                         p[0] = '.';                     /* ** => .* */
     120           0 :                                                         p[1] = '*';
     121           0 :                                                         p += 2;
     122             :                                                 } else {
     123             : #ifdef ZEND_WIN32
     124             :                                                         p[0] = '[';                     /* * => [^\\]* on Win32 */
     125             :                                                         p[1] = '^';
     126             :                                                         p[2] = '\\';
     127             :                                                         p[3] = '\\';
     128             :                                                         p[4] = ']';
     129             :                                                         p[5] = '*';
     130             :                                                         p += 6;
     131             : #else
     132           3 :                                                         p[0] = '[';                     /* * => [^/]* on *nix */
     133           3 :                                                         p[1] = '^';
     134           3 :                                                         p[2] = '/';
     135           3 :                                                         p[3] = ']';
     136           3 :                                                         p[4] = '*';
     137           3 :                                                         p += 5;
     138             : #endif
     139             :                                                 }
     140           3 :                                                 break;
     141             :                                         case '^':
     142             :                                         case '.':
     143             :                                         case '[':
     144             :                                         case ']':
     145             :                                         case '$':
     146             :                                         case '(':
     147             :                                         case ')':
     148             :                                         case '|':
     149             :                                         case '+':
     150             :                                         case '{':
     151             :                                         case '}':
     152             :                                         case '\\':
     153           9 :                                                 *p++ = '\\';
     154             :                                                 /* break missing intentionally */
     155             :                                         default:
     156         621 :                                                 *p++ = *c++;
     157             :                                 }
     158             :                         }
     159             :                 }
     160             : 
     161          33 :                 if (*c || i == blacklist->pos - 1) {
     162           6 :                         if (*c) {
     163           0 :                                 if (!backtrack) {
     164           0 :                                         zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
     165             :                                 }
     166           0 :                                 p = backtrack;
     167             :                         } else {
     168           6 :                                 i++;
     169             :                         }
     170           6 :                         *p++ = ')';
     171           6 :                         *p++ = '\0';
     172             : 
     173           6 :                         it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
     174           6 :                         if (!it) {
     175           0 :                                 zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
     176           0 :                                 return;
     177             :                         }
     178           6 :                         it->next = NULL;
     179             : 
     180           6 :                         if ((it->re = pcre_compile(regexp, PCRE_NO_AUTO_CAPTURE, &pcre_error, &pcre_error_offset, 0)) == NULL) {
     181           0 :                                 free(it);
     182           0 :                                 blacklist_report_regexp_error(pcre_error, pcre_error_offset);
     183           0 :                                 return;
     184             :                         }
     185             :                         /* prepare for the next iteration */
     186           6 :                         p = regexp + 2;
     187           6 :                         *regexp_list_it = it;
     188           6 :                         regexp_list_it = &it->next;
     189             :                 } else {
     190          21 :                         backtrack = p;
     191          21 :                         *p++ = '|';
     192          21 :                         i++;
     193             :                 }
     194             :         }
     195             : }
     196             : 
     197       23795 : void zend_accel_blacklist_shutdown(zend_blacklist *blacklist)
     198             : {
     199       23795 :         zend_blacklist_entry *p = blacklist->entries, *end = blacklist->entries + blacklist->pos;
     200             : 
     201       47611 :         while (p<end) {
     202          21 :                 free(p->path);
     203          21 :                 p++;
     204             :         }
     205       23795 :         free(blacklist->entries);
     206       23795 :         blacklist->entries = NULL;
     207       23795 :         if (blacklist->regexp_list) {
     208           3 :                 zend_regexp_list *temp, *it = blacklist->regexp_list;
     209           9 :                 while (it) {
     210           3 :                         pcre_free(it->re);
     211           3 :                         temp = it;
     212           3 :                         it = it->next;
     213           3 :                         free(temp);
     214             :                 }
     215             :         }
     216       23795 : }
     217             : 
     218          21 : static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist)
     219             : {
     220          21 :         if (blacklist->pos == blacklist->size) {
     221           0 :                 blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE;
     222           0 :                 blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size);
     223             :         }
     224          21 : }
     225             : 
     226             : #ifdef HAVE_GLOB
     227           6 : static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filename)
     228             : #else
     229             : void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
     230             : #endif
     231             : {
     232           6 :         char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL;
     233             :         FILE *fp;
     234             :         int path_length, blacklist_path_length;
     235             : 
     236           6 :         if ((fp = fopen(filename, "r")) == NULL) {
     237           0 :                 zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename);
     238           0 :                 return;
     239             :         }
     240             : 
     241           6 :         zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file:  '%s'", filename);
     242             : 
     243           6 :         if (VCWD_REALPATH(filename, buf)) {
     244           6 :                 blacklist_path_length = zend_dirname(buf, strlen(buf));
     245           6 :                 blacklist_path = zend_strndup(buf, blacklist_path_length);
     246             :         }
     247             : 
     248           6 :         memset(buf, 0, sizeof(buf));
     249           6 :         memset(real_path, 0, sizeof(real_path));
     250             : 
     251          45 :         while (fgets(buf, MAXPATHLEN, fp) != NULL) {
     252             :                 char *path_dup, *pbuf;
     253          33 :                 path_length = strlen(buf);
     254          33 :                 if (path_length > 0 && buf[path_length - 1] == '\n') {
     255          30 :                         buf[--path_length] = 0;
     256          30 :                         if (path_length > 0 && buf[path_length - 1] == '\r') {
     257           0 :                                 buf[--path_length] = 0;
     258             :                         }
     259             :                 }
     260             : 
     261             :                 /* Strip ctrl-m prefix */
     262          33 :                 pbuf = &buf[0];
     263          66 :                 while (*pbuf == '\r') {
     264           0 :                         *pbuf++ = 0;
     265           0 :                         path_length--;
     266             :                 }
     267             : 
     268             :                 /* strip \" */
     269          33 :                 if (pbuf[0] == '\"' && pbuf[path_length - 1]== '\"') {
     270           3 :                         *pbuf++ = 0;
     271           3 :                         path_length -= 2;
     272             :                 }
     273             : 
     274          33 :                 if (path_length == 0) {
     275           3 :                         continue;
     276             :                 }
     277             : 
     278             :                 /* skip comments */
     279          30 :                 if (pbuf[0]==';') {
     280           9 :                         continue;
     281             :                 }
     282             : 
     283          21 :                 path_dup = zend_strndup(pbuf, path_length);
     284          21 :                 if (blacklist_path) {
     285          21 :                         expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length);
     286             :                 } else {
     287           0 :                         expand_filepath(path_dup, real_path);
     288             :                 }
     289          21 :                 path_length = strlen(real_path);
     290             : 
     291          21 :                 free(path_dup);
     292             : 
     293          21 :                 zend_accel_blacklist_allocate(blacklist);
     294          21 :                 blacklist->entries[blacklist->pos].path_length = path_length;
     295          21 :                 blacklist->entries[blacklist->pos].path = (char *)malloc(path_length + 1);
     296          21 :                 if (!blacklist->entries[blacklist->pos].path) {
     297           0 :                         zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
     298           0 :                         fclose(fp);
     299           0 :                         return;
     300             :                 }
     301          21 :                 blacklist->entries[blacklist->pos].id = blacklist->pos;
     302          21 :                 memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length + 1);
     303          21 :                 blacklist->pos++;
     304             :         }
     305           6 :         fclose(fp);
     306           6 :         if (blacklist_path) {
     307           6 :                 free(blacklist_path);
     308             :         }
     309           6 :         zend_accel_blacklist_update_regexp(blacklist);
     310             : }
     311             : 
     312             : #ifdef HAVE_GLOB
     313           3 : void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
     314             : {
     315             :         glob_t globbuf;
     316             :         int    ret;
     317             :         unsigned int i;
     318             : 
     319           3 :         memset(&globbuf, 0, sizeof(glob_t));
     320             : 
     321           3 :         ret = glob(filename, 0, NULL, &globbuf);
     322             : #ifdef GLOB_NOMATCH
     323           3 :         if (ret == GLOB_NOMATCH || !globbuf.gl_pathc) {
     324             : #else
     325             :         if (!globbuf.gl_pathc) {
     326             : #endif
     327           0 :                 zend_accel_error(ACCEL_LOG_WARNING, "No blacklist file found matching: %s\n", filename);
     328             :         } else {
     329           9 :                 for(i=0 ; i<globbuf.gl_pathc; i++) {
     330           6 :                         zend_accel_blacklist_loadone(blacklist, globbuf.gl_pathv[i]);
     331             :                 }
     332           3 :                 globfree(&globbuf);
     333             :         }
     334           3 : }
     335             : #endif
     336             : 
     337         595 : zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path)
     338             : {
     339         595 :         int ret = 0;
     340         595 :         zend_regexp_list *regexp_list_it = blacklist->regexp_list;
     341             : 
     342         595 :         if (regexp_list_it == NULL) {
     343         589 :                 return 0;
     344             :         }
     345          17 :         while (regexp_list_it != NULL) {
     346           6 :                 if (pcre_exec(regexp_list_it->re, NULL, verify_path, strlen(verify_path), 0, 0, NULL, 0) >= 0) {
     347           1 :                         ret = 1;
     348           1 :                         break;
     349             :                 }
     350           5 :                 regexp_list_it = regexp_list_it->next;
     351             :         }
     352           6 :         return ret;
     353             : }
     354             : 
     355           2 : void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument)
     356             : {
     357             :         int i;
     358             : 
     359           9 :         for (i = 0; i < blacklist->pos; i++) {
     360           7 :                 func(&blacklist->entries[i], argument);
     361             :         }
     362           2 : }

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:01 +0000 (3 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.