| 88 | | static void fixup_property_info (zend_property_info * from TSRMLS_DC) |
|---|
| 89 | | { |
|---|
| 90 | | FIXUP (from->name); |
|---|
| 91 | | } |
|---|
| 92 | | #endif |
|---|
| 93 | | |
|---|
| 94 | | static void fixup_hash (HashTable * source, |
|---|
| 95 | | fixup_bucket_t fixup_bucket TSRMLS_DC) |
|---|
| 96 | | { |
|---|
| 97 | | unsigned int i; |
|---|
| 98 | | Bucket *p; |
|---|
| 99 | | |
|---|
| 100 | | if (source->nNumOfElements > 0) { |
|---|
| 101 | | if (!EAG (compress)) { |
|---|
| 102 | | if (source->arBuckets != NULL) { |
|---|
| 103 | | FIXUP (source->arBuckets); |
|---|
| 104 | | for (i = 0; i < source->nTableSize; i++) { |
|---|
| 105 | | FIXUP (source->arBuckets[i]); |
|---|
| | 89 | static void fixup_property_info(zend_property_info * from TSRMLS_DC) |
|---|
| | 90 | { |
|---|
| | 91 | FIXUP(from->name); |
|---|
| | 92 | } |
|---|
| | 93 | #endif |
|---|
| | 94 | |
|---|
| | 95 | static void fixup_hash(HashTable * source, |
|---|
| | 96 | fixup_bucket_t fixup_bucket TSRMLS_DC) |
|---|
| | 97 | { |
|---|
| | 98 | unsigned int i; |
|---|
| | 99 | Bucket *p; |
|---|
| | 100 | |
|---|
| | 101 | if (source->nNumOfElements > 0) { |
|---|
| | 102 | if (!EAG(compress)) { |
|---|
| | 103 | if (source->arBuckets != NULL) { |
|---|
| | 104 | FIXUP(source->arBuckets); |
|---|
| | 105 | for (i = 0; i < source->nTableSize; i++) { |
|---|
| | 106 | FIXUP(source->arBuckets[i]); |
|---|
| | 107 | } |
|---|
| | 108 | } |
|---|
| | 109 | } |
|---|
| | 110 | FIXUP(source->pListHead); |
|---|
| | 111 | FIXUP(source->pListTail); |
|---|
| | 112 | |
|---|
| | 113 | p = source->pListHead; |
|---|
| | 114 | while (p) { |
|---|
| | 115 | FIXUP(p->pNext); |
|---|
| | 116 | FIXUP(p->pLast); |
|---|
| | 117 | FIXUP(p->pData); |
|---|
| | 118 | FIXUP(p->pDataPtr); |
|---|
| | 119 | FIXUP(p->pListLast); |
|---|
| | 120 | FIXUP(p->pListNext); |
|---|
| | 121 | if (p->pDataPtr) { |
|---|
| | 122 | fixup_bucket(p->pDataPtr TSRMLS_CC); |
|---|
| | 123 | p->pData = &p->pDataPtr; |
|---|
| | 124 | } else { |
|---|
| | 125 | fixup_bucket(p->pData TSRMLS_CC); |
|---|
| | 126 | } |
|---|
| | 127 | p = p->pListNext; |
|---|
| | 128 | } |
|---|
| | 129 | source->pInternalPointer = source->pListHead; |
|---|
| | 130 | } |
|---|
| | 131 | } |
|---|
| | 132 | |
|---|
| | 133 | void fixup_zval(zval * zv TSRMLS_DC) |
|---|
| | 134 | { |
|---|
| | 135 | switch (zv->type & ~IS_CONSTANT_INDEX) { |
|---|
| | 136 | case IS_CONSTANT: /* fallthrough */ |
|---|
| | 137 | case IS_STRING: |
|---|
| | 138 | if (zv->value.str.val == NULL || zv->value.str.len == 0) { |
|---|
| | 139 | zv->value.str.val = empty_string; |
|---|
| | 140 | zv->value.str.len = 0; |
|---|
| | 141 | } else { |
|---|
| | 142 | FIXUP(zv->value.str.val); |
|---|
| | 143 | } |
|---|
| | 144 | break; |
|---|
| | 145 | case IS_ARRAY: /* fallthrough */ |
|---|
| | 146 | case IS_CONSTANT_ARRAY: |
|---|
| | 147 | if (zv->value.ht == NULL || zv->value.ht == &EG(symbol_table)) { |
|---|
| | 148 | } else { |
|---|
| | 149 | FIXUP(zv->value.ht); |
|---|
| | 150 | fixup_zval_hash(zv->value.ht); |
|---|
| | 151 | } |
|---|
| | 152 | break; |
|---|
| | 153 | case IS_OBJECT: |
|---|
| | 154 | if (!EAG(compress)) { |
|---|
| | 155 | return; |
|---|
| | 156 | } |
|---|
| | 157 | #ifndef ZEND_ENGINE_2 |
|---|
| | 158 | FIXUP(zv->value.obj.ce); |
|---|
| | 159 | if (zv->value.obj.properties != NULL) { |
|---|
| | 160 | FIXUP(zv->value.obj.properties); |
|---|
| | 161 | fixup_zval_hash(zv->value.obj.properties); |
|---|
| | 162 | } |
|---|
| | 163 | #endif |
|---|
| | 164 | default: |
|---|
| | 165 | break; |
|---|
| | 166 | } |
|---|
| | 167 | } |
|---|
| | 168 | |
|---|
| | 169 | void fixup_op_array(eaccelerator_op_array * from TSRMLS_DC) |
|---|
| | 170 | { |
|---|
| | 171 | zend_op *opline; |
|---|
| | 172 | zend_op *end; |
|---|
| | 173 | |
|---|
| | 174 | #ifdef ZEND_ENGINE_2 |
|---|
| | 175 | if (from->num_args > 0) { |
|---|
| | 176 | zend_uint i; |
|---|
| | 177 | FIXUP(from->arg_info); |
|---|
| | 178 | for (i = 0; i < from->num_args; i++) { |
|---|
| | 179 | FIXUP(from->arg_info[i].name); |
|---|
| | 180 | FIXUP(from->arg_info[i].class_name); |
|---|
| | 181 | } |
|---|
| | 182 | } |
|---|
| | 183 | #else |
|---|
| | 184 | FIXUP(from->arg_types); |
|---|
| | 185 | #endif |
|---|
| | 186 | FIXUP(from->function_name); |
|---|
| | 187 | #ifdef ZEND_ENGINE_2 |
|---|
| | 188 | FIXUP(from->scope_name); |
|---|
| | 189 | #endif |
|---|
| | 190 | if (from->type == ZEND_INTERNAL_FUNCTION) { |
|---|
| | 191 | return; |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | if (from->opcodes != NULL) { |
|---|
| | 195 | FIXUP(from->opcodes); |
|---|
| | 196 | |
|---|
| | 197 | opline = from->opcodes; |
|---|
| | 198 | end = opline + from->last; |
|---|
| | 199 | EAG(compress) = 0; |
|---|
| | 200 | for (; opline < end; opline++) { |
|---|
| | 201 | /* |
|---|
| | 202 | if (opline->result.op_type == IS_CONST) |
|---|
| | 203 | fixup_zval(&opline->result.u.constant TSRMLS_CC); |
|---|
| | 204 | */ |
|---|
| | 205 | if (opline->op1.op_type == IS_CONST) |
|---|
| | 206 | fixup_zval(&opline->op1.u.constant TSRMLS_CC); |
|---|
| | 207 | if (opline->op2.op_type == IS_CONST) |
|---|
| | 208 | fixup_zval(&opline->op2.u.constant TSRMLS_CC); |
|---|
| | 209 | #ifdef ZEND_ENGINE_2 |
|---|
| | 210 | switch (opline->opcode) { |
|---|
| | 211 | case ZEND_JMP: |
|---|
| | 212 | FIXUP(opline->op1.u.jmp_addr); |
|---|
| | 213 | break; |
|---|
| | 214 | case ZEND_JMPZ: /* fallthrough */ |
|---|
| | 215 | case ZEND_JMPNZ: |
|---|
| | 216 | case ZEND_JMPZ_EX: |
|---|
| | 217 | case ZEND_JMPNZ_EX: |
|---|
| | 218 | FIXUP(opline->op2.u.jmp_addr); |
|---|
| | 219 | break; |
|---|
| | 220 | } |
|---|
| | 221 | opline->handler = get_opcode_handler(opline->opcode TSRMLS_CC); |
|---|
| | 222 | #endif |
|---|
| | 223 | } |
|---|
| | 224 | EAG(compress) = 1; |
|---|
| | 225 | } |
|---|
| | 226 | FIXUP(from->brk_cont_array); |
|---|
| | 227 | #ifdef ZEND_ENGINE_2 |
|---|
| | 228 | FIXUP(from->try_catch_array); |
|---|
| | 229 | #endif |
|---|
| | 230 | if (from->static_variables != NULL) { |
|---|
| | 231 | FIXUP(from->static_variables); |
|---|
| | 232 | fixup_zval_hash(from->static_variables); |
|---|
| | 233 | } |
|---|
| | 234 | FIXUP(from->filename); |
|---|
| | 235 | #ifdef ZEND_ENGINE_2 |
|---|
| | 236 | FIXUP(from->doc_comment); |
|---|
| | 237 | #endif |
|---|
| | 238 | } |
|---|
| | 239 | |
|---|
| | 240 | void fixup_class_entry(eaccelerator_class_entry * from TSRMLS_DC) |
|---|
| | 241 | { |
|---|
| | 242 | FIXUP(from->name); |
|---|
| | 243 | FIXUP(from->parent); |
|---|
| | 244 | #ifdef ZEND_ENGINE_2 |
|---|
| | 245 | FIXUP(from->filename); |
|---|
| | 246 | FIXUP(from->doc_comment); |
|---|
| | 247 | fixup_zval_hash(&from->constants_table); |
|---|
| | 248 | fixup_zval_hash(&from->default_properties); |
|---|
| | 249 | fixup_hash(&from->properties_info, |
|---|
| | 250 | (fixup_bucket_t) fixup_property_info TSRMLS_CC); |
|---|
| | 251 | if (from->static_members != NULL) { |
|---|
| | 252 | FIXUP(from->static_members); |
|---|
| | 253 | fixup_zval_hash(from->static_members); |
|---|
| | 254 | } |
|---|
| | 255 | #else |
|---|
| | 256 | fixup_zval_hash(&from->default_properties); |
|---|
| | 257 | #endif |
|---|
| | 258 | fixup_hash(&from->function_table, |
|---|
| | 259 | (fixup_bucket_t) fixup_op_array TSRMLS_CC); |
|---|
| | 260 | } |
|---|
| | 261 | |
|---|
| | 262 | /******************************************************************************/ |
|---|
| | 263 | /* Functions to restore a php script from shared memory */ |
|---|
| | 264 | /******************************************************************************/ |
|---|
| | 265 | |
|---|
| | 266 | typedef void *(*restore_bucket_t) (void *TSRMLS_DC); |
|---|
| | 267 | |
|---|
| | 268 | #define restore_zval_hash(target, source) \ |
|---|
| | 269 | restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC) |
|---|
| | 270 | |
|---|
| | 271 | static zval *restore_zval_ptr(zval * from TSRMLS_DC) |
|---|
| | 272 | { |
|---|
| | 273 | zval *p; |
|---|
| | 274 | ALLOC_ZVAL(p); |
|---|
| | 275 | memcpy(p, from, sizeof(zval)); |
|---|
| | 276 | restore_zval(p TSRMLS_CC); |
|---|
| | 277 | return p; |
|---|
| | 278 | } |
|---|
| | 279 | |
|---|
| | 280 | static HashTable *restore_hash(HashTable * target, HashTable * source, |
|---|
| | 281 | restore_bucket_t copy_bucket TSRMLS_DC) |
|---|
| | 282 | { |
|---|
| | 283 | Bucket *p, *np, *prev_p; |
|---|
| | 284 | int nIndex; |
|---|
| | 285 | |
|---|
| | 286 | if (target == NULL) { |
|---|
| | 287 | ALLOC_HASHTABLE(target); |
|---|
| | 288 | } |
|---|
| | 289 | memcpy(target, source, sizeof(HashTable)); |
|---|
| | 290 | target->arBuckets = |
|---|
| | 291 | (Bucket **) emalloc(target->nTableSize * sizeof(Bucket *)); |
|---|
| | 292 | memset(target->arBuckets, 0, target->nTableSize * sizeof(Bucket *)); |
|---|
| | 293 | target->pDestructor = NULL; |
|---|
| | 294 | target->persistent = 0; |
|---|
| | 295 | target->pListHead = NULL; |
|---|
| | 296 | target->pListTail = NULL; |
|---|
| | 297 | |
|---|
| | 298 | p = source->pListHead; |
|---|
| | 299 | prev_p = NULL; |
|---|
| | 300 | np = NULL; |
|---|
| | 301 | while (p) { |
|---|
| | 302 | np = (Bucket *) emalloc(offsetof(Bucket, arKey) + p->nKeyLength); |
|---|
| | 303 | /* np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); */ |
|---|
| | 304 | nIndex = p->h % source->nTableSize; |
|---|
| | 305 | if (target->arBuckets[nIndex]) { |
|---|
| | 306 | np->pNext = target->arBuckets[nIndex]; |
|---|
| | 307 | np->pLast = NULL; |
|---|
| | 308 | np->pNext->pLast = np; |
|---|
| | 309 | } else { |
|---|
| | 310 | np->pNext = NULL; |
|---|
| | 311 | np->pLast = NULL; |
|---|
| | 312 | } |
|---|
| | 313 | target->arBuckets[nIndex] = np; |
|---|
| | 314 | np->h = p->h; |
|---|
| | 315 | np->nKeyLength = p->nKeyLength; |
|---|
| | 316 | |
|---|
| | 317 | if (p->pDataPtr == NULL) { |
|---|
| | 318 | np->pData = copy_bucket(p->pData TSRMLS_CC); |
|---|
| | 319 | np->pDataPtr = NULL; |
|---|
| | 320 | } else { |
|---|
| | 321 | np->pDataPtr = copy_bucket(p->pDataPtr TSRMLS_CC); |
|---|
| | 322 | np->pData = &np->pDataPtr; |
|---|
| | 323 | } |
|---|
| | 324 | np->pListLast = prev_p; |
|---|
| | 325 | np->pListNext = NULL; |
|---|
| | 326 | |
|---|
| | 327 | memcpy(np->arKey, p->arKey, p->nKeyLength); |
|---|
| | 328 | |
|---|
| | 329 | if (prev_p) { |
|---|
| | 330 | prev_p->pListNext = np; |
|---|
| | 331 | } else { |
|---|
| | 332 | target->pListHead = np; |
|---|
| | 333 | } |
|---|
| | 334 | prev_p = np; |
|---|
| | 335 | p = p->pListNext; |
|---|
| | 336 | } |
|---|
| | 337 | target->pListTail = np; |
|---|
| | 338 | target->pInternalPointer = target->pListHead; |
|---|
| | 339 | return target; |
|---|
| | 340 | } |
|---|
| | 341 | |
|---|
| | 342 | void restore_zval(zval * zv TSRMLS_DC) |
|---|
| | 343 | { |
|---|
| | 344 | switch (zv->type & ~IS_CONSTANT_INDEX) { |
|---|
| | 345 | case IS_CONSTANT: |
|---|
| | 346 | case IS_STRING: |
|---|
| | 347 | if (zv->value.str.val == NULL || |
|---|
| | 348 | zv->value.str.val == empty_string || zv->value.str.len == 0) { |
|---|
| | 349 | zv->value.str.val = empty_string; |
|---|
| | 350 | return; |
|---|
| | 351 | } else { |
|---|
| | 352 | char *p = emalloc(zv->value.str.len + 1); |
|---|
| | 353 | memcpy(p, zv->value.str.val, zv->value.str.len + 1); |
|---|
| | 354 | zv->value.str.val = p; |
|---|
| | 355 | } |
|---|
| | 356 | return; |
|---|
| | 357 | |
|---|
| | 358 | case IS_ARRAY: |
|---|
| | 359 | case IS_CONSTANT_ARRAY: |
|---|
| | 360 | if (zv->value.ht != NULL && zv->value.ht != &EG(symbol_table)) { |
|---|
| | 361 | zv->value.ht = restore_zval_hash(NULL, zv->value.ht); |
|---|
| | 362 | zv->value.ht->pDestructor = ZVAL_PTR_DTOR; |
|---|
| | 363 | } |
|---|
| | 364 | return; |
|---|
| | 365 | |
|---|
| | 366 | case IS_OBJECT: |
|---|
| | 367 | { |
|---|
| | 368 | #ifndef ZEND_ENGINE_2 |
|---|
| | 369 | zend_bool incomplete_class = 0; |
|---|
| | 370 | char *class_name = (char *) zv->value.obj.ce; |
|---|
| | 371 | int name_len = 0; |
|---|
| | 372 | if (!EAG(compress)) { |
|---|
| | 373 | return; |
|---|
| | 374 | } |
|---|
| | 375 | if (class_name != NULL) { |
|---|
| | 376 | zend_class_entry *ce = NULL; |
|---|
| | 377 | name_len = strlen(class_name); |
|---|
| | 378 | if (zend_hash_find(CG(class_table), (void *) class_name, name_len + 1, (void **) &ce) != SUCCESS) { |
|---|
| | 379 | char *lowercase_name = estrndup(INCOMPLETE_CLASS, sizeof(INCOMPLETE_CLASS)); |
|---|
| | 380 | zend_str_tolower(lowercase_name, sizeof(INCOMPLETE_CLASS)); |
|---|
| | 381 | if (zend_hash_find(CG(class_table), lowercase_name, |
|---|
| | 382 | sizeof(INCOMPLETE_CLASS), (void **) &ce) != SUCCESS) { |
|---|
| | 383 | efree(lowercase_name); |
|---|
| | 384 | zend_error(E_ERROR, "EACCELERATOR can't restore object's class \"%s\"", class_name); |
|---|
| | 385 | } else { |
|---|
| | 386 | efree(lowercase_name); |
|---|
| | 387 | zv->value.obj.ce = ce; |
|---|
| | 388 | incomplete_class = 1; |
|---|
| | 389 | } |
|---|
| | 390 | } else { |
|---|
| | 391 | zv->value.obj.ce = ce; |
|---|
| | 392 | } |
|---|
| | 393 | } |
|---|
| | 394 | if (zv->value.obj.properties != NULL) { |
|---|
| | 395 | zv->value.obj.properties = restore_zval_hash(NULL, zv->value.obj.properties); |
|---|
| | 396 | zv->value.obj.properties->pDestructor = ZVAL_PTR_DTOR; |
|---|
| | 397 | /* Clearing references */ |
|---|
| | 398 | { |
|---|
| | 399 | Bucket *p = zv->value.obj.properties->pListHead; |
|---|
| | 400 | while (p != NULL) { |
|---|
| | 401 | ((zval *) (p->pDataPtr))->refcount = 1; |
|---|
| | 402 | p = p->pListNext; |
|---|
| 192 | | |
|---|
| 193 | | if (from->opcodes != NULL) { |
|---|
| 194 | | FIXUP (from->opcodes); |
|---|
| 195 | | |
|---|
| 196 | | opline = from->opcodes; |
|---|
| 197 | | end = opline + from->last; |
|---|
| 198 | | EAG (compress) = 0; |
|---|
| 199 | | for (; opline < end; opline++) { |
|---|
| 200 | | /* |
|---|
| 201 | | if (opline->result.op_type == IS_CONST) fixup_zval(&opline->result.u.constant TSRMLS_CC); |
|---|
| 202 | | */ |
|---|
| 203 | | if (opline->op1.op_type == IS_CONST) |
|---|
| 204 | | fixup_zval (&opline->op1.u.constant TSRMLS_CC); |
|---|
| 205 | | if (opline->op2.op_type == IS_CONST) |
|---|
| 206 | | fixup_zval (&opline->op2.u.constant TSRMLS_CC); |
|---|
| 207 | | #ifdef ZEND_ENGINE_2 |
|---|
| 208 | | switch (opline->opcode) { |
|---|
| 209 | | case ZEND_JMP: |
|---|
| 210 | | FIXUP (opline->op1.u.jmp_addr); |
|---|
| 211 | | break; |
|---|
| 212 | | case ZEND_JMPZ: /* fallthrough */ |
|---|
| 213 | | case ZEND_JMPNZ: |
|---|
| 214 | | case ZEND_JMPZ_EX: |
|---|
| 215 | | case ZEND_JMPNZ_EX: |
|---|
| 216 | | FIXUP (opline->op2.u.jmp_addr); |
|---|
| 217 | | break; |
|---|
| 218 | | } |
|---|
| 219 | | opline->handler = get_opcode_handler (opline->opcode TSRMLS_CC); |
|---|
| 220 | | #endif |
|---|
| 221 | | } |
|---|
| 222 | | EAG (compress) = 1; |
|---|
| 223 | | } |
|---|
| 224 | | FIXUP (from->brk_cont_array); |
|---|
| 225 | | #ifdef ZEND_ENGINE_2 |
|---|
| 226 | | FIXUP (from->try_catch_array); |
|---|
| 227 | | #endif |
|---|
| 228 | | if (from->static_variables != NULL) { |
|---|
| 229 | | FIXUP (from->static_variables); |
|---|
| 230 | | fixup_zval_hash (from->static_variables); |
|---|
| 231 | | } |
|---|
| 232 | | FIXUP (from->filename); |
|---|
| 233 | | #ifdef ZEND_ENGINE_2 |
|---|
| 234 | | FIXUP (from->doc_comment); |
|---|
| 235 | | #endif |
|---|
| 236 | | } |
|---|
| 237 | | |
|---|
| 238 | | void fixup_class_entry (eaccelerator_class_entry * from TSRMLS_DC) |
|---|
| 239 | | { |
|---|
| 240 | | FIXUP (from->name); |
|---|
| 241 | | FIXUP (from->parent); |
|---|
| 242 | | #ifdef ZEND_ENGINE_2 |
|---|
| 243 | | FIXUP (from->filename); |
|---|
| 244 | | FIXUP (from->doc_comment); |
|---|
| 245 | | fixup_zval_hash (&from->constants_table); |
|---|
| 246 | | fixup_zval_hash (&from->default_properties); |
|---|
| 247 | | fixup_hash (&from->properties_info, |
|---|
| 248 | | (fixup_bucket_t) fixup_property_info TSRMLS_CC); |
|---|
| 249 | | if (from->static_members != NULL) { |
|---|
| 250 | | FIXUP (from->static_members); |
|---|
| 251 | | fixup_zval_hash (from->static_members); |
|---|
| 252 | | } |
|---|
| 253 | | #else |
|---|
| 254 | | fixup_zval_hash (&from->default_properties); |
|---|
| 255 | | #endif |
|---|
| 256 | | fixup_hash (&from->function_table, |
|---|
| 257 | | (fixup_bucket_t) fixup_op_array TSRMLS_CC); |
|---|
| 258 | | } |
|---|
| 259 | | |
|---|
| 260 | | /******************************************************************************/ |
|---|
| 261 | | /* Functions to restore a php script from shared memory */ |
|---|
| 262 | | /******************************************************************************/ |
|---|
| 263 | | |
|---|
| 264 | | typedef void *(*restore_bucket_t) (void *TSRMLS_DC); |
|---|
| 265 | | |
|---|
| 266 | | #define restore_zval_hash(target, source) \ |
|---|
| 267 | | restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC) |
|---|
| 268 | | |
|---|
| 269 | | static zval *restore_zval_ptr (zval * from TSRMLS_DC) |
|---|
| 270 | | { |
|---|
| 271 | | zval *p; |
|---|
| 272 | | ALLOC_ZVAL (p); |
|---|
| 273 | | memcpy (p, from, sizeof (zval)); |
|---|
| 274 | | restore_zval (p TSRMLS_CC); |
|---|
| 275 | | return p; |
|---|
| 276 | | } |
|---|
| 277 | | |
|---|
| 278 | | static HashTable *restore_hash (HashTable * target, HashTable * source, |
|---|
| 279 | | restore_bucket_t copy_bucket TSRMLS_DC) |
|---|
| 280 | | { |
|---|
| 281 | | Bucket *p, *np, *prev_p; |
|---|
| 282 | | int nIndex; |
|---|
| 283 | | |
|---|
| 284 | | if (target == NULL) { |
|---|
| 285 | | ALLOC_HASHTABLE (target); |
|---|
| 286 | | } |
|---|
| 287 | | memcpy (target, source, sizeof (HashTable)); |
|---|
| 288 | | target->arBuckets = |
|---|
| 289 | | (Bucket **) emalloc (target->nTableSize * sizeof (Bucket *)); |
|---|
| 290 | | memset (target->arBuckets, 0, target->nTableSize * sizeof (Bucket *)); |
|---|
| 291 | | target->pDestructor = NULL; |
|---|
| 292 | | target->persistent = 0; |
|---|
| 293 | | target->pListHead = NULL; |
|---|
| 294 | | target->pListTail = NULL; |
|---|
| 295 | | |
|---|
| 296 | | p = source->pListHead; |
|---|
| 297 | | prev_p = NULL; |
|---|
| 298 | | np = NULL; |
|---|
| 299 | | while (p) { |
|---|
| 300 | | np = (Bucket *) emalloc (offsetof (Bucket, arKey) + p->nKeyLength); |
|---|
| 301 | | /* np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);*/ |
|---|
| 302 | | nIndex = p->h % source->nTableSize; |
|---|
| 303 | | if (target->arBuckets[nIndex]) { |
|---|
| 304 | | np->pNext = target->arBuckets[nIndex]; |
|---|
| 305 | | np->pLast = NULL; |
|---|
| 306 | | np->pNext->pLast = np; |
|---|
| 307 | | } else { |
|---|
| 308 | | np->pNext = NULL; |
|---|
| 309 | | np->pLast = NULL; |
|---|
| 310 | | } |
|---|
| 311 | | target->arBuckets[nIndex] = np; |
|---|
| 312 | | np->h = p->h; |
|---|
| 313 | | np->nKeyLength = p->nKeyLength; |
|---|
| 314 | | |
|---|
| 315 | | if (p->pDataPtr == NULL) { |
|---|
| 316 | | np->pData = copy_bucket (p->pData TSRMLS_CC); |
|---|
| 317 | | np->pDataPtr = NULL; |
|---|
| 318 | | } else { |
|---|
| 319 | | np->pDataPtr = copy_bucket (p->pDataPtr TSRMLS_CC); |
|---|
| 320 | | np->pData = &np->pDataPtr; |
|---|
| 321 | | } |
|---|
| 322 | | np->pListLast = prev_p; |
|---|
| 323 | | np->pListNext = NULL; |
|---|
| 324 | | |
|---|
| 325 | | memcpy (np->arKey, p->arKey, p->nKeyLength); |
|---|
| 326 | | |
|---|
| 327 | | if (prev_p) { |
|---|
| 328 | | prev_p->pListNext = np; |
|---|
| 329 | | } else { |
|---|
| 330 | | target->pListHead = np; |
|---|
| 331 | | } |
|---|
| 332 | | prev_p = np; |
|---|
| 333 | | p = p->pListNext; |
|---|
| 334 | | } |
|---|
| 335 | | target->pListTail = np; |
|---|
| 336 | | target->pInternalPointer = target->pListHead; |
|---|
| 337 | | return target; |
|---|
| 338 | | } |
|---|
| 339 | | |
|---|
| 340 | | void restore_zval (zval * zv TSRMLS_DC) |
|---|
| 341 | | { |
|---|
| 342 | | switch (zv->type & ~IS_CONSTANT_INDEX) { |
|---|
| 343 | | case IS_CONSTANT: |
|---|
| 344 | | case IS_STRING: |
|---|
| 345 | | if (zv->value.str.val == NULL || zv->value.str.val == empty_string |
|---|
| 346 | | || zv->value.str.len == 0) { |
|---|
| 347 | | zv->value.str.val = empty_string; |
|---|
| 348 | | return; |
|---|
| 349 | | } else { |
|---|
| 350 | | char *p = emalloc (zv->value.str.len + 1); |
|---|
| 351 | | memcpy (p, zv->value.str.val, zv->value.str.len + 1); |
|---|
| 352 | | zv->value.str.val = p; |
|---|
| 353 | | } |
|---|
| 354 | | return; |
|---|
| 355 | | |
|---|
| 356 | | case IS_ARRAY: |
|---|
| 357 | | case IS_CONSTANT_ARRAY: |
|---|
| 358 | | if (zv->value.ht != NULL && zv->value.ht != &EG (symbol_table)) { |
|---|
| 359 | | zv->value.ht = restore_zval_hash (NULL, zv->value.ht); |
|---|
| 360 | | zv->value.ht->pDestructor = ZVAL_PTR_DTOR; |
|---|
| 361 | | } |
|---|
| 362 | | return; |
|---|
| 363 | | |
|---|
| 364 | | case IS_OBJECT: |
|---|
| 365 | | { |
|---|
| | 417 | } |
|---|
| | 418 | } |
|---|
| | 419 | |
|---|
| | 420 | static void call_op_array_ctor_handler(zend_extension * extension, |
|---|
| | 421 | zend_op_array * op_array TSRMLS_DC) |
|---|
| | 422 | { |
|---|
| | 423 | if (extension->op_array_ctor) { |
|---|
| | 424 | extension->op_array_ctor(op_array); |
|---|
| | 425 | } |
|---|
| | 426 | } |
|---|
| | 427 | |
|---|
| | 428 | zend_op_array *restore_op_array(zend_op_array * to, |
|---|
| | 429 | eaccelerator_op_array * from TSRMLS_DC) |
|---|
| | 430 | { |
|---|
| | 431 | zend_function *function; |
|---|
| | 432 | #ifdef ZEND_ENGINE_2 |
|---|
| | 433 | int fname_len = 0; |
|---|
| | 434 | char *fname_lc = NULL; |
|---|
| | 435 | #endif |
|---|
| | 436 | |
|---|
| | 437 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 438 | ea_debug_printf(EA_DEBUG, "[%d] restore_op_array: %s\n", getpid(), |
|---|
| | 439 | from->function_name ? from->function_name : "(top)"); |
|---|
| | 440 | |
|---|
| | 441 | if (from->type == ZEND_INTERNAL_FUNCTION) { |
|---|
| | 442 | if (to == NULL) { |
|---|
| | 443 | to = emalloc(sizeof(zend_internal_function)); |
|---|
| | 444 | } |
|---|
| | 445 | memset(to, 0, sizeof(zend_internal_function)); |
|---|
| | 446 | } else { |
|---|
| | 447 | if (to == NULL) { |
|---|
| | 448 | to = emalloc(sizeof(zend_op_array)); |
|---|
| | 449 | } |
|---|
| | 450 | memset(to, 0, sizeof(zend_op_array)); |
|---|
| | 451 | if (ZendOptimizer) { |
|---|
| | 452 | zend_llist_apply_with_argument(&zend_extensions, |
|---|
| | 453 | (llist_apply_with_arg_func_t) call_op_array_ctor_handler, to TSRMLS_CC); |
|---|
| | 454 | } |
|---|
| | 455 | } |
|---|
| | 456 | to->type = from->type; |
|---|
| | 457 | #ifdef ZEND_ENGINE_2 |
|---|
| | 458 | to->num_args = from->num_args; |
|---|
| | 459 | to->required_num_args = from->required_num_args; |
|---|
| | 460 | to->arg_info = from->arg_info; |
|---|
| | 461 | to->pass_rest_by_reference = from->pass_rest_by_reference; |
|---|
| | 462 | #else |
|---|
| | 463 | to->arg_types = from->arg_types; |
|---|
| | 464 | #endif |
|---|
| | 465 | to->function_name = from->function_name; |
|---|
| | 466 | |
|---|
| | 467 | #ifdef ZEND_ENGINE_2 |
|---|
| | 468 | if (to->function_name) { |
|---|
| | 469 | fname_len = strlen(to->function_name); |
|---|
| | 470 | fname_lc = zend_str_tolower_dup(to->function_name, fname_len); |
|---|
| | 471 | } |
|---|
| | 472 | |
|---|
| | 473 | to->fn_flags = from->fn_flags; |
|---|
| | 474 | |
|---|
| | 475 | /* segv74: |
|---|
| | 476 | * to->scope = EAG(class_entry) |
|---|
| | 477 | * |
|---|
| | 478 | * if from->scope_name == NULL, |
|---|
| | 479 | * ; EAG(class) == NULL : we are in function or outside function. |
|---|
| | 480 | * ; EAG(class) != NULL : inherited method not defined in current file, should have to find. |
|---|
| | 481 | * just LINK (zend_op_array *) to to original entry in parent, |
|---|
| | 482 | * but, with what? !!! I don't know PARENT CLASS NAME !!!! |
|---|
| | 483 | * |
|---|
| | 484 | * |
|---|
| | 485 | * if from->scope_name != NULL, |
|---|
| | 486 | * ; we are in class member function |
|---|
| | 487 | * |
|---|
| | 488 | * ; we have to find appropriate (zend_class_entry*) to->scope for name from->scope_name |
|---|
| | 489 | * ; if we find in CG(class_table), link to it. |
|---|
| | 490 | * ; if fail, it should be EAG(class_entry) |
|---|
| | 491 | * |
|---|
| | 492 | * am I right here ? ;-( |
|---|
| | 493 | */ |
|---|
| | 494 | if (from->scope_name != NULL) { |
|---|
| | 495 | char *from_scope_lc = zend_str_tolower_dup(from->scope_name, from->scope_name_len); |
|---|
| | 496 | if (zend_hash_find (CG(class_table), (void *) from_scope_lc, |
|---|
| | 497 | from->scope_name_len + 1, (void **) &to->scope) != SUCCESS) { |
|---|
| | 498 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 499 | ea_debug_printf(EA_DEBUG, "[%d] can't find '%s' in hash. use EAG(class_entry).\n", getpid(), from_scope_lc); |
|---|
| | 500 | to->scope = EAG(class_entry); |
|---|
| | 501 | } else { |
|---|
| | 502 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 503 | ea_debug_printf(EA_DEBUG, "[%d] found '%s' in hash\n", getpid(), from_scope_lc); |
|---|
| | 504 | to->scope = *(zend_class_entry **) to->scope; |
|---|
| | 505 | } |
|---|
| | 506 | efree(from_scope_lc); |
|---|
| | 507 | } else { // zoeloelip: is this needed? scope is always stored |
|---|
| | 508 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 509 | ea_debug_printf(EA_DEBUG, "[%d] from is NULL\n", getpid()); |
|---|
| | 510 | if (EAG(class_entry)) { |
|---|
| | 511 | zend_class_entry *p; |
|---|
| | 512 | for (p = EAG(class_entry)->parent; p; p = p->parent) { |
|---|
| | 513 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 514 | ea_debug_printf(EA_DEBUG, "[%d] checking parent '%s' have '%s'\n", getpid(), p->name, fname_lc); |
|---|
| | 515 | if (zend_hash_find(&p->function_table, fname_lc, fname_len + 1, (void **) &function) == SUCCESS) { |
|---|
| | 516 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 517 | ea_debug_printf(EA_DEBUG, "[%d] '%s' has '%s' of scope '%s'\n", |
|---|
| | 518 | getpid(), p->name, fname_lc, function->common.scope->name); |
|---|
| | 519 | to->scope = function->common.scope; |
|---|
| | 520 | break; |
|---|
| | 521 | } |
|---|
| | 522 | } |
|---|
| | 523 | } else { |
|---|
| | 524 | to->scope = NULL; |
|---|
| | 525 | } |
|---|
| | 526 | } |
|---|
| | 527 | |
|---|
| | 528 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 529 | ea_debug_printf(EA_DEBUG, "[%d] %s's scope is '%s'\n", getpid(), |
|---|
| | 530 | from->function_name ? from->function_name : "(top)", to->scope ? to->scope->name : "NULL"); |
|---|
| | 531 | #endif |
|---|
| | 532 | if (from->type == ZEND_INTERNAL_FUNCTION) { |
|---|
| | 533 | zend_class_entry *class_entry = EAG(class_entry); |
|---|
| | 534 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 535 | ea_debug_printf(EA_DEBUG, "[%d] [internal function from=%08x,to=%08x] class_entry='%s' [%08x]\n", |
|---|
| | 536 | getpid(), from, to, class_entry->name, class_entry); |
|---|
| | 537 | if (class_entry) { |
|---|
| | 538 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 539 | ea_debug_printf(EA_DEBUG, "[%d] class_entry->parent='%s' [%08x]\n", |
|---|
| | 540 | getpid(), class_entry->parent->name, class_entry->parent); |
|---|
| | 541 | } |
|---|
| | 542 | if (class_entry != NULL && class_entry->parent != NULL && |
|---|
| | 543 | zend_hash_find(&class_entry->parent->function_table, |
|---|
| | 544 | #ifdef ZEND_ENGINE_2 |
|---|
| | 545 | fname_lc, fname_len + 1, |
|---|
| | 546 | #else |
|---|
| | 547 | to->function_name, strlen(to->function_name) + 1, |
|---|
| | 548 | #endif |
|---|
| | 549 | (void **) &function) == SUCCESS && function->type == ZEND_INTERNAL_FUNCTION) { |
|---|
| | 550 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 551 | ea_debug_printf(EA_DEBUG, "[%d] found in function table\n", getpid()); |
|---|
| | 552 | ((zend_internal_function *) (to))->handler = ((zend_internal_function *) function)->handler; |
|---|
| | 553 | } else { |
|---|
| | 554 | /* FIXME. I don't know how to fix handler. |
|---|
| | 555 | * TODO: must solve this somehow, to avoid returning damaged structure... |
|---|
| | 556 | */ |
|---|
| | 557 | ea_debug_pad(EA_DEBUG TSRMLS_CC); |
|---|
| | 558 | ea_debug_printf(EA_DEBUG, "[%d] can't find\n", getpid()); |
|---|
| | 559 | } |
|---|
| | 560 | return to; |
|---|
| | 561 | } |
|---|
| | 562 | to->opcodes = from->opcodes; |
|---|
| | 563 | to->last = to->size = from->last; |
|---|
| | 564 | to->T = from->T; |
|---|
| | 565 | to->brk_cont_array = from->brk_cont_array; |
|---|
| | 566 | to->last_brk_cont = from->last_brk_cont; |
|---|
| | 567 | /* |
|---|
| | 568 | to->current_brk_cont = -1; |
|---|
| | 569 | to->static_variables = from->static_variables; |
|---|
| | 570 | to->start_op = to->opcodes; |
|---|
| | 571 | to->backpatch_count = 0; |
|---|
| | 572 | */ |
|---|
| | 573 | to->return_reference = from->return_reference; |
|---|
| | 574 | to->done_pass_two = 1; |
|---|
| | 575 | to->filename = from->filename; |
|---|
| | 576 | #ifdef ZEND_ENGINE_2 |
|---|
| | 577 | /* HOESH: try & catch support */ |
|---|
| | 578 | to->try_catch_array = from->try_catch_array; |
|---|
| | 579 | to->last_try_catch = from->last_try_catch; |
|---|
| | 580 | to->uses_this = from->uses_this; |
|---|
| | 581 | |
|---|
| | 582 | to->line_start = from->line_start; |
|---|
| | 583 | to->line_end = from->line_end; |
|---|
| | 584 | to->doc_comment_len = from->doc_comment_len; |
|---|
| | 585 | to->doc_comment = from->doc_comment; |
|---|
| | 586 | /*??? |
|---|
| | 587 | if (from->doc_comment != NULL) { |
|---|
| | 588 | to->doc_comment = emalloc(from->doc_comment_len+1); |
|---|
| | 589 | memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len+1); |
|---|
| | 590 | } |
|---|
| | 591 | */ |
|---|
| | 592 | #else |
|---|
| | 593 | to->uses_globals = from->uses_globals; |
|---|
| | 594 | #endif |
|---|
| | 595 | if (from->static_variables) { |
|---|
| | 596 | to->static_variables = restore_zval_hash(NULL, from->static_variables); |
|---|
| | 597 | to->static_variables->pDestructor = ZVAL_PTR_DTOR; |
|---|
| 367 | | zend_bool incomplete_class = 0; |
|---|
| 368 | | char *class_name = (char *) zv->value.obj.ce; |
|---|
| 369 | | int name_len = 0; |
|---|
| 370 | | if (!EAG (compress)) { |
|---|
| 371 | | return; |
|---|
| 372 | | } |
|---|
| 373 | | if (class_name != NULL) { |
|---|
| 374 | | zend_class_entry *ce = NULL; |
|---|
| 375 | | name_len = strlen (class_name); |
|---|
| 376 | | if (zend_hash_find(CG (class_table), |
|---|
| 377 | | (void *) class_name, name_len + 1, |
|---|
| 378 | | (void **) &ce) != SUCCESS) { |
|---|
| 379 | | char *lowercase_name = |
|---|
| 380 | | estrndup (INCOMPLETE_CLASS, sizeof (INCOMPLETE_CLASS)); |
|---|
| 381 | | zend_str_tolower (lowercase_name, sizeof (INCOMPLETE_CLASS)); |
|---|
| 382 | | if (zend_hash_find(CG (class_table), lowercase_name, |
|---|
| 383 | | sizeof (INCOMPLETE_CLASS), |
|---|
| 384 | | (void **) &ce) != SUCCESS) { |
|---|
| 385 | | efree (lowercase_name); |
|---|
| 386 | | zend_error (E_ERROR, "EACCELERATOR can't restore object's class \"%s\"", |
|---|
| 387 | | class_name); |
|---|
| 388 | | } else { |
|---|
| 389 | | efree (lowercase_name); |
|---|
| 390 | | zv->value.obj.ce = ce; |
|---|
| 391 | | incomplete_class = 1; |
|---|
| 392 | | } |
|---|
| 393 | | } else { |
|---|
| 394 | | zv->value.obj.ce = ce; |
|---|
| 395 | | } |
|---|
| 396 | | } |
|---|
| 397 | | if (zv->value.obj.properties != NULL) { |
|---|
| 398 | | zv->value.obj.properties = |
|---|
| 399 | | restore_zval_hash (NULL, zv->value.obj.properties); |
|---|
| 400 | | zv->value.obj.properties->pDestructor = ZVAL_PTR_DTOR; |
|---|
| 401 | | /* Clearing references */ |
|---|
| 402 | | { |
|---|
| 403 | | Bucket *p = zv->value.obj.properties->pListHead; |
|---|
| 404 | | while (p != NULL) { |
|---|
| 405 | | ((zval *) (p->pDataPtr))->refcount = 1; |
|---|
| 406 | | p = p->pListNext; |
|---|
| 407 | | } |
|---|
| 408 | | } |
|---|
| 409 | | } |
|---|
| 410 | | if (incomplete_class && class_name != NULL) { |
|---|
| 411 | | zval *val; |
|---|
| 412 | | MAKE_STD_ZVAL (val); |
|---|
| 413 | | Z_TYPE_P (val) = IS_STRING; |
|---|
| 414 | | Z_STRVAL_P (val) = estrndup (class_name, name_len); |
|---|
| 415 | | Z_STRLEN_P (val) = name_len; |
|---|
| 416 | | zend_hash_update (Z_OBJPROP_P (zv), MAGIC_MEMBER, |
|---|
| 417 | | sizeof (MAGIC_MEMBER), &val, sizeof (val), |
|---|
| 418 | | NULL); |
|---|
| 419 | | } |
|---|
| 420 | | #endif |
|---|
| 421 | | return; |
|---|
| 422 | | } |
|---|
| 423 | | } |
|---|
| 424 | | } |
|---|
| 425 | | |
|---|
| 426 | | static void call_op_array_ctor_handler (zend_extension * extension, |
|---|
| 427 | | zend_op_array * op_array TSRMLS_DC) |
|---|
| 428 | | { |
|---|
| 429 | | if (extension->op_array_ctor) { |
|---|
| 430 | | extension->op_array_ctor (op_array); |
|---|
| 431 | | } |
|---|
| 432 | | } |
|---|
| 433 | | |
|---|
| 434 | | zend_op_array *restore_op_array (zend_op_array * to, |
|---|
| 435 | | eaccelerator_op_array * from TSRMLS_DC) |
|---|
| 436 | | { |
|---|
| 437 | | zend_function *function; |
|---|
| 438 | | |
|---|
| 439 | | #ifdef ZEND_ENGINE_2 |
|---|
| 440 | | int fname_len = 0; |
|---|
| 441 | | char *fname_lc = NULL; |
|---|
| 442 | | #endif |
|---|
| 443 | | |
|---|
| 444 | | ea_debug_pad (EA_DEBUG TSRMLS_CC); |
|---|
| 445 | | ea_debug_printf (EA_DEBUG, "[%d] restore_op_array: %s\n", getpid (), |
|---|
| 446 | | from->function_name ? from->function_name : "(top)"); |
|---|
| 447 | | |
|---|
| 448 | | if (from->type == ZEND_INTERNAL_FUNCTION) { |
|---|
| 449 | | if (to == NULL) { |
|---|
| 450 | | to = emalloc (sizeof (zend_internal_function)); |
|---|
| 451 | | } |
|---|
| 452 | | memset (to, 0, sizeof (zend_internal_function)); |
|---|
| 453 | | } else { |
|---|
| 454 | | if (to == NULL) { |
|---|
| 455 | | to = emalloc (sizeof (zend_op_array)); |
|---|
| 456 | | } |
|---|
| 457 | | memset (to, 0, sizeof (zend_op_array)); |
|---|
| 458 | | if (ZendOptimizer) { |
|---|
| 459 | | zend_llist_apply_with_argument (&zend_extensions, |
|---|
| 460 | | (llist_apply_with_arg_func_t) call_op_array_ctor_handler, |
|---|
| 461 | | to TSRMLS_CC); |
|---|
| 462 | | } |
|---|
| 463 | | } |
|---|
| 464 | | to->type = from->type; |
|---|
| 465 | | #ifdef ZEND_ENGINE_2 |
|---|
| 466 | | /* this is internal function's case |
|---|
| 467 | | * struct zend_internal_function |
|---|
| 468 | | zend_uchar type; |
|---|
| 469 | | char *function_name; |
|---|
| 470 | | zend_class_entry *scope; |
|---|
| 471 | | zend_uint fn_flags; |
|---|
| 472 | | union _zend_function *prototype; |
|---|
| 473 | | zend_uint num_args; |
|---|
| 474 | | zend_uint required_num_args; |
|---|
| 475 | | zend_arg_info *arg_info; |
|---|
| 476 | | zend_bool pass_rest_by_reference; |
|---|
| 477 | | unsigned char return_reference; |
|---|
| 478 | | */ |
|---|
| 479 | | /* |
|---|
| 480 | |
|---|