static void function_copy_ctor(zval *zv) /* {{{ */ { zend_function *old_func = Z_FUNC_P(zv); Z_FUNC_P(zv) = pemalloc(sizeof(zend_internal_function), 1); memcpy(Z_FUNC_P(zv), old_func, sizeof(zend_internal_function)); function_add_ref(Z_FUNC_P(zv)); }
static int timecop_func_override() { const struct timecop_override_func_entry *p; zend_function *zf_orig, *zf_ovrd, *zf_save; p = &(timecop_override_func_table[0]); while (p->orig_func != NULL) { zf_orig = zend_hash_str_find_ptr(EG(function_table), p->orig_func, strlen(p->orig_func)); if (zf_orig == NULL) { // Do nothing. Because some functions are introduced by optional extensions. p++; continue; } zf_ovrd = zend_hash_str_find_ptr(EG(function_table), p->ovrd_func, strlen(p->ovrd_func)); if (zf_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find function %s.", p->ovrd_func); p++; continue; } zf_save = zend_hash_str_find_ptr(EG(function_table), p->save_func, strlen(p->save_func)); if (zf_save != NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't create function %s because already exists.", p->save_func); p++; continue; } TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION); zend_hash_str_add_mem(EG(function_table), p->save_func, strlen(p->save_func), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func), zf_ovrd, sizeof(zend_internal_function)); function_add_ref(zf_ovrd); p++; } return SUCCESS; }
zend_function *duplicate_function(zend_function *func) { zend_function *new_function; if (func->type != ZEND_INTERNAL_FUNCTION) { new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, func, sizeof(zend_op_array)); function_add_ref(new_function); return new_function; } new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); memcpy(new_function, func, sizeof(zend_internal_function)); new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; function_add_ref(new_function); return new_function; }
static int timecop_class_override_clear() { const struct timecop_override_class_entry *p; zend_class_entry *ce_orig; zend_function *zf_orig, *zf_ovrd, *zf_save; p = &(timecop_override_class_table[0]); while (p->orig_class != NULL) { ce_orig = zend_hash_str_find_ptr(EG(class_table), p->orig_class, strlen(p->orig_class)); if (ce_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->orig_class); p++; continue; } zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (zf_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->orig_class, p->save_method); p++; continue; } zend_hash_str_update_mem(&ce_orig->function_table, p->orig_method, strlen(p->orig_method), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_del(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (strcmp(p->orig_method, "__construct") == 0) { ce_orig->constructor = zf_orig; } p++; } return SUCCESS; }
/* clear overrideed function. */ static int timecop_func_override_clear() { const struct timecop_override_func_entry *p; zend_function *zf_orig; p = &(timecop_override_func_table[0]); while (p->orig_func != NULL) { zf_orig = zend_hash_str_find_ptr(EG(function_table), p->save_func, strlen(p->save_func)); if (zf_orig == NULL) { p++; continue; } zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_del(EG(function_table), p->save_func, strlen(p->save_func)); p++; } return SUCCESS; }
static int timecop_class_override() { const struct timecop_override_class_entry *p; zend_class_entry *ce_orig, *ce_ovrd; zend_function *zf_orig, *zf_ovrd, *zf_save, *zf_new; p = &(timecop_override_class_table[0]); while (p->orig_class != NULL) { ce_orig = zend_hash_str_find_ptr(EG(class_table), p->orig_class, strlen(p->orig_class)); if (ce_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->orig_class); p++; continue; } ce_ovrd = zend_hash_str_find_ptr(EG(class_table), p->ovrd_class, strlen(p->ovrd_class)); if (ce_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->ovrd_class); p++; continue; } zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table, p->orig_method, strlen(p->orig_method)); if (zf_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->orig_class, p->orig_method); p++; continue; } zf_ovrd = zend_hash_str_find_ptr(&ce_ovrd->function_table, p->orig_method, strlen(p->orig_method)); if (zf_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->ovrd_class, p->orig_method); p++; continue; } zf_save = zend_hash_str_find_ptr(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (zf_save != NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't create method %s::%s because already exists.", p->orig_class, p->save_method); p++; continue; } TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(ce_orig->type & ZEND_INTERNAL_CLASS); TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(ce_ovrd->type & ZEND_INTERNAL_CLASS); zend_hash_str_add_mem(&ce_orig->function_table, p->save_method, strlen(p->save_method), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zf_new = zend_hash_str_update_mem(&ce_orig->function_table, p->orig_method, strlen(p->orig_method), zf_ovrd, sizeof(zend_internal_function)); function_add_ref(zf_ovrd); TIMECOP_ASSERT(zf_new != NULL); TIMECOP_ASSERT(zf_new != zf_orig); if (strcmp(p->orig_method, "__construct") == 0) { ce_orig->constructor = zf_new; } p++; } return SUCCESS; }