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_util_funcs.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 285 516 55.2 %
Date: 2015-04-14 Functions: 20 22 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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 "zend_API.h"
      23             : #include "zend_constants.h"
      24             : #include "zend_accelerator_util_funcs.h"
      25             : #include "zend_persist.h"
      26             : #include "zend_shared_alloc.h"
      27             : 
      28             : #define ZEND_PROTECTED_REFCOUNT (1<<30)
      29             : 
      30             : static uint32_t zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
      31             : 
      32             : #if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
      33             : /* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
      34             : # define accel_xlat_set(old, new)       zend_hash_index_update_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
      35             : # define accel_xlat_get(old)            zend_hash_index_find_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old))
      36             : #else
      37             : # define accel_xlat_set(old, new)       (zend_hash_str_add_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))
      38             : # define accel_xlat_get(old, new)       ((new) = zend_hash_str_find_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new)))
      39             : #endif
      40             : 
      41             : #define ARENA_REALLOC(ptr) \
      42             :         (void*)(((char*)(ptr)) + ((char*)ZCG(arena_mem) - (char*)ZCG(current_persistent_script)->arena_mem))
      43             : 
      44             : typedef int (*id_function_t)(void *, void *);
      45             : typedef void (*unique_copy_ctor_func_t)(void *pElement);
      46             : 
      47             : static const uint32_t uninitialized_bucket = {INVALID_IDX};
      48             : 
      49             : static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
      50             : static zend_ast *zend_ast_clone(zend_ast *ast);
      51             : 
      52           4 : static void zend_accel_destroy_zend_function(zval *zv)
      53             : {
      54           4 :         zend_function *function = Z_PTR_P(zv);
      55             : 
      56           4 :         if (function->type == ZEND_USER_FUNCTION) {
      57           4 :                 if (function->op_array.static_variables) {
      58             : 
      59           0 :                         FREE_HASHTABLE(function->op_array.static_variables);
      60           0 :                         function->op_array.static_variables = NULL;
      61             :                 }
      62             :         }
      63             : 
      64           4 :         destroy_zend_function(function);
      65           4 : }
      66             : 
      67           4 : static void zend_accel_destroy_zend_class(zval *zv)
      68             : {
      69           4 :         zend_class_entry *ce = Z_PTR_P(zv);
      70           4 :         ce->function_table.pDestructor = zend_accel_destroy_zend_function;
      71           4 :         destroy_zend_class(zv);
      72           4 : }
      73             : 
      74         428 : zend_persistent_script* create_persistent_script(void)
      75             : {
      76         428 :         zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
      77         428 :         memset(persistent_script, 0, sizeof(zend_persistent_script));
      78             : 
      79         428 :         zend_hash_init(&persistent_script->function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
      80             :         /* class_table is usually destroyed by free_persistent_script() that
      81             :          * overrides destructor. ZEND_CLASS_DTOR may be used by standard
      82             :          * PHP compiler
      83             :          */
      84         428 :         zend_hash_init(&persistent_script->class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
      85             : 
      86         428 :         return persistent_script;
      87             : }
      88             : 
      89           3 : void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
      90             : {
      91           3 :         if (destroy_elements) {
      92           3 :                 persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
      93           3 :                 persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class;
      94             :         } else {
      95           0 :                 persistent_script->function_table.pDestructor = NULL;
      96           0 :                 persistent_script->class_table.pDestructor = NULL;
      97             :         }
      98             : 
      99           3 :         zend_hash_destroy(&persistent_script->function_table);
     100           3 :         zend_hash_destroy(&persistent_script->class_table);
     101             : 
     102           3 :         if (persistent_script->full_path) {
     103           0 :                 efree(persistent_script->full_path);
     104             :         }
     105             : 
     106           3 :         efree(persistent_script);
     107           3 : }
     108             : 
     109        6388 : static int is_not_internal_function(zval *zv)
     110             : {
     111        6388 :         zend_function *function = Z_PTR_P(zv);
     112        6388 :         return(function->type != ZEND_INTERNAL_FUNCTION);
     113             : }
     114             : 
     115           3 : void zend_accel_free_user_functions(HashTable *ht)
     116             : {
     117           3 :         dtor_func_t orig_dtor = ht->pDestructor;
     118             : 
     119           3 :         ht->pDestructor = NULL;
     120           3 :         zend_hash_apply(ht, (apply_func_t) is_not_internal_function);
     121           3 :         ht->pDestructor = orig_dtor;
     122           3 : }
     123             : 
     124      906104 : static int move_user_function(zval *zv, int num_args, va_list args, zend_hash_key *hash_key)
     125             : {
     126      906104 :         zend_function *function = Z_PTR_P(zv);
     127      906104 :         HashTable *function_table = va_arg(args, HashTable *);
     128             :         (void)num_args; /* keep the compiler happy */
     129             : 
     130      906104 :         if (function->type == ZEND_USER_FUNCTION) {
     131          24 :                 zend_hash_update_ptr(function_table, hash_key->key, function);
     132          24 :                 return 1;
     133             :         } else {
     134      906080 :                 return 0;
     135             :         }
     136             : }
     137             : 
     138         425 : void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
     139             : {
     140         425 :         dtor_func_t orig_dtor = src->pDestructor;
     141             : 
     142         425 :         src->pDestructor = NULL;
     143         425 :         zend_hash_apply_with_arguments(src, (apply_func_args_t)move_user_function, 1, dst);
     144         425 :         src->pDestructor = orig_dtor;
     145         425 : }
     146             : 
     147    44159592 : static int copy_internal_function(zval *zv, HashTable *function_table)
     148             : {
     149    44159592 :         zend_internal_function *function = Z_PTR_P(zv);
     150    44159592 :         if (function->type == ZEND_INTERNAL_FUNCTION) {
     151    44159592 :                 zend_hash_update_mem(function_table, function->function_name, function, sizeof(zend_internal_function));
     152             :         }
     153    44159592 :         return 0;
     154             : }
     155             : 
     156       20751 : void zend_accel_copy_internal_functions(void)
     157             : {
     158       20751 :         zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table));
     159       20751 :         ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
     160       20751 : }
     161             : 
     162           2 : static void zend_destroy_property_info(zval *zv)
     163             : {
     164           2 :         zend_property_info *property_info = Z_PTR_P(zv);
     165             : 
     166           2 :         zend_string_release(property_info->name);
     167           2 :         if (property_info->doc_comment) {
     168           0 :                 zend_string_release(property_info->doc_comment);
     169             :         }
     170           2 : }
     171             : 
     172             : static zend_always_inline zend_string *zend_clone_str(zend_string *str)
     173             : {
     174             :         zend_string *ret;
     175             : 
     176          39 :         if (EXPECTED(IS_INTERNED(str))) {
     177          39 :                 ret = str;
     178           0 :         } else if (GC_REFCOUNT(str) <= 1 || (ret = accel_xlat_get(str)) == NULL) {
     179           0 :                 ret = zend_string_dup(str, 0);
     180           0 :                 GC_FLAGS(ret) = GC_FLAGS(str);
     181           0 :                 if (GC_REFCOUNT(str) > 1) {
     182           0 :                         accel_xlat_set(str, ret);
     183             :                 }
     184             :         } else {
     185           0 :                 GC_REFCOUNT(ret)++;
     186             :         }
     187          39 :         return ret;
     188             : }
     189             : 
     190          20 : static inline void zend_clone_zval(zval *src, int bind)
     191             : {
     192             :         void *ptr;
     193             : 
     194          20 :         if (Z_IMMUTABLE_P(src)) {
     195          12 :                 return;
     196             :         }
     197             : 
     198           8 :         switch (Z_TYPE_P(src)) {
     199             :                 case IS_STRING:
     200             :             case IS_CONSTANT:
     201           2 :                         Z_STR_P(src) = zend_clone_str(Z_STR_P(src));
     202           1 :                         break;
     203             :                 case IS_ARRAY:
     204           0 :                         if (Z_ARR_P(src) != &EG(symbol_table)) {
     205           0 :                         if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_ARR_P(src))) != NULL) {
     206           0 :                                 Z_ARR_P(src) = ptr;
     207             :                                 } else {
     208           0 :                                         zend_array *old = Z_ARR_P(src);
     209             : 
     210           0 :                                         Z_ARR_P(src) = emalloc(sizeof(zend_array));
     211           0 :                                         Z_ARR_P(src)->gc = old->gc;
     212           0 :                                 if (bind && Z_REFCOUNT_P(src) > 1) {
     213           0 :                                                 accel_xlat_set(old, Z_ARR_P(src));
     214             :                                         }
     215           0 :                                         zend_hash_clone_zval(Z_ARRVAL_P(src), old, 0);
     216             :                                 }
     217             :                         }
     218           0 :                         break;
     219             :             case IS_REFERENCE:
     220           0 :                 if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_REF_P(src))) != NULL) {
     221           0 :                         Z_REF_P(src) = ptr;
     222             :                         } else {
     223           0 :                                 zend_reference *old = Z_REF_P(src);
     224           0 :                                 ZVAL_NEW_REF(src, &old->val);
     225           0 :                                 Z_REF_P(src)->gc = old->gc;
     226           0 :                         if (bind && Z_REFCOUNT_P(src) > 1) {
     227           0 :                                         accel_xlat_set(old, Z_REF_P(src));
     228             :                                 }
     229           0 :                                 zend_clone_zval(Z_REFVAL_P(src), bind);
     230             :                         }
     231           0 :                 break;
     232             :             case IS_CONSTANT_AST:
     233           0 :                 if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
     234           0 :                         Z_AST_P(src) = ptr;
     235             :                         } else {
     236           0 :                                 zend_ast_ref *old = Z_AST_P(src);
     237             : 
     238           0 :                         ZVAL_NEW_AST(src, old->ast);
     239           0 :                                 Z_AST_P(src)->gc = old->gc;
     240           0 :                         if (bind && Z_REFCOUNT_P(src) > 1) {
     241           0 :                                         accel_xlat_set(old, Z_AST_P(src));
     242             :                                 }
     243           0 :                         Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
     244             :                         }
     245             :                 break;
     246             :         }
     247             : }
     248             : 
     249           0 : static zend_ast *zend_ast_clone(zend_ast *ast)
     250             : {
     251             :         uint32_t i;
     252             : 
     253           0 :         if (ast->kind == ZEND_AST_ZVAL) {
     254           0 :                 zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval));
     255           0 :                 copy->kind = ZEND_AST_ZVAL;
     256           0 :                 copy->attr = ast->attr;
     257           0 :                 ZVAL_COPY_VALUE(&copy->val, zend_ast_get_zval(ast));
     258           0 :                 zend_clone_zval(&copy->val, 0);
     259           0 :                 return (zend_ast *) copy;
     260           0 :         } else if (zend_ast_is_list(ast)) {
     261           0 :                 zend_ast_list *list = zend_ast_get_list(ast);
     262           0 :                 zend_ast_list *copy = emalloc(
     263             :                         sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
     264           0 :                 copy->kind = list->kind;
     265           0 :                 copy->attr = list->attr;
     266           0 :                 copy->children = list->children;
     267           0 :                 for (i = 0; i < list->children; i++) {
     268           0 :                         if (list->child[i]) {
     269           0 :                                 copy->child[i] = zend_ast_clone(list->child[i]);
     270             :                         } else {
     271           0 :                                 copy->child[i] = NULL;
     272             :                         }
     273             :                 }
     274           0 :                 return (zend_ast *) copy;
     275             :         } else {
     276           0 :                 uint32_t children = zend_ast_get_num_children(ast);
     277           0 :                 zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
     278           0 :                 copy->kind = ast->kind;
     279           0 :                 copy->attr = ast->attr;
     280           0 :                 for (i = 0; i < children; i++) {
     281           0 :                         if (ast->child[i]) {
     282           0 :                                 copy->child[i] = zend_ast_clone(ast->child[i]);
     283             :                         } else {
     284           0 :                                 copy->child[i] = NULL;
     285             :                         }
     286             :                 }
     287           0 :                 return copy;
     288             :         }
     289             : }
     290             : 
     291          20 : static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
     292             : {
     293             :         uint idx;
     294             :         Bucket *p, *q, *r;
     295             :         zend_ulong nIndex;
     296             : 
     297          20 :         ht->nTableSize = source->nTableSize;
     298          20 :         ht->nTableMask = source->nTableMask;
     299          20 :         ht->nNumUsed = 0;
     300          20 :         ht->nNumOfElements = source->nNumOfElements;
     301          20 :         ht->nNextFreeElement = source->nNextFreeElement;
     302          20 :         ht->pDestructor = ZVAL_PTR_DTOR;
     303          20 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
     304          20 :         ht->arData = NULL;
     305          20 :         ht->arHash = NULL;
     306          20 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     307             : 
     308          20 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     309           6 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     310           6 :                 return;
     311             :         }
     312             : 
     313          14 :         if (source->u.flags & HASH_FLAG_PACKED) {
     314           0 :                 ht->u.flags |= HASH_FLAG_PACKED;
     315           0 :                 ht->arData = (Bucket *) emalloc(ht->nTableSize * sizeof(Bucket));
     316           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     317             : 
     318           0 :                 for (idx = 0; idx < source->nNumUsed; idx++) {
     319           0 :                         p = source->arData + idx;
     320           0 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
     321           0 :                         nIndex = p->h & ht->nTableMask;
     322             : 
     323           0 :                         r = ht->arData + ht->nNumUsed;
     324           0 :                         q = ht->arData + p->h;
     325           0 :                         while (r != q) {
     326           0 :                                 ZVAL_UNDEF(&r->val);
     327           0 :                                 r++;
     328             :                         }
     329           0 :                         ht->nNumUsed = p->h + 1;
     330             : 
     331             :                         /* Initialize key */
     332           0 :                         q->h = p->h;
     333           0 :                         q->key = NULL;
     334             : 
     335             :                         /* Copy data */
     336           0 :                         ZVAL_COPY_VALUE(&q->val, &p->val);
     337           0 :                         zend_clone_zval(&q->val, bind);
     338             :                 }
     339             :         } else {
     340          14 :                 ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
     341          14 :                 ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     342          14 :                 memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
     343             : 
     344          32 :                 for (idx = 0; idx < source->nNumUsed; idx++) {
     345          18 :                         p = source->arData + idx;
     346          36 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
     347          18 :                         nIndex = p->h & ht->nTableMask;
     348             : 
     349             :                         /* Insert into hash collision list */
     350          18 :                         q = ht->arData + ht->nNumUsed;
     351          18 :                         Z_NEXT(q->val) = ht->arHash[nIndex];
     352          18 :                         ht->arHash[nIndex] = ht->nNumUsed++;
     353             : 
     354             :                         /* Initialize key */
     355          18 :                         q->h = p->h;
     356          18 :                         if (!p->key) {
     357           0 :                                 q->key = NULL;
     358             :                         } else {
     359          36 :                                 q->key = zend_clone_str(p->key);
     360             :                         }
     361             : 
     362             :                         /* Copy data */
     363          18 :                         ZVAL_COPY_VALUE(&q->val, &p->val);
     364          18 :                         zend_clone_zval(&q->val, bind);
     365             :                 }
     366             :         }
     367             : }
     368             : 
     369             : /* protects reference count, creates copy of statics */
     370             : static zend_always_inline void zend_prepare_function_for_execution(zend_op_array *op_array)
     371             : {
     372             :         /* protect reference count */
     373         458 :         op_array->refcount = &zend_accel_refcount;
     374         458 :         (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
     375             : 
     376             :         /* copy statics */
     377         458 :         if (UNEXPECTED(op_array->static_variables)) {
     378          13 :                 HashTable *shared_statics = op_array->static_variables;
     379             : 
     380          13 :                 ALLOC_HASHTABLE(op_array->static_variables);
     381          13 :                 GC_REFCOUNT(op_array->static_variables) = 1;
     382          13 :                 GC_TYPE(op_array->static_variables) = IS_ARRAY;
     383          13 :                 zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
     384             :         }
     385             : }
     386             : 
     387           7 : static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
     388             : {
     389             :         uint idx;
     390             :         Bucket *p, *q;
     391             :         zend_ulong nIndex;
     392             :         zend_class_entry *new_ce;
     393             :         zend_function *new_prototype;
     394             :         zend_op_array *new_entry;
     395             : 
     396           7 :         ht->nTableSize = source->nTableSize;
     397           7 :         ht->nTableMask = source->nTableMask;
     398           7 :         ht->nNumUsed = 0;
     399           7 :         ht->nNumOfElements = source->nNumOfElements;
     400           7 :         ht->nNextFreeElement = source->nNextFreeElement;
     401           7 :         ht->pDestructor = ZEND_FUNCTION_DTOR;
     402           7 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     403           7 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     404             : 
     405           7 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     406           2 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     407           2 :                 return;
     408             :         }
     409             : 
     410             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     411           5 :         ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
     412           5 :         ht->arHash = (uint32_t *)(ht->arData + ht->nTableSize);
     413           5 :         memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
     414             : 
     415          14 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     416           9 :                 p = source->arData + idx;
     417          18 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     418             : 
     419           9 :                 nIndex = p->h & ht->nTableMask;
     420             : 
     421             :                 /* Insert into hash collision list */
     422           9 :                 q = ht->arData + ht->nNumUsed;
     423           9 :                 Z_NEXT(q->val) = ht->arHash[nIndex];
     424           9 :                 ht->arHash[nIndex] = ht->nNumUsed++;
     425             : 
     426             :                 /* Initialize key */
     427           9 :                 q->h = p->h;
     428             :                 ZEND_ASSERT(p->key != NULL);
     429          18 :                 q->key = zend_clone_str(p->key);
     430             : 
     431             :                 /* Copy data */
     432           9 :                 ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
     433           9 :                 new_entry = (zend_op_array*)Z_PTR(q->val);
     434             : 
     435             :                 /* Copy constructor */
     436             :                 /* we use refcount to show that op_array is referenced from several places */
     437           9 :                 if (new_entry->refcount != NULL) {
     438           2 :                         accel_xlat_set(Z_PTR(p->val), new_entry);
     439             :                 }
     440             : 
     441             :                 zend_prepare_function_for_execution(new_entry);
     442             : 
     443           9 :                 if (old_ce == new_entry->scope) {
     444           9 :                         new_entry->scope = ce;
     445             :                 } else {
     446           0 :                         if ((new_ce = accel_xlat_get(new_entry->scope)) != NULL) {
     447           0 :                                 new_entry->scope = new_ce;
     448             :                         } else {
     449           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
     450             :                         }
     451             :                 }
     452             : 
     453             :                 /* update prototype */
     454           9 :                 if (new_entry->prototype) {
     455           4 :                         if ((new_prototype = accel_xlat_get(new_entry->prototype)) != NULL) {
     456           2 :                                 new_entry->prototype = new_prototype;
     457             :                         } else {
     458           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
     459             :                         }
     460             :                 }
     461             :         }
     462             : }
     463             : 
     464           7 : static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
     465             : {
     466             :         uint idx;
     467             :         Bucket *p, *q;
     468             :         zend_ulong nIndex;
     469             :         zend_class_entry *new_ce;
     470             :         zend_property_info *prop_info;
     471             : 
     472           7 :         ht->nTableSize = source->nTableSize;
     473           7 :         ht->nTableMask = source->nTableMask;
     474           7 :         ht->nNumUsed = 0;
     475           7 :         ht->nNumOfElements = source->nNumOfElements;
     476           7 :         ht->nNextFreeElement = source->nNextFreeElement;
     477           7 :         ht->pDestructor = zend_destroy_property_info;
     478           7 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     479           7 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     480             : 
     481           7 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     482           6 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     483           6 :                 return;
     484             :         }
     485             : 
     486             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     487           1 :         ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
     488           1 :         ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     489           1 :         memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
     490             : 
     491           3 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     492           2 :                 p = source->arData + idx;
     493           4 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     494             : 
     495           2 :                 nIndex = p->h & ht->nTableMask;
     496             : 
     497             :                 /* Insert into hash collision list */
     498           2 :                 q = ht->arData + ht->nNumUsed;
     499           2 :                 Z_NEXT(q->val) = ht->arHash[nIndex];
     500           2 :                 ht->arHash[nIndex] = ht->nNumUsed++;
     501             : 
     502             :                 /* Initialize key */
     503           2 :                 q->h = p->h;
     504             :                 ZEND_ASSERT(p->key != NULL);
     505           4 :                 q->key = zend_clone_str(p->key);
     506             : 
     507             :                 /* Copy data */
     508           2 :                 ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
     509           2 :                 prop_info = Z_PTR(q->val);
     510             : 
     511             :                 /* Copy constructor */
     512           4 :                 prop_info->name = zend_clone_str(prop_info->name);
     513           2 :                 if (prop_info->doc_comment) {
     514           0 :                         if (ZCG(accel_directives).load_comments) {
     515           0 :                                 prop_info->doc_comment = zend_string_dup(prop_info->doc_comment, 0);
     516             :                         } else {
     517           0 :                                 prop_info->doc_comment = NULL;
     518             :                         }
     519             :                 }
     520           2 :                 if (prop_info->ce == old_ce) {
     521           2 :                         prop_info->ce = ce;
     522           0 :                 } else if ((new_ce = accel_xlat_get(prop_info->ce)) != NULL) {
     523           0 :                         prop_info->ce = new_ce;
     524             :                 } else {
     525           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name->val, prop_info->name->val);
     526             :                 }
     527             :         }
     528             : }
     529             : 
     530             : #define zend_update_inherited_handler(handler) \
     531             : { \
     532             :         if (ce->handler != NULL) { \
     533             :                 if ((new_func = accel_xlat_get(ce->handler)) != NULL) { \
     534             :                         ce->handler = new_func; \
     535             :                 } else { \
     536             :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name->val); \
     537             :                 } \
     538             :         } \
     539             : }
     540             : 
     541             : /* Protects class' refcount, copies default properties, functions and class name */
     542           7 : static void zend_class_copy_ctor(zend_class_entry **pce)
     543             : {
     544           7 :         zend_class_entry *ce = *pce;
     545           7 :         zend_class_entry *old_ce = ce;
     546             :         zend_class_entry *new_ce;
     547             :         zend_function *new_func;
     548             : 
     549           7 :         *pce = ce = ARENA_REALLOC(old_ce);
     550           7 :         ce->refcount = 1;
     551             : 
     552           7 :         if (old_ce->refcount != 1) {
     553             :                 /* this class is not used as a parent for any other classes */
     554           3 :                 accel_xlat_set(old_ce, ce);
     555             :         }
     556             : 
     557           7 :         if (old_ce->default_properties_table) {
     558             :                 int i;
     559             : 
     560           0 :                 ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
     561           0 :                 for (i = 0; i < old_ce->default_properties_count; i++) {
     562           0 :                         ZVAL_COPY_VALUE(&ce->default_properties_table[i], &old_ce->default_properties_table[i]);
     563           0 :                         zend_clone_zval(&ce->default_properties_table[i], 1);
     564             :                 }
     565             :         }
     566             : 
     567           7 :         zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce);
     568             : 
     569             :         /* static members */
     570           7 :         if (old_ce->default_static_members_table) {
     571             :                 int i;
     572             : 
     573           1 :                 ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
     574           3 :                 for (i = 0; i < old_ce->default_static_members_count; i++) {
     575           2 :                         ZVAL_COPY_VALUE(&ce->default_static_members_table[i], &old_ce->default_static_members_table[i]);
     576           2 :                         zend_clone_zval(&ce->default_static_members_table[i], 1);
     577             :                 }
     578             :         }
     579           7 :         ce->static_members_table = ce->default_static_members_table;
     580             : 
     581             :         /* properties_info */
     582           7 :         zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce);
     583             : 
     584             :         /* constants table */
     585           7 :         zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
     586           7 :         ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     587             : 
     588          14 :         ce->name = zend_clone_str(ce->name);
     589             : 
     590             :         /* interfaces aren't really implemented, so we create a new table */
     591           7 :         if (ce->num_interfaces) {
     592           0 :                 ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
     593           0 :                 memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
     594             :         } else {
     595           7 :                 ce->interfaces = NULL;
     596             :         }
     597           7 :         if (ZEND_CE_DOC_COMMENT(ce)) {
     598           0 :                 if (ZCG(accel_directives).load_comments) {
     599           0 :                         ZEND_CE_DOC_COMMENT(ce) = zend_string_dup(ZEND_CE_DOC_COMMENT(ce), 0);
     600             :                 } else {
     601           0 :                         ZEND_CE_DOC_COMMENT(ce) =  NULL;
     602             :                 }
     603             :         }
     604             : 
     605           7 :         if (ce->parent) {
     606           6 :                 if ((new_ce = accel_xlat_get(ce->parent)) != NULL) {
     607           3 :                         ce->parent = new_ce;
     608             :                 } else {
     609           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name->val);
     610             :                 }
     611             :         }
     612             : 
     613           7 :         zend_update_inherited_handler(constructor);
     614           7 :         zend_update_inherited_handler(destructor);
     615           7 :         zend_update_inherited_handler(clone);
     616           7 :         zend_update_inherited_handler(__get);
     617           7 :         zend_update_inherited_handler(__set);
     618           7 :         zend_update_inherited_handler(__call);
     619             : /* 5.1 stuff */
     620           7 :         zend_update_inherited_handler(serialize_func);
     621           7 :         zend_update_inherited_handler(unserialize_func);
     622           7 :         zend_update_inherited_handler(__isset);
     623           7 :         zend_update_inherited_handler(__unset);
     624             : /* 5.2 stuff */
     625           7 :         zend_update_inherited_handler(__tostring);
     626             : 
     627             : /* 5.3 stuff */
     628           7 :         zend_update_inherited_handler(__callstatic);
     629           7 :         zend_update_inherited_handler(__debugInfo);
     630             : 
     631             : /* 5.4 traits */
     632           7 :         if (ce->trait_aliases) {
     633             :                 zend_trait_alias **trait_aliases;
     634           0 :                 int i = 0;
     635             : 
     636           0 :                 while (ce->trait_aliases[i]) {
     637           0 :                         i++;
     638             :                 }
     639           0 :                 trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
     640           0 :                 i = 0;
     641           0 :                 while (ce->trait_aliases[i]) {
     642           0 :                         trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
     643           0 :                         memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
     644           0 :                         trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     645           0 :                         memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
     646           0 :                         if (trait_aliases[i]->trait_method) {
     647           0 :                                 if (trait_aliases[i]->trait_method->method_name) {
     648           0 :                                         trait_aliases[i]->trait_method->method_name =
     649           0 :                                                 zend_clone_str(trait_aliases[i]->trait_method->method_name);
     650             :                                 }
     651           0 :                                 if (trait_aliases[i]->trait_method->class_name) {
     652           0 :                                         trait_aliases[i]->trait_method->class_name =
     653           0 :                                                 zend_clone_str(trait_aliases[i]->trait_method->class_name);
     654             :                                 }
     655             :                         }
     656             : 
     657           0 :                         if (trait_aliases[i]->alias) {
     658           0 :                                 trait_aliases[i]->alias =
     659           0 :                                         zend_clone_str(trait_aliases[i]->alias);
     660             :                         }
     661           0 :                         i++;
     662             :                 }
     663           0 :                 trait_aliases[i] = NULL;
     664           0 :                 ce->trait_aliases = trait_aliases;
     665             :         }
     666             : 
     667           7 :         if (ce->trait_precedences) {
     668             :                 zend_trait_precedence **trait_precedences;
     669           0 :                 int i = 0;
     670             : 
     671           0 :                 while (ce->trait_precedences[i]) {
     672           0 :                         i++;
     673             :                 }
     674           0 :                 trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
     675           0 :                 i = 0;
     676           0 :                 while (ce->trait_precedences[i]) {
     677           0 :                         trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
     678           0 :                         memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
     679           0 :                         trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     680           0 :                         memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
     681             : 
     682           0 :                         trait_precedences[i]->trait_method->method_name =
     683           0 :                                 zend_clone_str(trait_precedences[i]->trait_method->method_name);
     684           0 :                         trait_precedences[i]->trait_method->class_name =
     685           0 :                                 zend_clone_str(trait_precedences[i]->trait_method->class_name);
     686             : 
     687           0 :                         if (trait_precedences[i]->exclude_from_classes) {
     688             :                                 zend_string **exclude_from_classes;
     689           0 :                                 int j = 0;
     690             : 
     691           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     692           0 :                                         j++;
     693             :                                 }
     694           0 :                                 exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1));
     695           0 :                                 j = 0;
     696           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     697           0 :                                         exclude_from_classes[j] =
     698           0 :                                                 zend_clone_str(trait_precedences[i]->exclude_from_classes[j].class_name);
     699           0 :                                         j++;
     700             :                                 }
     701           0 :                                 exclude_from_classes[j] = NULL;
     702           0 :                                 trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes;
     703             :                         }
     704           0 :                         i++;
     705             :                 }
     706           0 :                 trait_precedences[i] = NULL;
     707           0 :                 ce->trait_precedences = trait_precedences;
     708             :         }
     709           7 : }
     710             : 
     711           0 : static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
     712             : {
     713             :         zend_function *function1, *function2;
     714             :         uint idx;
     715             :         Bucket *p;
     716             :         zval *t;
     717             : 
     718           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     719           0 :                 p = source->arData + idx;
     720           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     721           0 :                 if (p->key) {
     722           0 :                         t = zend_hash_add(target, p->key, &p->val);
     723           0 :                         if (UNEXPECTED(t == NULL)) {
     724           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     725             :                                         /* Mangled key */
     726           0 :                                         t = zend_hash_update(target, p->key, &p->val);
     727             :                                 } else {
     728           0 :                                         t = zend_hash_find(target, p->key);
     729           0 :                                         goto failure;
     730             :                                 }
     731             :                         }
     732             :                 } else {
     733           0 :                     t = zend_hash_index_add(target, p->h, &p->val);
     734           0 :                         if (UNEXPECTED(t == NULL)) {
     735           0 :                                 t = zend_hash_index_find(target, p->h);
     736           0 :                                 goto failure;
     737             :                         }
     738             :                 }
     739             :         }
     740           0 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     741           0 :         return;
     742             : 
     743             : failure:
     744           0 :         function1 = Z_PTR(p->val);
     745           0 :         function2 = Z_PTR_P(t);
     746           0 :         CG(in_compilation) = 1;
     747           0 :         zend_set_compiled_filename(function1->op_array.filename);
     748           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     749           0 :         if (function2->type == ZEND_USER_FUNCTION
     750           0 :                 && function2->op_array.last > 0) {
     751           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     752           0 :                                    function1->common.function_name->val,
     753           0 :                                    function2->op_array.filename->val,
     754           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     755             :         } else {
     756           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     757             :         }
     758             : }
     759             : 
     760          24 : static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
     761             : {
     762             :         zend_function *function1, *function2;
     763             :         uint idx;
     764             :         Bucket *p;
     765             :         zval *t;
     766             : 
     767          48 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     768          24 :                 p = source->arData + idx;
     769          48 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     770          24 :                 if (p->key) {
     771          24 :                         t = zend_hash_add(target, p->key, &p->val);
     772          24 :                         if (UNEXPECTED(t == NULL)) {
     773           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     774             :                                         /* Mangled key */
     775           0 :                                         t = zend_hash_update(target, p->key, &p->val);
     776             :                                 } else {
     777           0 :                                         t = zend_hash_find(target, p->key);
     778           0 :                                         goto failure;
     779             :                                 }
     780             :                         }
     781             :                 } else {
     782           0 :                     t = zend_hash_index_add(target, p->h, &p->val);
     783           0 :                         if (UNEXPECTED(t == NULL)) {
     784           0 :                                 t = zend_hash_index_find(target, p->h);
     785           0 :                                 goto failure;
     786             :                         }
     787             :                 }
     788          24 :                 Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
     789          24 :                 zend_prepare_function_for_execution((zend_op_array*)Z_PTR_P(t));
     790             :         }
     791          24 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     792          24 :         return;
     793             : 
     794             : failure:
     795           0 :         function1 = Z_PTR(p->val);
     796           0 :         function2 = Z_PTR_P(t);
     797           0 :         CG(in_compilation) = 1;
     798           0 :         zend_set_compiled_filename(function1->op_array.filename);
     799           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     800           0 :         if (function2->type == ZEND_USER_FUNCTION
     801           0 :                 && function2->op_array.last > 0) {
     802           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     803           0 :                                    function1->common.function_name->val,
     804           0 :                                    function2->op_array.filename->val,
     805           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     806             :         } else {
     807           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     808             :         }
     809             : }
     810             : 
     811           4 : static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
     812             : {
     813             :         zend_class_entry *ce1;
     814             :         uint idx;
     815             :         Bucket *p;
     816             :         zval *t;
     817             : 
     818          18 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     819          14 :                 p = source->arData + idx;
     820          28 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     821           7 :                 if (p->key) {
     822           7 :                         t = zend_hash_add(target, p->key, &p->val);
     823           7 :                         if (UNEXPECTED(t == NULL)) {
     824           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     825             :                                         /* Mangled key - ignore and wait for runtime */
     826           0 :                                         continue;
     827           0 :                                 } else if (!ZCG(accel_directives).ignore_dups) {
     828           0 :                                         t = zend_hash_find(target, p->key);
     829           0 :                                         goto failure;
     830             :                                 }
     831             :                         }
     832             :                 } else {
     833           0 :                         t = zend_hash_index_add(target, p->h, &p->val);
     834           0 :                         if (UNEXPECTED(t == NULL)) {
     835           0 :                                 if (!ZCG(accel_directives).ignore_dups) {
     836           0 :                                         t = zend_hash_index_find(target,p->h);
     837           0 :                                         goto failure;
     838             :                                 }
     839             :                         }
     840             :                 }
     841           7 :                 if (pCopyConstructor) {
     842           7 :                         pCopyConstructor(&Z_PTR_P(t));
     843             :                 }
     844             :         }
     845           4 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     846           4 :         return;
     847             : 
     848             : failure:
     849           0 :         ce1 = Z_PTR(p->val);
     850           0 :         CG(in_compilation) = 1;
     851           0 :         zend_set_compiled_filename(ce1->info.user.filename);
     852           0 :         CG(zend_lineno) = ce1->info.user.line_start;
     853           0 :         zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
     854             : }
     855             : 
     856         425 : zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
     857             : {
     858             :         zend_op_array *op_array;
     859             : 
     860         425 :         op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
     861         425 :         *op_array = persistent_script->main_op_array;
     862             : 
     863         425 :         if (EXPECTED(from_shared_memory)) {
     864         425 :                 zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
     865             : 
     866         425 :                 ZCG(current_persistent_script) = persistent_script;
     867         425 :                 ZCG(arena_mem) = NULL;
     868         425 :                 if (EXPECTED(persistent_script->arena_size)) {
     869          56 :                         ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
     870          28 :                         memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
     871             :                 }
     872             : 
     873             :                 /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
     874         425 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     875           4 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
     876             :                 }
     877             :                 /* we must first to copy all classes and then prepare functions, since functions may try to bind
     878             :                    classes - which depend on pre-bind class entries existent in the class table */
     879         425 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     880          24 :                         zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
     881             :                 }
     882             : 
     883             :                 zend_prepare_function_for_execution(op_array);
     884             : 
     885             :                 /* Register __COMPILER_HALT_OFFSET__ constant */
     886         520 :                 if (persistent_script->compiler_halt_offset != 0 &&
     887          95 :                     persistent_script->full_path) {
     888             :                         zend_string *name;
     889          95 :                         char haltoff[] = "__COMPILER_HALT_OFFSET__";
     890             : 
     891          95 :                         name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, persistent_script->full_path->val, persistent_script->full_path->len, 0);
     892          95 :                         if (!zend_hash_exists(EG(zend_constants), name)) {
     893           0 :                                 zend_register_long_constant(name->val, name->len, persistent_script->compiler_halt_offset, CONST_CS, 0);
     894             :                         }
     895             :                         zend_string_release(name);
     896             :                 }
     897             : 
     898         425 :                 zend_hash_destroy(&ZCG(bind_hash));
     899         425 :                 ZCG(current_persistent_script) = NULL;
     900             :         } else /* if (!from_shared_memory) */ {
     901           0 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     902           0 :                         zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table);
     903             :                 }
     904           0 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     905           0 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL);
     906             :                 }
     907             :         }
     908             : 
     909         425 :         if (op_array->early_binding != (uint32_t)-1) {
     910           0 :                 zend_string *orig_compiled_filename = CG(compiled_filename);
     911           0 :                 CG(compiled_filename) = persistent_script->full_path;
     912           0 :                 zend_do_delayed_early_binding(op_array);
     913           0 :                 CG(compiled_filename) = orig_compiled_filename;
     914             :         }
     915             : 
     916         425 :         if (UNEXPECTED(!from_shared_memory)) {
     917           0 :                 free_persistent_script(persistent_script, 0); /* free only hashes */
     918             :         }
     919             : 
     920         425 :         return op_array;
     921             : }
     922             : 
     923             : /*
     924             :  * zend_adler32() is based on zlib implementation
     925             :  * Computes the Adler-32 checksum of a data stream
     926             :  *
     927             :  * Copyright (C) 1995-2005 Mark Adler
     928             :  * For conditions of distribution and use, see copyright notice in zlib.h
     929             :  *
     930             :  * Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
     931             :  *
     932             :  *  This software is provided 'as-is', without any express or implied
     933             :  *  warranty.  In no event will the authors be held liable for any damages
     934             :  *  arising from the use of this software.
     935             :  *
     936             :  *  Permission is granted to anyone to use this software for any purpose,
     937             :  *  including commercial applications, and to alter it and redistribute it
     938             :  *  freely, subject to the following restrictions:
     939             :  *
     940             :  *  1. The origin of this software must not be misrepresented; you must not
     941             :  *     claim that you wrote the original software. If you use this software
     942             :  *     in a product, an acknowledgment in the product documentation would be
     943             :  *     appreciated but is not required.
     944             :  *  2. Altered source versions must be plainly marked as such, and must not be
     945             :  *     misrepresented as being the original software.
     946             :  *  3. This notice may not be removed or altered from any source distribution.
     947             :  *
     948             :  */
     949             : 
     950             : #define ADLER32_BASE 65521 /* largest prime smaller than 65536 */
     951             : #define ADLER32_NMAX 5552
     952             : /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
     953             : 
     954             : #define ADLER32_DO1(buf)        {s1 += *(buf); s2 += s1;}
     955             : #define ADLER32_DO2(buf, i)     ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1);
     956             : #define ADLER32_DO4(buf, i)     ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2);
     957             : #define ADLER32_DO8(buf, i)     ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4);
     958             : #define ADLER32_DO16(buf)       ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8);
     959             : 
     960         850 : unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len)
     961             : {
     962         850 :         unsigned int s1 = checksum & 0xffff;
     963         850 :         unsigned int s2 = (checksum >> 16) & 0xffff;
     964             :         signed char *end;
     965             : 
     966        1706 :         while (len >= ADLER32_NMAX) {
     967           6 :                 len -= ADLER32_NMAX;
     968           6 :                 end = buf + ADLER32_NMAX;
     969             :                 do {
     970        2082 :                         ADLER32_DO16(buf);
     971        2082 :                         buf += 16;
     972        2082 :                 } while (buf != end);
     973           6 :                 s1 %= ADLER32_BASE;
     974           6 :                 s2 %= ADLER32_BASE;
     975             :         }
     976             : 
     977         850 :         if (len) {
     978         850 :                 if (len >= 16) {
     979         850 :                         end = buf + (len & 0xfff0);
     980         850 :                         len &= 0xf;
     981             :                         do {
     982       32423 :                                 ADLER32_DO16(buf);
     983       32423 :                                 buf += 16;
     984       32423 :                         } while (buf != end);
     985             :                 }
     986         850 :                 if (len) {
     987         628 :                         end = buf + len;
     988             :                         do {
     989        5024 :                                 ADLER32_DO1(buf);
     990        5024 :                                 buf++;
     991        5024 :                         } while (buf != end);
     992             :                 }
     993         850 :                 s1 %= ADLER32_BASE;
     994         850 :                 s2 %= ADLER32_BASE;
     995             :         }
     996             : 
     997         850 :         return (s2 << 16) | s1;
     998             : }

Generated by: LCOV version 1.10

Generated at Tue, 14 Apr 2015 11:48:46 +0000 (4 days ago)

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