Skip to content

Commit

Permalink
Changed "instanceof" and "catch" operators, is_a() and is_subclass_of…
Browse files Browse the repository at this point in the history
…() functions to not call __autoload().
  • Loading branch information
dstogov committed Sep 9, 2005
1 parent 26bf79a commit 9305339
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 10 deletions.
2 changes: 2 additions & 0 deletions NEWS
@@ -1,6 +1,8 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? Aug 2005, PHP 5.1 Release Candidate 2
- Changed "instanceof" and "catch" operators, is_a() and is_subclass_of()
functions to not call __autoload(). (Dmitry)
- Added support for class constants and static members for internal
classes. (Dmitry, Michael Wallner)
- Added "new_link" parameter to mssql_connect(). Bug #34369. (Frank)
Expand Down
23 changes: 23 additions & 0 deletions Zend/tests/catch.phpt
@@ -0,0 +1,23 @@
--TEST--
catch shouldn't call __autoload
--FILE--
<?php
function __autoload($name) {
echo("AUTOLOAD '$name'\n");
eval("class $name {}");
}


try {
} catch (A $e) {
}

try {
throw new Exception();
} catch (B $e) {
} catch (Exception $e) {
echo "ok\n";
}
?>
--EXPECT--
ok
18 changes: 18 additions & 0 deletions Zend/tests/instanceof.phpt
@@ -0,0 +1,18 @@
--TEST--
instanceof shouldn't call __autoload
--FILE--
<?php
function __autoload($name) {
echo("AUTOLOAD '$name'\n");
eval("class $name {}");
}

class A {
}
$a = new A;
var_dump($a instanceof B);
var_dump($a instanceof A);
?>
--EXPECT--
bool(false)
bool(true)
51 changes: 51 additions & 0 deletions Zend/tests/is_a.phpt
@@ -0,0 +1,51 @@
--TEST--
is_a() and is_subclass_of() shouldn't call __autoload
--INI--
error_reporting=4095
--FILE--
<?php
function __autoload($name) {
echo("AUTOLOAD '$name'\n");
eval("class $name {}");
}

class BASE {
}

interface INT {
}

class A extends BASE implements INT {
}

$a = new A;
var_dump(is_a($a, "B1"));
var_dump(is_a($a, "A"));
var_dump(is_a($a, "BASE"));
var_dump(is_a($a, "INT"));
var_dump(is_subclass_of($a, "B2"));
var_dump(is_subclass_of($a, "A"));
var_dump(is_subclass_of($a, "BASE"));
var_dump(is_subclass_of($a, "INT"));

var_dump(is_subclass_of("X1", "X2"));
?>
--EXPECTF--
Strict Standards: is_a(): Deprecated. Please use the instanceof operator in %sis_a.php on line 17
bool(false)

Strict Standards: is_a(): Deprecated. Please use the instanceof operator in %sis_a.php on line 18
bool(true)

Strict Standards: is_a(): Deprecated. Please use the instanceof operator in %sis_a.php on line 19
bool(true)

Strict Standards: is_a(): Deprecated. Please use the instanceof operator in %sis_a.php on line 20
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
AUTOLOAD 'X1'
AUTOLOAD 'X2'
bool(false)
2 changes: 1 addition & 1 deletion Zend/zend_builtin_functions.c
Expand Up @@ -625,7 +625,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)

convert_to_string_ex(class_name);

if (zend_lookup_class(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), &ce TSRMLS_CC) == FAILURE) {
if (zend_lookup_class_ex(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), (instance_ce != NULL), &ce TSRMLS_CC) == FAILURE) {
retval = 0;
} else {
if (only_subclass) {
Expand Down
18 changes: 17 additions & 1 deletion Zend/zend_compile.c
Expand Up @@ -1712,6 +1712,13 @@ void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var,
long catch_op_number = get_next_op_number(CG(active_op_array));
zend_op *opline;

if (catch_op_number > 0) {
opline = &CG(active_op_array)->opcodes[catch_op_number-1];
if (opline->opcode == ZEND_FETCH_CLASS) {
opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
}
}

opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CATCH;
opline->op1 = *catch_class;
Expand Down Expand Up @@ -3468,8 +3475,17 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC

void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
int last_op_number = get_next_op_number(CG(active_op_array));
zend_op *opline;

if (last_op_number > 0) {
opline = &CG(active_op_array)->opcodes[last_op_number-1];
if (opline->opcode == ZEND_FETCH_CLASS) {
opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
}
}

opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INSTANCEOF;
opline->result.op_type = IS_TMP_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_compile.h
Expand Up @@ -583,7 +583,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_FETCH_CLASS_GLOBAL 4
#define ZEND_FETCH_CLASS_AUTO 5
#define ZEND_FETCH_CLASS_INTERFACE 6

#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80

/* variable parsing type (compile-time) */
#define ZEND_PARSED_MEMBER (1<<0)
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_execute.h
Expand Up @@ -65,6 +65,7 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI
}
}
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);

Expand Down
24 changes: 17 additions & 7 deletions Zend/zend_execute_API.c
Expand Up @@ -908,7 +908,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}


ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC)
{
zval **args[1];
zval autoload_function;
Expand Down Expand Up @@ -936,7 +936,7 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
* (doesn't impact fuctionality of __autoload()
*/
if (zend_is_compiling(TSRMLS_C)) {
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
free_alloca(lc_name);
return FAILURE;
}
Expand Down Expand Up @@ -1004,6 +1004,11 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
return retval;
}

ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
{
return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
}

ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
{
zval pv;
Expand Down Expand Up @@ -1329,7 +1334,9 @@ void zend_unset_timeout(TSRMLS_D)
zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
{
zend_class_entry **pce;
int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;

fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD;
check_fetch_type:
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
Expand All @@ -1354,12 +1361,15 @@ zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fe
break;
}

if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_error(E_ERROR, "Interface '%s' not found", class_name);
} else {
zend_error(E_ERROR, "Class '%s' not found", class_name);
if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) {
if (use_autoload) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_error(E_ERROR, "Interface '%s' not found", class_name);
} else {
zend_error(E_ERROR, "Class '%s' not found", class_name);
}
}
return NULL;
}
return *pce;
}
Expand Down

0 comments on commit 9305339

Please sign in to comment.