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: 260 514 50.6 %
Date: 2015-01-26 Functions: 18 22 81.8 %
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           0 : static void zend_accel_destroy_zend_function(zval *zv)
      53             : {
      54           0 :         zend_function *function = Z_PTR_P(zv);
      55             : 
      56           0 :         if (function->type == ZEND_USER_FUNCTION) {
      57           0 :                 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           0 :         destroy_zend_function(function);
      65           0 : }
      66             : 
      67           0 : static void zend_accel_destroy_zend_class(zval *zv)
      68             : {
      69           0 :         zend_class_entry *ce = Z_PTR_P(zv);
      70           0 :         ce->function_table.pDestructor = zend_accel_destroy_zend_function;
      71           0 :         destroy_zend_class(zv);
      72           0 : }
      73             : 
      74         423 : zend_persistent_script* create_persistent_script(void)
      75             : {
      76         423 :         zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
      77         423 :         memset(persistent_script, 0, sizeof(zend_persistent_script));
      78             : 
      79         423 :         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         423 :         zend_hash_init(&persistent_script->class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
      85             : 
      86         423 :         return persistent_script;
      87             : }
      88             : 
      89           1 : void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
      90             : {
      91           1 :         if (destroy_elements) {
      92           1 :                 persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
      93           1 :                 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           1 :         zend_hash_destroy(&persistent_script->function_table);
     100           1 :         zend_hash_destroy(&persistent_script->class_table);
     101             : 
     102           1 :         if (persistent_script->full_path) {
     103           0 :                 efree(persistent_script->full_path);
     104             :         }
     105             : 
     106           1 :         efree(persistent_script);
     107           1 : }
     108             : 
     109        2229 : static int is_not_internal_function(zval *zv)
     110             : {
     111        2229 :         zend_function *function = Z_PTR_P(zv);
     112        2229 :         return(function->type != ZEND_INTERNAL_FUNCTION);
     113             : }
     114             : 
     115           1 : void zend_accel_free_user_functions(HashTable *ht)
     116             : {
     117           1 :         dtor_func_t orig_dtor = ht->pDestructor;
     118             : 
     119           1 :         ht->pDestructor = NULL;
     120           1 :         zend_hash_apply(ht, (apply_func_t) is_not_internal_function);
     121           1 :         ht->pDestructor = orig_dtor;
     122           1 : }
     123             : 
     124      940654 : static int move_user_function(zval *zv, int num_args, va_list args, zend_hash_key *hash_key)
     125             : {
     126      940654 :         zend_function *function = Z_PTR_P(zv);
     127      940654 :         HashTable *function_table = va_arg(args, HashTable *);
     128             :         (void)num_args; /* keep the compiler happy */
     129             : 
     130      940654 :         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      940630 :                 return 0;
     135             :         }
     136             : }
     137             : 
     138         422 : void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
     139             : {
     140         422 :         dtor_func_t orig_dtor = src->pDestructor;
     141             : 
     142         422 :         src->pDestructor = NULL;
     143         422 :         zend_hash_apply_with_arguments(src, (apply_func_args_t)move_user_function, 1, dst);
     144         422 :         src->pDestructor = orig_dtor;
     145         422 : }
     146             : 
     147    45983314 : static int copy_internal_function(zval *zv, HashTable *function_table)
     148             : {
     149    45983314 :         zend_internal_function *function = Z_PTR_P(zv);
     150    45983314 :         if (function->type == ZEND_INTERNAL_FUNCTION) {
     151    45983314 :                 zend_hash_update_mem(function_table, function->function_name, function, sizeof(zend_internal_function));
     152             :         }
     153    45983314 :         return 0;
     154             : }
     155             : 
     156       20666 : void zend_accel_copy_internal_functions(void)
     157             : {
     158       20666 :         zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table));
     159       20666 :         ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
     160       20666 : }
     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          29 :         if (EXPECTED(IS_INTERNED(str))) {
     177          29 :                 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          29 :         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->ht, 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          14 : 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          14 :         ht->nTableSize = source->nTableSize;
     298          14 :         ht->nTableMask = source->nTableMask;
     299          14 :         ht->nNumUsed = 0;
     300          14 :         ht->nNumOfElements = source->nNumOfElements;
     301          14 :         ht->nNextFreeElement = source->nNextFreeElement;
     302          14 :         ht->pDestructor = ZVAL_PTR_DTOR;
     303          14 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
     304          14 :         ht->arData = NULL;
     305          14 :         ht->arHash = NULL;
     306          14 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     307             : 
     308          14 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     309           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     310           0 :                 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         451 :         op_array->refcount = &zend_accel_refcount;
     374         451 :         (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
     375             : 
     376             :         /* copy statics */
     377         451 :         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 :                 zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
     382             :         }
     383             : }
     384             : 
     385           1 : static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
     386             : {
     387             :         uint idx;
     388             :         Bucket *p, *q;
     389             :         zend_ulong nIndex;
     390             :         zend_class_entry *new_ce;
     391             :         zend_function *new_prototype;
     392             :         zend_op_array *new_entry;
     393             : 
     394           1 :         ht->nTableSize = source->nTableSize;
     395           1 :         ht->nTableMask = source->nTableMask;
     396           1 :         ht->nNumUsed = 0;
     397           1 :         ht->nNumOfElements = source->nNumOfElements;
     398           1 :         ht->nNextFreeElement = source->nNextFreeElement;
     399           1 :         ht->pDestructor = ZEND_FUNCTION_DTOR;
     400           1 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     401           1 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     402             : 
     403           1 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     404           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     405           0 :                 return;
     406             :         }
     407             : 
     408             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     409           1 :         ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
     410           1 :         ht->arHash = (uint32_t *)(ht->arData + ht->nTableSize);
     411           1 :         memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
     412             : 
     413           6 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     414           5 :                 p = source->arData + idx;
     415          10 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     416             : 
     417           5 :                 nIndex = p->h & ht->nTableMask;
     418             : 
     419             :                 /* Insert into hash collision list */
     420           5 :                 q = ht->arData + ht->nNumUsed;
     421           5 :                 Z_NEXT(q->val) = ht->arHash[nIndex];
     422           5 :                 ht->arHash[nIndex] = ht->nNumUsed++;
     423             : 
     424             :                 /* Initialize key */
     425           5 :                 q->h = p->h;
     426             :                 ZEND_ASSERT(p->key != NULL);
     427          10 :                 q->key = zend_clone_str(p->key);
     428             : 
     429             :                 /* Copy data */
     430           5 :                 ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
     431           5 :                 new_entry = (zend_op_array*)Z_PTR(q->val);
     432             : 
     433             :                 /* Copy constructor */
     434             :                 /* we use refcount to show that op_array is referenced from several places */
     435           5 :                 if (new_entry->refcount != NULL) {
     436           0 :                         accel_xlat_set(Z_PTR(p->val), new_entry);
     437             :                 }
     438             : 
     439             :                 zend_prepare_function_for_execution(new_entry);
     440             : 
     441           5 :                 if (old_ce == new_entry->scope) {
     442           5 :                         new_entry->scope = ce;
     443             :                 } else {
     444           0 :                         if ((new_ce = accel_xlat_get(new_entry->scope)) != NULL) {
     445           0 :                                 new_entry->scope = new_ce;
     446             :                         } else {
     447           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
     448             :                         }
     449             :                 }
     450             : 
     451             :                 /* update prototype */
     452           5 :                 if (new_entry->prototype) {
     453           0 :                         if ((new_prototype = accel_xlat_get(new_entry->prototype)) != NULL) {
     454           0 :                                 new_entry->prototype = new_prototype;
     455             :                         } else {
     456           0 :                                 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
     457             :                         }
     458             :                 }
     459             :         }
     460             : }
     461             : 
     462           1 : static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
     463             : {
     464             :         uint idx;
     465             :         Bucket *p, *q;
     466             :         zend_ulong nIndex;
     467             :         zend_class_entry *new_ce;
     468             :         zend_property_info *prop_info;
     469             : 
     470           1 :         ht->nTableSize = source->nTableSize;
     471           1 :         ht->nTableMask = source->nTableMask;
     472           1 :         ht->nNumUsed = 0;
     473           1 :         ht->nNumOfElements = source->nNumOfElements;
     474           1 :         ht->nNextFreeElement = source->nNextFreeElement;
     475           1 :         ht->pDestructor = zend_destroy_property_info;
     476           1 :         ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
     477           1 :         ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
     478             : 
     479           1 :         if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
     480           0 :                 ht->arHash = (uint32_t*)&uninitialized_bucket;
     481           0 :                 return;
     482             :         }
     483             : 
     484             :         ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
     485           1 :         ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
     486           1 :         ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     487           1 :         memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
     488             : 
     489           3 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     490           2 :                 p = source->arData + idx;
     491           4 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     492             : 
     493           2 :                 nIndex = p->h & ht->nTableMask;
     494             : 
     495             :                 /* Insert into hash collision list */
     496           2 :                 q = ht->arData + ht->nNumUsed;
     497           2 :                 Z_NEXT(q->val) = ht->arHash[nIndex];
     498           2 :                 ht->arHash[nIndex] = ht->nNumUsed++;
     499             : 
     500             :                 /* Initialize key */
     501           2 :                 q->h = p->h;
     502             :                 ZEND_ASSERT(p->key != NULL);
     503           4 :                 q->key = zend_clone_str(p->key);
     504             : 
     505             :                 /* Copy data */
     506           2 :                 ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
     507           2 :                 prop_info = Z_PTR(q->val);
     508             : 
     509             :                 /* Copy constructor */
     510           4 :                 prop_info->name = zend_clone_str(prop_info->name);
     511           2 :                 if (prop_info->doc_comment) {
     512           0 :                         if (ZCG(accel_directives).load_comments) {
     513           0 :                                 prop_info->doc_comment = zend_string_dup(prop_info->doc_comment, 0);
     514             :                         } else {
     515           0 :                                 prop_info->doc_comment = NULL;
     516             :                         }
     517             :                 }
     518           2 :                 if (prop_info->ce == old_ce) {
     519           2 :                         prop_info->ce = ce;
     520           0 :                 } else if ((new_ce = accel_xlat_get(prop_info->ce)) != NULL) {
     521           0 :                         prop_info->ce = new_ce;
     522             :                 } else {
     523           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name->val, prop_info->name->val);
     524             :                 }
     525             :         }
     526             : }
     527             : 
     528             : #define zend_update_inherited_handler(handler) \
     529             : { \
     530             :         if (ce->handler != NULL) { \
     531             :                 if ((new_func = accel_xlat_get(ce->handler)) != NULL) { \
     532             :                         ce->handler = new_func; \
     533             :                 } else { \
     534             :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name->val); \
     535             :                 } \
     536             :         } \
     537             : }
     538             : 
     539             : /* Protects class' refcount, copies default properties, functions and class name */
     540           1 : static void zend_class_copy_ctor(zend_class_entry **pce)
     541             : {
     542           1 :         zend_class_entry *ce = *pce;
     543           1 :         zend_class_entry *old_ce = ce;
     544             :         zend_class_entry *new_ce;
     545             :         zend_function *new_func;
     546             : 
     547           1 :         *pce = ce = ARENA_REALLOC(old_ce);
     548           1 :         ce->refcount = 1;
     549             : 
     550           1 :         if (old_ce->refcount != 1) {
     551             :                 /* this class is not used as a parent for any other classes */
     552           0 :                 accel_xlat_set(old_ce, ce);
     553             :         }
     554             : 
     555           1 :         if (old_ce->default_properties_table) {
     556             :                 int i;
     557             : 
     558           0 :                 ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
     559           0 :                 for (i = 0; i < old_ce->default_properties_count; i++) {
     560           0 :                         ZVAL_COPY_VALUE(&ce->default_properties_table[i], &old_ce->default_properties_table[i]);
     561           0 :                         zend_clone_zval(&ce->default_properties_table[i], 1);
     562             :                 }
     563             :         }
     564             : 
     565           1 :         zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce);
     566             : 
     567             :         /* static members */
     568           1 :         if (old_ce->default_static_members_table) {
     569             :                 int i;
     570             : 
     571           1 :                 ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
     572           3 :                 for (i = 0; i < old_ce->default_static_members_count; i++) {
     573           2 :                         ZVAL_COPY_VALUE(&ce->default_static_members_table[i], &old_ce->default_static_members_table[i]);
     574           2 :                         zend_clone_zval(&ce->default_static_members_table[i], 1);
     575             :                 }
     576             :         }
     577           1 :         ce->static_members_table = ce->default_static_members_table;
     578             : 
     579             :         /* properties_info */
     580           1 :         zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce);
     581             : 
     582             :         /* constants table */
     583           1 :         zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
     584           1 :         ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     585             : 
     586           2 :         ce->name = zend_clone_str(ce->name);
     587             : 
     588             :         /* interfaces aren't really implemented, so we create a new table */
     589           1 :         if (ce->num_interfaces) {
     590           0 :                 ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
     591           0 :                 memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
     592             :         } else {
     593           1 :                 ce->interfaces = NULL;
     594             :         }
     595           1 :         if (ZEND_CE_DOC_COMMENT(ce)) {
     596           0 :                 if (ZCG(accel_directives).load_comments) {
     597           0 :                         ZEND_CE_DOC_COMMENT(ce) = zend_string_dup(ZEND_CE_DOC_COMMENT(ce), 0);
     598             :                 } else {
     599           0 :                         ZEND_CE_DOC_COMMENT(ce) =  NULL;
     600             :                 }
     601             :         }
     602             : 
     603           1 :         if (ce->parent) {
     604           0 :                 if ((new_ce = accel_xlat_get(ce->parent)) != NULL) {
     605           0 :                         ce->parent = new_ce;
     606             :                 } else {
     607           0 :                         zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name->val);
     608             :                 }
     609             :         }
     610             : 
     611           1 :         zend_update_inherited_handler(constructor);
     612           1 :         zend_update_inherited_handler(destructor);
     613           1 :         zend_update_inherited_handler(clone);
     614           1 :         zend_update_inherited_handler(__get);
     615           1 :         zend_update_inherited_handler(__set);
     616           1 :         zend_update_inherited_handler(__call);
     617             : /* 5.1 stuff */
     618           1 :         zend_update_inherited_handler(serialize_func);
     619           1 :         zend_update_inherited_handler(unserialize_func);
     620           1 :         zend_update_inherited_handler(__isset);
     621           1 :         zend_update_inherited_handler(__unset);
     622             : /* 5.2 stuff */
     623           1 :         zend_update_inherited_handler(__tostring);
     624             : 
     625             : /* 5.3 stuff */
     626           1 :         zend_update_inherited_handler(__callstatic);
     627           1 :         zend_update_inherited_handler(__debugInfo);
     628             : 
     629             : /* 5.4 traits */
     630           1 :         if (ce->trait_aliases) {
     631             :                 zend_trait_alias **trait_aliases;
     632           0 :                 int i = 0;
     633             : 
     634           0 :                 while (ce->trait_aliases[i]) {
     635           0 :                         i++;
     636             :                 }
     637           0 :                 trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
     638           0 :                 i = 0;
     639           0 :                 while (ce->trait_aliases[i]) {
     640           0 :                         trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
     641           0 :                         memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
     642           0 :                         trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     643           0 :                         memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
     644           0 :                         if (trait_aliases[i]->trait_method) {
     645           0 :                                 if (trait_aliases[i]->trait_method->method_name) {
     646           0 :                                         trait_aliases[i]->trait_method->method_name =
     647           0 :                                                 zend_clone_str(trait_aliases[i]->trait_method->method_name);
     648             :                                 }
     649           0 :                                 if (trait_aliases[i]->trait_method->class_name) {
     650           0 :                                         trait_aliases[i]->trait_method->class_name =
     651           0 :                                                 zend_clone_str(trait_aliases[i]->trait_method->class_name);
     652             :                                 }
     653             :                         }
     654             : 
     655           0 :                         if (trait_aliases[i]->alias) {
     656           0 :                                 trait_aliases[i]->alias =
     657           0 :                                         zend_clone_str(trait_aliases[i]->alias);
     658             :                         }
     659           0 :                         i++;
     660             :                 }
     661           0 :                 trait_aliases[i] = NULL;
     662           0 :                 ce->trait_aliases = trait_aliases;
     663             :         }
     664             : 
     665           1 :         if (ce->trait_precedences) {
     666             :                 zend_trait_precedence **trait_precedences;
     667           0 :                 int i = 0;
     668             : 
     669           0 :                 while (ce->trait_precedences[i]) {
     670           0 :                         i++;
     671             :                 }
     672           0 :                 trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
     673           0 :                 i = 0;
     674           0 :                 while (ce->trait_precedences[i]) {
     675           0 :                         trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
     676           0 :                         memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
     677           0 :                         trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
     678           0 :                         memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
     679             : 
     680           0 :                         trait_precedences[i]->trait_method->method_name =
     681           0 :                                 zend_clone_str(trait_precedences[i]->trait_method->method_name);
     682           0 :                         trait_precedences[i]->trait_method->class_name =
     683           0 :                                 zend_clone_str(trait_precedences[i]->trait_method->class_name);
     684             : 
     685           0 :                         if (trait_precedences[i]->exclude_from_classes) {
     686             :                                 zend_string **exclude_from_classes;
     687           0 :                                 int j = 0;
     688             : 
     689           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     690           0 :                                         j++;
     691             :                                 }
     692           0 :                                 exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1));
     693           0 :                                 j = 0;
     694           0 :                                 while (trait_precedences[i]->exclude_from_classes[j].class_name) {
     695           0 :                                         exclude_from_classes[j] =
     696           0 :                                                 zend_clone_str(trait_precedences[i]->exclude_from_classes[j].class_name);
     697           0 :                                         j++;
     698             :                                 }
     699           0 :                                 exclude_from_classes[j] = NULL;
     700           0 :                                 trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes;
     701             :                         }
     702           0 :                         i++;
     703             :                 }
     704           0 :                 trait_precedences[i] = NULL;
     705           0 :                 ce->trait_precedences = trait_precedences;
     706             :         }
     707           1 : }
     708             : 
     709           0 : static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
     710             : {
     711             :         zend_function *function1, *function2;
     712             :         uint idx;
     713             :         Bucket *p;
     714             :         zval *t;
     715             : 
     716           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     717           0 :                 p = source->arData + idx;
     718           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     719           0 :                 if (p->key) {
     720           0 :                         t = zend_hash_add(target, p->key, &p->val);
     721           0 :                         if (UNEXPECTED(t == NULL)) {
     722           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     723             :                                         /* Mangled key */
     724           0 :                                         t = zend_hash_update(target, p->key, &p->val);
     725             :                                 } else {
     726           0 :                                         t = zend_hash_find(target, p->key);
     727           0 :                                         goto failure;
     728             :                                 }
     729             :                         }
     730             :                 } else {
     731           0 :                     t = zend_hash_index_add(target, p->h, &p->val);
     732           0 :                         if (UNEXPECTED(t == NULL)) {
     733           0 :                                 t = zend_hash_index_find(target, p->h);
     734           0 :                                 goto failure;
     735             :                         }
     736             :                 }
     737             :         }
     738           0 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     739           0 :         return;
     740             : 
     741             : failure:
     742           0 :         function1 = Z_PTR(p->val);
     743           0 :         function2 = Z_PTR_P(t);
     744           0 :         CG(in_compilation) = 1;
     745           0 :         zend_set_compiled_filename(function1->op_array.filename);
     746           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     747           0 :         if (function2->type == ZEND_USER_FUNCTION
     748           0 :                 && function2->op_array.last > 0) {
     749           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     750           0 :                                    function1->common.function_name->val,
     751           0 :                                    function2->op_array.filename->val,
     752           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     753             :         } else {
     754           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     755             :         }
     756             : }
     757             : 
     758          24 : static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
     759             : {
     760             :         zend_function *function1, *function2;
     761             :         uint idx;
     762             :         Bucket *p;
     763             :         zval *t;
     764             : 
     765          48 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     766          24 :                 p = source->arData + idx;
     767          48 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     768          24 :                 if (p->key) {
     769          24 :                         t = zend_hash_add(target, p->key, &p->val);
     770          24 :                         if (UNEXPECTED(t == NULL)) {
     771           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     772             :                                         /* Mangled key */
     773           0 :                                         t = zend_hash_update(target, p->key, &p->val);
     774             :                                 } else {
     775           0 :                                         t = zend_hash_find(target, p->key);
     776           0 :                                         goto failure;
     777             :                                 }
     778             :                         }
     779             :                 } else {
     780           0 :                     t = zend_hash_index_add(target, p->h, &p->val);
     781           0 :                         if (UNEXPECTED(t == NULL)) {
     782           0 :                                 t = zend_hash_index_find(target, p->h);
     783           0 :                                 goto failure;
     784             :                         }
     785             :                 }
     786          24 :                 Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
     787          24 :                 zend_prepare_function_for_execution((zend_op_array*)Z_PTR_P(t));
     788             :         }
     789          24 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     790          24 :         return;
     791             : 
     792             : failure:
     793           0 :         function1 = Z_PTR(p->val);
     794           0 :         function2 = Z_PTR_P(t);
     795           0 :         CG(in_compilation) = 1;
     796           0 :         zend_set_compiled_filename(function1->op_array.filename);
     797           0 :         CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
     798           0 :         if (function2->type == ZEND_USER_FUNCTION
     799           0 :                 && function2->op_array.last > 0) {
     800           0 :                 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
     801           0 :                                    function1->common.function_name->val,
     802           0 :                                    function2->op_array.filename->val,
     803           0 :                                    (int)function2->op_array.opcodes[0].lineno);
     804             :         } else {
     805           0 :                 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
     806             :         }
     807             : }
     808             : 
     809           1 : static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
     810             : {
     811             :         zend_class_entry *ce1;
     812             :         uint idx;
     813             :         Bucket *p;
     814             :         zval *t;
     815             : 
     816           3 :         for (idx = 0; idx < source->nNumUsed; idx++) {
     817           2 :                 p = source->arData + idx;
     818           4 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     819           1 :                 if (p->key) {
     820           1 :                         t = zend_hash_add(target, p->key, &p->val);
     821           1 :                         if (UNEXPECTED(t == NULL)) {
     822           0 :                                 if (p->key->len > 0 && p->key->val[0] == 0) {
     823             :                                         /* Mangled key - ignore and wait for runtime */
     824           0 :                                         continue;
     825           0 :                                 } else if (!ZCG(accel_directives).ignore_dups) {
     826           0 :                                         t = zend_hash_find(target, p->key);
     827           0 :                                         goto failure;
     828             :                                 }
     829             :                         }
     830             :                 } else {
     831           0 :                         t = zend_hash_index_add(target, p->h, &p->val);
     832           0 :                         if (UNEXPECTED(t == NULL)) {
     833           0 :                                 if (!ZCG(accel_directives).ignore_dups) {
     834           0 :                                         t = zend_hash_index_find(target,p->h);
     835           0 :                                         goto failure;
     836             :                                 }
     837             :                         }
     838             :                 }
     839           1 :                 if (pCopyConstructor) {
     840           1 :                         pCopyConstructor(&Z_PTR_P(t));
     841             :                 }
     842             :         }
     843           1 :         target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
     844           1 :         return;
     845             : 
     846             : failure:
     847           0 :         ce1 = Z_PTR(p->val);
     848           0 :         CG(in_compilation) = 1;
     849           0 :         zend_set_compiled_filename(ce1->info.user.filename);
     850           0 :         CG(zend_lineno) = ce1->info.user.line_start;
     851           0 :         zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
     852             : }
     853             : 
     854         422 : zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
     855             : {
     856             :         zend_op_array *op_array;
     857             : 
     858         422 :         op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
     859         422 :         *op_array = persistent_script->main_op_array;
     860             : 
     861         422 :         if (EXPECTED(from_shared_memory)) {
     862         422 :                 zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
     863             : 
     864         422 :                 ZCG(current_persistent_script) = persistent_script;
     865         422 :                 ZCG(arena_mem) = NULL;
     866         422 :                 if (EXPECTED(persistent_script->arena_size)) {
     867          50 :                         ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
     868          25 :                         memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
     869             :                 }
     870             : 
     871             :                 /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
     872         422 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     873           1 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
     874             :                 }
     875             :                 /* we must first to copy all classes and then prepare functions, since functions may try to bind
     876             :                    classes - which depend on pre-bind class entries existent in the class table */
     877         422 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     878          24 :                         zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
     879             :                 }
     880             : 
     881             :                 zend_prepare_function_for_execution(op_array);
     882             : 
     883             :                 /* Register __COMPILER_HALT_OFFSET__ constant */
     884         517 :                 if (persistent_script->compiler_halt_offset != 0 &&
     885          95 :                     persistent_script->full_path) {
     886             :                         zend_string *name;
     887          95 :                         char haltoff[] = "__COMPILER_HALT_OFFSET__";
     888             : 
     889          95 :                         name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, persistent_script->full_path->val, persistent_script->full_path->len, 0);
     890          95 :                         if (!zend_hash_exists(EG(zend_constants), name)) {
     891           0 :                                 zend_register_long_constant(name->val, name->len, persistent_script->compiler_halt_offset, CONST_CS, 0);
     892             :                         }
     893             :                         zend_string_release(name);
     894             :                 }
     895             : 
     896         422 :                 zend_hash_destroy(&ZCG(bind_hash));
     897         422 :                 ZCG(current_persistent_script) = NULL;
     898             :         } else /* if (!from_shared_memory) */ {
     899           0 :                 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
     900           0 :                         zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table);
     901             :                 }
     902           0 :                 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
     903           0 :                         zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL);
     904             :                 }
     905             :         }
     906             : 
     907         422 :         if (op_array->early_binding != (uint32_t)-1) {
     908           0 :                 zend_string *orig_compiled_filename = CG(compiled_filename);
     909           0 :                 CG(compiled_filename) = persistent_script->full_path;
     910           0 :                 zend_do_delayed_early_binding(op_array);
     911           0 :                 CG(compiled_filename) = orig_compiled_filename;
     912             :         }
     913             : 
     914         422 :         if (UNEXPECTED(!from_shared_memory)) {
     915           0 :                 free_persistent_script(persistent_script, 0); /* free only hashes */
     916             :         }
     917             : 
     918         422 :         return op_array;
     919             : }
     920             : 
     921             : /*
     922             :  * zend_adler32() is based on zlib implementation
     923             :  * Computes the Adler-32 checksum of a data stream
     924             :  *
     925             :  * Copyright (C) 1995-2005 Mark Adler
     926             :  * For conditions of distribution and use, see copyright notice in zlib.h
     927             :  *
     928             :  * Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
     929             :  *
     930             :  *  This software is provided 'as-is', without any express or implied
     931             :  *  warranty.  In no event will the authors be held liable for any damages
     932             :  *  arising from the use of this software.
     933             :  *
     934             :  *  Permission is granted to anyone to use this software for any purpose,
     935             :  *  including commercial applications, and to alter it and redistribute it
     936             :  *  freely, subject to the following restrictions:
     937             :  *
     938             :  *  1. The origin of this software must not be misrepresented; you must not
     939             :  *     claim that you wrote the original software. If you use this software
     940             :  *     in a product, an acknowledgment in the product documentation would be
     941             :  *     appreciated but is not required.
     942             :  *  2. Altered source versions must be plainly marked as such, and must not be
     943             :  *     misrepresented as being the original software.
     944             :  *  3. This notice may not be removed or altered from any source distribution.
     945             :  *
     946             :  */
     947             : 
     948             : #define ADLER32_BASE 65521 /* largest prime smaller than 65536 */
     949             : #define ADLER32_NMAX 5552
     950             : /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
     951             : 
     952             : #define ADLER32_DO1(buf)        {s1 += *(buf); s2 += s1;}
     953             : #define ADLER32_DO2(buf, i)     ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1);
     954             : #define ADLER32_DO4(buf, i)     ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2);
     955             : #define ADLER32_DO8(buf, i)     ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4);
     956             : #define ADLER32_DO16(buf)       ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8);
     957             : 
     958         844 : unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len)
     959             : {
     960         844 :         unsigned int s1 = checksum & 0xffff;
     961         844 :         unsigned int s2 = (checksum >> 16) & 0xffff;
     962             :         signed char *end;
     963             : 
     964        1694 :         while (len >= ADLER32_NMAX) {
     965           6 :                 len -= ADLER32_NMAX;
     966           6 :                 end = buf + ADLER32_NMAX;
     967             :                 do {
     968        2082 :                         ADLER32_DO16(buf);
     969        2082 :                         buf += 16;
     970        2082 :                 } while (buf != end);
     971           6 :                 s1 %= ADLER32_BASE;
     972           6 :                 s2 %= ADLER32_BASE;
     973             :         }
     974             : 
     975         844 :         if (len) {
     976         844 :                 if (len >= 16) {
     977         844 :                         end = buf + (len & 0xfff0);
     978         844 :                         len &= 0xf;
     979             :                         do {
     980       31416 :                                 ADLER32_DO16(buf);
     981       31416 :                                 buf += 16;
     982       31416 :                         } while (buf != end);
     983             :                 }
     984         844 :                 if (len) {
     985         627 :                         end = buf + len;
     986             :                         do {
     987        5016 :                                 ADLER32_DO1(buf);
     988        5016 :                                 buf++;
     989        5016 :                         } while (buf != end);
     990             :                 }
     991         844 :                 s1 %= ADLER32_BASE;
     992         844 :                 s2 %= ADLER32_BASE;
     993             :         }
     994             : 
     995         844 :         return (s2 << 16) | s1;
     996             : }

Generated by: LCOV version 1.10

Generated at Mon, 26 Jan 2015 14:46:48 +0000 (4 days ago)

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