Skip to content

fix tests in Zend #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Dec 22, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5ea5070
Initial concept draft of new zend autoloader
ircmaxell Aug 29, 2013
b2f0734
More progress
ircmaxell Aug 30, 2013
d10dc03
More work, fixing memleaks and behavior
ircmaxell Aug 30, 2013
1155888
Merge branch 'use-function' of github.com:igorw/php-src into function…
ircmaxell Aug 30, 2013
191c149
Merge branch 'use-function' of github.com:igorw/php-src into function…
ircmaxell Aug 30, 2013
5e71fb5
Refactor out the lookup in is_callable
ircmaxell Aug 30, 2013
2efdc97
Remove lowercasing components
ircmaxell Aug 30, 2013
6aa5b03
Fix memory leak, and clean up a bit
ircmaxell Aug 30, 2013
e570462
Merge remote-tracking branch 'upstream/PHP-5.6' into function-autoloa…
igorw Dec 11, 2013
dd32908
Merge branch 'function-autoloading' of https://github.com/igorw/php-s…
krakjoe Dec 21, 2013
cdac9d7
fix build
krakjoe Dec 21, 2013
4daa114
Merge branch 'master' of https://github.com/php/php-src into function…
krakjoe Dec 21, 2013
8657f77
fix call to unload
krakjoe Dec 21, 2013
8a73ed4
fix build
krakjoe Dec 21, 2013
f16b075
fix patch, run tests
krakjoe Dec 21, 2013
dfa13d9
plug leaks
krakjoe Dec 21, 2013
c34abb5
fix most tests in Zend, three remain
krakjoe Dec 22, 2013
cfa2f6f
fix register autoload array callable
krakjoe Dec 22, 2013
3cf2f1f
fix error conditions test, prototype for function_exists
krakjoe Dec 22, 2013
2212f24
correct test
krakjoe Dec 22, 2013
e2d73a2
be compatible with phpdbg
krakjoe Dec 22, 2013
2b68179
fix zts build
krakjoe Dec 22, 2013
92fe949
all tests pass
krakjoe Dec 22, 2013
ed22ad9
remove debug printing, add author line
krakjoe Dec 22, 2013
530db35
Merge branch 'master' of https://git.php.net/push/php-src into functi…
krakjoe Dec 22, 2013
c1b56c0
...
krakjoe Dec 22, 2013
202921e
Merge branch 'master' of https://git.php.net/push/php-src into functi…
krakjoe Dec 22, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Zend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ libZend_la_SOURCES=\
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c zend_virtual_cwd.c zend_ast.c
zend_generators.c zend_autoload.c zend_virtual_cwd.c zend_ast.c

libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/bug61011.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Bug #61011 (Crash when an exception is thrown by __autoload accessing a static p
function __autoload($name) {
throw new Exception($name);
}
try {
try {
echo AAA::$a; //zend_fetch_var_address_helper
} catch (Exception $e) {
try {
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/function_exists_error.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Test function_exists() function : error conditions
--FILE--
<?php
/*
* proto bool function_exists(string function_name)
* proto bool function_exists(string function_name [, boolean autoload = true])
* Function is implemented in Zend/zend_builtin_functions.c
*/

Expand All @@ -13,7 +13,7 @@ $arg_0 = "ABC";
$extra_arg = 1;

echo "\nToo many arguments\n";
var_dump(function_exists($arg_0, $extra_arg));
var_dump(function_exists($arg_0, true, $extra_arg));

echo "\nToo few arguments\n";
var_dump(function_exists());
Expand All @@ -25,12 +25,12 @@ var_dump(function_exists());

Too many arguments

Warning: function_exists() expects exactly 1 parameter, 2 given in %s on line %d
Warning: function_exists() expects at most 2 parameters, 3 given in %s on line %d
NULL

Too few arguments

Warning: function_exists() expects exactly 1 parameter, 0 given in %s on line %d
Warning: function_exists() expects at least 1 parameter, 0 given in %s on line %d
NULL
===Done===

2 changes: 2 additions & 0 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
#endif
EG(saved_fpu_cw_ptr) = NULL;
EG(active) = 0;
EG(autoload_legacy) = NULL;
EG(autoload_stack) = NULL;
}
/* }}} */

Expand Down
1 change: 1 addition & 0 deletions Zend/zend.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_LEXICAL_VAR 0x020
#define IS_LEXICAL_REF 0x040
#define IS_CONSTANT_IN_NAMESPACE 0x100
#define IS_CONSTANT_IN_AUTOLOAD 0x200

#define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST)

Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2770,7 +2770,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
}
/* Check if function with given name exists.
* This may be a compound name that includes namespace name */
if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
if (ZEND_LOOKUP_FUNCTION_BY_NAME(lmname, mlen, &fcc->function_handler)) {
efree(lmname);
return 1;
}
Expand Down
284 changes: 284 additions & 0 deletions Zend/zend_autoload.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Anthony Ferrara <[email protected]> |
| Authors: Joe Watkins <[email protected]> |
+----------------------------------------------------------------------+
*/

/* $Id$ */

#include "zend.h"
#include "zend_API.h"
#include "zend_execute.h"
#include "zend_globals.h"
#include "zend_globals_macros.h"
#include "zend_autoload.h"
#include "zend_hash.h"
#include "zend_execute.h"
#include "zend_interfaces.h"
#include "zend_exceptions.h"

static char* zend_autoload_get_name_key(zend_fcall_info *fci, zend_fcall_info_cache *fcc, int *length, zend_bool *do_free TSRMLS_DC);
static void zend_autoload_func_dtor(zend_autoload_func *func);

int zend_autoload_call(const zval* name, long type TSRMLS_DC)
{
zval *ztype, *retval = NULL;
char *lc_name;
int lc_length;
HashTable *symbol_table;
HashPosition function_pos;
zend_autoload_func *func_info;
char dummy = 1;

if (Z_TYPE_P(name) != IS_STRING) {
return FAILURE;
}

switch (type) {
case ZEND_AUTOLOAD_CLASS:
symbol_table = EG(class_table);
break;
case ZEND_AUTOLOAD_FUNCTION:
symbol_table = EG(function_table);
break;
case ZEND_AUTOLOAD_CONSTANT:
symbol_table = EG(zend_constants);
break;
default:
return FAILURE;
}

lc_length = Z_STRLEN_P(name);
lc_name = zend_str_tolower_dup(Z_STRVAL_P(name), lc_length);

/* run legacy autoloader */
{
zend_bool loaded = 0;

if (EG(autoload_funcs) == NULL || EG(autoload_funcs)->nNumOfElements == 0) {
if (type == ZEND_AUTOLOAD_CLASS
&& (
EG(autoload_legacy) != NULL
|| zend_lookup_function_ex(ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME), NULL, 0, &EG(autoload_legacy) TSRMLS_CC) == SUCCESS
)
) {
zend_call_method_with_1_params(NULL, NULL, &EG(autoload_legacy), ZEND_AUTOLOAD_FUNC_NAME, &retval, (zval*) name);
loaded = zend_hash_exists(
symbol_table, lc_name, lc_length + 1);
if (retval) {
zval_ptr_dtor(&retval);
}
}
efree(lc_name);

return (loaded) ? SUCCESS : FAILURE;
}
}

if (EG(autoload_stack) == NULL) {
ALLOC_HASHTABLE(EG(autoload_stack));
zend_hash_init(EG(autoload_stack), 0, NULL, NULL, 0);
}

if (zend_hash_add(EG(autoload_stack), lc_name, lc_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
efree(lc_name);
return FAILURE;
}

MAKE_STD_ZVAL(ztype);
ZVAL_LONG(ztype, type);

zend_hash_internal_pointer_reset_ex(EG(autoload_funcs), &function_pos);
while(zend_hash_has_more_elements_ex(EG(autoload_funcs), &function_pos) == SUCCESS) {
zend_hash_get_current_data_ex(EG(autoload_funcs), (void **) &func_info, &function_pos);
if (func_info->type & type) {
func_info->fci.retval_ptr_ptr = &retval;
zend_fcall_info_argn(&func_info->fci TSRMLS_CC, 2, &name, &ztype);
zend_call_function(&func_info->fci, &func_info->fcc TSRMLS_CC);
zend_exception_save(TSRMLS_C);
if (retval) {
zval_ptr_dtor(&retval);
retval = NULL;
}
if (zend_hash_exists(symbol_table, lc_name, lc_length + 1)) {
break;
}
}
zend_hash_move_forward_ex(EG(autoload_funcs), &function_pos);
}
zend_fcall_info_args_clear(&func_info->fci, 1);
zend_exception_restore(TSRMLS_C);

zval_ptr_dtor(&ztype);
zend_hash_del(EG(autoload_stack), lc_name, lc_length);
efree(lc_name);
return SUCCESS;
}

#define HT_MOVE_TAIL_TO_HEAD(ht) \
(ht)->pListTail->pListNext = (ht)->pListHead; \
(ht)->pListHead = (ht)->pListTail; \
(ht)->pListTail = (ht)->pListHead->pListLast; \
(ht)->pListHead->pListNext->pListLast = (ht)->pListHead;\
(ht)->pListTail->pListNext = NULL; \
(ht)->pListHead->pListLast = NULL;

static char* zend_autoload_get_name_key(zend_fcall_info *fci, zend_fcall_info_cache *fcc, int *length, zend_bool *do_free TSRMLS_DC) {
char *name;
switch (Z_TYPE_P(fci->function_name)) {
case IS_STRING:
*length = Z_STRLEN_P(fci->function_name);
return Z_STRVAL_P(fci->function_name);
break;
case IS_OBJECT:
*length = sizeof(zend_object_handle);
name = emalloc(*length + 1);
*do_free = 1;
memcpy(name, &Z_OBJ_HANDLE_P(fci->function_name), *length);
name[*length] = '\0';
return name;
break;
case IS_ARRAY:
if (fcc->function_handler->common.scope) {
zend_function *func = fcc->function_handler;
zend_class_entry *ce = func->common.scope;

*do_free = 1;
if (ce) {
*length = strlen(func->common.function_name) + ce->name_length + 2;
name = emalloc(*length + 1);
memcpy(name, ce->name, ce->name_length);
memcpy(&name[ce->name_length], "::", sizeof("::")-1);
memcpy(&name[ce->name_length+sizeof("::")-1],
func->common.function_name, strlen(func->common.function_name));
name[*length] = 0;
return name;
}
}
break;
default:
return 0;
}

return 0;
}

static void zend_autoload_func_dtor(zend_autoload_func *func) {
if (func->callable) {
zval_ptr_dtor(&func->callable);
}
}

int zend_autoload_register(zend_autoload_func *func, zend_bool prepend TSRMLS_DC)
{
char *lc_name;
zend_bool do_free = 0;
int lc_length, status = SUCCESS;

lc_name = zend_autoload_get_name_key(&func->fci, &func->fcc, &lc_length, &do_free TSRMLS_CC);
if (lc_name == 0) {
zend_error_noreturn(E_ERROR, "Unknown Function Name Type Provided");
}

if (!EG(autoload_funcs)) {
ALLOC_HASHTABLE(EG(autoload_funcs));
zend_hash_init(EG(autoload_funcs), 1, NULL, (dtor_func_t) zend_autoload_func_dtor, 0);
} else if (zend_hash_exists(EG(autoload_funcs), lc_name, lc_length + 1)) {
if (do_free) {
efree(lc_name);
}
return FAILURE;
}

if (zend_hash_add(EG(autoload_funcs), lc_name, lc_length + 1, (void**) func, sizeof(zend_autoload_func), NULL) == FAILURE) {
status = FAILURE;
} else if (prepend) {
HT_MOVE_TAIL_TO_HEAD(EG(autoload_funcs));
}
if (do_free) {
efree(lc_name);
}
return status;
}

int zend_autoload_unregister(zval *callable TSRMLS_DC)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
char *lc_name;
zend_bool do_free = 0;
int lc_length;

if (zend_fcall_info_init(callable, 0, &fci, &fcc, NULL, NULL TSRMLS_CC) == FAILURE) {
return FAILURE;
}

lc_name = zend_autoload_get_name_key(&fci, &fcc, &lc_length, &do_free TSRMLS_CC);
if (lc_name == 0) {
return FAILURE;
}

zend_hash_del(EG(autoload_funcs), lc_name, lc_length);
if (do_free) {
efree(lc_name);
}

return SUCCESS;
}

ZEND_FUNCTION(autoload_register)
{
zval *callable;
zend_autoload_func *func;
zend_bool prepend = 0;
long type = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|lb", &callable, &type, &prepend) == FAILURE) {
return;
}

func = emalloc(sizeof(zend_autoload_func));

if (zend_fcall_info_init(callable, 0, &func->fci, &func->fcc, NULL, NULL TSRMLS_CC) == FAILURE) {
efree(func);
zend_error_noreturn(E_ERROR, "Expecting a valid callback");
}

func->callable = callable;
Z_ADDREF_P(callable);

if (!type) {
func->type = ZEND_AUTOLOAD_ALL;
} else {
func->type = type;
}

if (zend_autoload_register(func, prepend TSRMLS_CC) == FAILURE) {
zval_ptr_dtor(&callable);
}
efree(func);
}

ZEND_FUNCTION(autoload_unregister)
{
zval *callable;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callable) == FAILURE) {
return;
}
RETVAL_BOOL(zend_autoload_unregister(callable TSRMLS_CC) == SUCCESS);
}

Loading