diff options
Diffstat (limited to 'Zend')
83 files changed, 2748 insertions, 479 deletions
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 8b9dd7b35..18480b514 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -1,5 +1,5 @@ dnl -dnl $Id: Zend.m4,v 1.43.2.4 2005/03/10 09:50:37 hyanantha Exp $ +dnl $Id: Zend.m4,v 1.43.2.5 2005/06/07 17:22:56 sniper Exp $ dnl dnl This file contains Zend specific autoconf functions. dnl @@ -136,6 +136,15 @@ AC_ARG_ENABLE(debug, AC_DEFUN([LIBZEND_OTHER_CHECKS],[ +AC_ARG_ENABLE(zend-memory-manager, +[ --disable-zend-memory-manager + Disable the Zend memory manager - FOR DEVELOPERS ONLY!!], +[ + ZEND_USE_ZEND_ALLOC=$enableval +], [ + ZEND_USE_ZEND_ALLOC=yes +]) + AC_ARG_ENABLE(maintainer-zts, [ --enable-maintainer-zts Enable thread safety - for code maintainers only],[ ZEND_MAINTAINER_ZTS=$enableval @@ -165,6 +174,9 @@ AC_ARG_ENABLE(zend-multibyte, ZEND_MULTIBYTE=no ]) +AC_MSG_CHECKING(whether to enable the Zend memory manager) +AC_MSG_RESULT($ZEND_USE_ZEND_ALLOC) + AC_MSG_CHECKING(whether to enable thread-safety) AC_MSG_RESULT($ZEND_MAINTAINER_ZTS) @@ -195,6 +207,12 @@ fi test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS" +if test "$ZEND_USE_ZEND_ALLOC" = "yes"; then + AC_DEFINE(USE_ZEND_ALLOC,1,[Use Zend memory manager]) +else + AC_DEFINE(USE_ZEND_ALLOC,0,[Use Zend memory manager]) +fi + if test "$ZEND_MAINTAINER_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) CFLAGS="$CFLAGS -DZTS" diff --git a/Zend/acconfig.h b/Zend/acconfig.h index cedd29a04..42f679b4d 100644 --- a/Zend/acconfig.h +++ b/Zend/acconfig.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: acconfig.h,v 1.34.2.2 2005/03/11 06:51:01 hyanantha Exp $ */ +/* $Id: acconfig.h,v 1.34.2.3 2005/07/29 09:20:02 hyanantha Exp $ */ #define ZEND_API #define ZEND_DLEXPORT @@ -98,6 +98,13 @@ int zend_sprintf(char *buffer, const char *format, ...); #endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */ +#ifdef NETWARE +#ifdef USE_WINSOCK +#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T +#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H +#endif +#endif + /* * Local variables: * tab-width: 4 diff --git a/Zend/tests/bug20240.phpt b/Zend/tests/bug20240.phpt index acf673a27..439504400 100755 --- a/Zend/tests/bug20240.phpt +++ b/Zend/tests/bug20240.phpt @@ -39,5 +39,5 @@ echo "Done\n"; 2 3 Done -test::destructor test::__destruct +test::destructor diff --git a/Zend/tests/bug22836.phpt b/Zend/tests/bug22836.phpt index ceaf6414b..3cbc95493 100644 --- a/Zend/tests/bug22836.phpt +++ b/Zend/tests/bug22836.phpt @@ -64,11 +64,3 @@ string(3) "foo" Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d -string(3) "foo" -'foo' - -Notice: Undefined variable: a in %s on line %d - -Strict Standards: Only variable references should be returned by reference in %s on line %d - - diff --git a/Zend/tests/bug27268.phpt b/Zend/tests/bug27268.phpt new file mode 100755 index 000000000..3c34c90fc --- /dev/null +++ b/Zend/tests/bug27268.phpt @@ -0,0 +1,28 @@ +--TEST--
+Bug #27268 (Bad references accentuated by clone)
+--FILE--
+<?php
+class A
+{
+ public function &getA()
+ {
+ return $this->a;
+ }
+}
+
+$A = new A;
+$A->a = array(1);
+$x = $A->getA();
+$clone = clone $A;
+$clone->a = array();
+print_r($A);
+?>
+--EXPECT--
+A Object
+(
+ [a] => Array
+ (
+ [0] => 1
+ )
+
+)
diff --git a/Zend/tests/bug27304.phpt b/Zend/tests/bug27304.phpt new file mode 100755 index 000000000..51e392d59 --- /dev/null +++ b/Zend/tests/bug27304.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #27304 +--FILE-- +<?php + +class Staticexample +{ + static function test() + { + var_dump(isset($this)); + } +} + +$b = new Staticexample(); +Staticexample::test(); +$b->test(); + +?> +===DONE=== +--EXPECT-- +bool(false) +bool(false) +===DONE=== diff --git a/Zend/tests/bug27598.phpt b/Zend/tests/bug27598.phpt new file mode 100755 index 000000000..6ec229b60 --- /dev/null +++ b/Zend/tests/bug27598.phpt @@ -0,0 +1,12 @@ +--TEST--
+Bug #27598 (list() array key assignment causes HUGE memory leak)
+--FILE--
+<?php
+list($out[0]) = array(1);
+var_dump($out);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ int(1)
+}
diff --git a/Zend/tests/bug28377.phpt b/Zend/tests/bug28377.phpt new file mode 100755 index 000000000..69c8b3dc3 --- /dev/null +++ b/Zend/tests/bug28377.phpt @@ -0,0 +1,23 @@ +--TEST--
+Bug #28377 (debug_backtrace is intermittently passing args)
+--FILE--
+<?php
+function doit($a, $b)
+{
+ $trace = debug_backtrace();
+ custom_callback('dereferenced', $trace);
+ custom_callback('direct', debug_backtrace());
+}
+
+function custom_callback($traceName, $btInfo)
+{
+ echo $traceName ." -- args: ";
+ echo isset($btInfo[0]['args']) ? count($btInfo[0]['args']) : 'does not exist';
+ echo "\n";
+}
+
+doit('a','b');
+?>
+--EXPECT--
+dereferenced -- args: 2
+direct -- args: 2
diff --git a/Zend/tests/bug29015.phpt b/Zend/tests/bug29015.phpt new file mode 100644 index 000000000..6c18ab8a0 --- /dev/null +++ b/Zend/tests/bug29015.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #29015 (Incorrect behavior of member vars(non string ones)-numeric mem vars und others) +--FILE-- +<?php +$a = new stdClass(); +$x = ""; +$a->$x = "string('')"; +var_dump($a); +?> +--EXPECTF-- +Fatal error: Cannot access empty property in %sbug29015.php on line 4 diff --git a/Zend/tests/bug29104.phpt b/Zend/tests/bug29104.phpt new file mode 100644 index 000000000..4b3948887 --- /dev/null +++ b/Zend/tests/bug29104.phpt @@ -0,0 +1,27 @@ +--TEST--
+Bug #29104 Function declaration in method doesn't work
+--FILE--
+<?php
+class A
+{
+ function g()
+ {
+ echo "function g - begin\n";
+
+ function f()
+ {
+ echo "function f\n";
+ }
+
+ echo "function g - end\n";
+ }
+}
+
+$a = new A;
+$a->g();
+f();
+?>
+--EXPECT--
+function g - begin
+function g - end
+function f
diff --git a/Zend/tests/bug29210.phpt b/Zend/tests/bug29210.phpt new file mode 100644 index 000000000..f43ff57f5 --- /dev/null +++ b/Zend/tests/bug29210.phpt @@ -0,0 +1,104 @@ +--TEST--
+Bug #29210 Function: is_callable - no support for private and protected classes
+--FILE--
+<?php
+class test_class {
+ private function test_func1() {
+ echo "test_func1\n";
+ }
+ protected function test_func2() {
+ echo "test_func2\n";
+ }
+ static private function test_func3() {
+ echo "test_func3\n";
+ }
+ static protected function test_func4() {
+ echo "test_func4\n";
+ }
+ function test() {
+ if (is_callable(array($this,'test_func1'))) {
+ $this->test_func1();
+ } else {
+ echo "test_func1 isn't callable from inside\n";
+ }
+ if (is_callable(array($this,'test_func2'))) {
+ $this->test_func2();
+ } else {
+ echo "test_func2 isn't callable from inside\n";
+ }
+ if (is_callable(array('test_class','test_func3'))) {
+ test_class::test_func3();
+ } else {
+ echo "test_func3 isn't callable from inside\n";
+ }
+ if (is_callable(array('test_class','test_func4'))) {
+ test_class::test_func4();
+ } else {
+ echo "test_func4 isn't callable from inside\n";
+ }
+ }
+}
+
+class foo extends test_class {
+ function test() {
+ if (is_callable(array($this,'test_func1'))) {
+ $this->test_func1();
+ } else {
+ echo "test_func1 isn't callable from child\n";
+ }
+ if (is_callable(array($this,'test_func2'))) {
+ $this->test_func2();
+ } else {
+ echo "test_func2 isn't callable from child\n";
+ }
+ if (is_callable(array('test_class','test_func3'))) {
+ test_class::test_func3();
+ } else {
+ echo "test_func3 isn't callable from child\n";
+ }
+ if (is_callable(array('test_class','test_func4'))) {
+ test_class::test_func4();
+ } else {
+ echo "test_func4 isn't callable from child\n";
+ }
+ }
+}
+
+$object = new test_class;
+$object->test();
+if (is_callable(array($object,'test_func1'))) {
+ $object->test_func1();
+} else {
+ echo "test_func1 isn't callable from outside\n";
+}
+if (is_callable(array($object,'test_func2'))) {
+ $object->test_func2();
+} else {
+ echo "test_func2 isn't callable from outside\n";
+}
+if (is_callable(array('test_class','test_func3'))) {
+ test_class::test_func3();
+} else {
+ echo "test_func3 isn't callable from outside\n";
+}
+if (is_callable(array('test_class','test_func4'))) {
+ test_class::test_func4();
+} else {
+ echo "test_func4 isn't callable from outside\n";
+}
+$object = new foo();
+$object->test();
+?>
+--EXPECT--
+test_func1
+test_func2
+test_func3
+test_func4
+test_func1 isn't callable from outside
+test_func2 isn't callable from outside
+test_func3 isn't callable from outside
+test_func4 isn't callable from outside
+test_func1 isn't callable from child
+test_func2
+test_func3 isn't callable from child
+test_func4
diff --git a/Zend/tests/bug29689.phpt b/Zend/tests/bug29689.phpt new file mode 100644 index 000000000..74dabc159 --- /dev/null +++ b/Zend/tests/bug29689.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #29689 (default value of protected member overrides default value of private) +--FILE-- +<?php +class foo { + private $foo = 'foo'; + private $foo2 = 'foo2'; + + function printFoo() + { + echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n"; + } +} + +class bar extends foo { + protected $foo = 'bar'; + + function printFoo() + { + parent::printFoo(); + echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n"; + } +} + +class baz extends bar { + protected $foo = 'baz'; + protected $foo2 = 'baz2'; +} + +class bar2 extends foo { + function printFoo() + { + parent::printFoo(); + echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n"; + } +} + +class baz2 extends bar2 { + protected $foo = 'baz2'; + protected $foo2 = 'baz22'; +} + +$bar = new bar; +$bar->printFoo(); +echo "---baz--\n"; +$baz = new baz(); +$baz->printFoo(); +echo "---baz2--\n"; +$baz = new baz2(); +$baz->printFoo(); +?> +--EXPECTF-- +foo: foo foo2 +bar: bar +Notice: Undefined property: bar::$foo2 in %s on line %d + +---baz-- +foo: foo foo2 +bar: baz baz2 +---baz2-- +foo: foo foo2 +bar2: baz2 baz22 diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt new file mode 100644 index 000000000..17ed5afa3 --- /dev/null +++ b/Zend/tests/bug29890.phpt @@ -0,0 +1,23 @@ +--TEST--
+Bug #29890 (crash if error handler fails)
+--FILE--
+<?php
+function customErrorHandler($fErrNo,$fErrStr,$fErrFile,$fErrLine,&$fClass) {
+echo "error :".$fErrStr."\n";
+}
+
+set_time_limit(5);
+
+error_reporting(E_ALL);
+
+set_error_handler("customErrorHandler");
+
+define("TEST",2);
+
+//should return a notice that the constant is already defined
+
+define("TEST",3);
+
+?>
+--EXPECT--
+error :Constant TEST already defined
diff --git a/Zend/tests/bug29896.phpt b/Zend/tests/bug29896.phpt new file mode 100755 index 000000000..34d43522d --- /dev/null +++ b/Zend/tests/bug29896.phpt @@ -0,0 +1,28 @@ +--TEST--
+Bug #29896 (Backtrace argument list out of sync)
+--FILE--
+<?php
+function userErrorHandler($num, $msg, $file, $line, $vars)
+{
+ debug_print_backtrace();
+}
+
+$OldErrorHandler = set_error_handler("userErrorHandler");
+
+function GenerateError1($A1)
+{
+ $a = $b;
+}
+
+function GenerateError2($A1)
+{
+ GenerateError1("Test1");
+}
+
+GenerateError2("Test2");
+?>
+--EXPECTF--
+#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11, Array ([A1] => Test1)) called at [%sbug29896.php:11]
+#1 GenerateError1(Test1) called at [%sbug29896.php:16]
+#2 GenerateError2(Test2) called at [%sbug29896.php:19]
+
diff --git a/Zend/tests/bug29944.phpt b/Zend/tests/bug29944.phpt new file mode 100644 index 000000000..2cb42ebb0 --- /dev/null +++ b/Zend/tests/bug29944.phpt @@ -0,0 +1,16 @@ +--TEST--
+Bug #29944 (Function defined in switch, crashes)
+--FILE--
+<?php
+$a = 1;
+switch ($a) {
+ case 1:
+ function foo($a) {
+ return "ok\n";
+ }
+ echo foo($a);
+}
+?>
+--EXPECT--
+ok
+
diff --git a/Zend/tests/bug30080.phpt b/Zend/tests/bug30080.phpt new file mode 100755 index 000000000..80a70147d --- /dev/null +++ b/Zend/tests/bug30080.phpt @@ -0,0 +1,18 @@ +--TEST--
+Bug #30080 (Passing array or non array of objects)
+--FILE--
+<?php
+class foo {
+ function foo($arrayobj) {
+ var_dump($arrayobj);
+ }
+}
+
+new foo(array(new stdClass));
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ object(stdClass)#2 (0) {
+ }
+}
diff --git a/Zend/tests/bug30140.phpt b/Zend/tests/bug30140.phpt new file mode 100755 index 000000000..eb7f9cb37 --- /dev/null +++ b/Zend/tests/bug30140.phpt @@ -0,0 +1,30 @@ +--TEST--
+Bug #30140 (Problem with array in static properties)
+--FILE--
+<?php
+class A {
+ public static $test1 = true;
+ public static $test2 = array();
+ public static $test3 = "str";
+}
+
+class B extends A {
+}
+
+A::$test1 = "x";
+A::$test2 = "y";
+A::$test3 = "z";
+var_dump(A::$test1);
+var_dump(A::$test2);
+var_dump(A::$test3);
+var_dump(B::$test1);
+var_dump(B::$test2);
+var_dump(B::$test3);
+?>
+--EXPECT--
+string(1) "x"
+string(1) "y"
+string(1) "z"
+string(1) "x"
+string(1) "y"
+string(1) "z"
diff --git a/Zend/tests/bug30162.phpt b/Zend/tests/bug30162.phpt new file mode 100755 index 000000000..ae11f8ff8 --- /dev/null +++ b/Zend/tests/bug30162.phpt @@ -0,0 +1,52 @@ +--TEST-- +Bug #30162 (Catching exception in constructor couses lose of $this) +--FILE-- +<?php +class FIIFO { + + public function __construct() { + $this->x = "x"; + throw new Exception; + } + +} + +class hariCow extends FIIFO { + + public function __construct() { + try { + parent::__construct(); + } catch(Exception $e) { + } + $this->y = "y"; + try { + $this->z = new FIIFO; + } catch(Exception $e) { + } + } + + public function __toString() { + return "Rusticus in asino sedet."; + } + +} + +try { + $db = new FIIFO(); +} catch(Exception $e) { +} +var_dump($db); + +$db = new hariCow; + +var_dump($db); +?> +--EXPECTF-- +Notice: Undefined variable: db in %sbug30162.php on line 35 +NULL +object(hariCow)#1 (2) { + ["x"]=> + string(1) "x" + ["y"]=> + string(1) "y" +} diff --git a/Zend/tests/bug30332.phpt b/Zend/tests/bug30332.phpt new file mode 100644 index 000000000..873cd7d36 --- /dev/null +++ b/Zend/tests/bug30332.phpt @@ -0,0 +1,40 @@ +--TEST--
+Bug #30332 (zend.ze1_compatibility_mode isnt fully compatable with array_push())
+--INI--
+zend.ze1_compatibility_mode=on
+error_reporting=4095
+--FILE--
+<?php
+class x { };
+
+$first = new x;
+$second = $first;
+$container = array();
+array_push($container, $first);
+
+$first->first = " im in the first";
+
+print_r($first);
+print_r($second);
+print_r($container);
+?>
+--EXPECTF--
+Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 4
+
+Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 5
+
+Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 7
+x Object
+(
+ [first] => im in the first
+)
+x Object
+(
+)
+Array
+(
+ [0] => x Object
+ (
+ )
+
+)
diff --git a/Zend/tests/bug30394.phpt b/Zend/tests/bug30394.phpt new file mode 100755 index 000000000..a979e0796 --- /dev/null +++ b/Zend/tests/bug30394.phpt @@ -0,0 +1,30 @@ +--TEST--
+Bug #30394 (Assignment operators yield wrong result with __get/__set)
+--FILE--
+<?php
+class Container
+{
+ public function __get( $what )
+ {
+ return $this->_p[ $what ];
+ }
+
+ public function __set( $what, $value )
+ {
+ $this->_p[ $what ] = $value;
+ }
+
+ private $_p = array();
+}
+
+$c = new Container();
+$c->a = 1;
+$c->a += 1;
+print $c->a; // --> 2
+
+print " - ";
+$c->a += max( 0, 1 );
+print $c->a; // --> 4 (!)
+?>
+--EXPECT--
+2 - 3
diff --git a/Zend/tests/bug30451.phpt b/Zend/tests/bug30451.phpt new file mode 100644 index 000000000..91d51a68f --- /dev/null +++ b/Zend/tests/bug30451.phpt @@ -0,0 +1,36 @@ +--TEST--
+Bug #30451 (static properties permissions broken)
+--FILE--
+<?php
+
+class A {
+
+ protected static $property = TRUE;
+
+ protected static function method() {
+ return TRUE;
+ }
+
+}
+
+class B extends A {
+
+ public function __construct() {
+
+ var_dump(self::method());
+ var_dump(parent::method());
+
+ var_dump(self::$property);
+ var_dump(parent::$property);
+
+ }
+
+}
+
+new B;
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/Zend/tests/bug30519.phpt b/Zend/tests/bug30519.phpt new file mode 100755 index 000000000..a499a3fad --- /dev/null +++ b/Zend/tests/bug30519.phpt @@ -0,0 +1,10 @@ +--TEST--
+Bug #30519 Interface not existing says Class not found
+--FILE--
+<?php
+class test implements a {
+}
+?>
+--EXPECTF--
+Fatal error: Interface 'a' not found in %sbug30519.php on line 2
+
diff --git a/Zend/tests/bug30702.phpt b/Zend/tests/bug30702.phpt new file mode 100644 index 000000000..e3e8f59fe --- /dev/null +++ b/Zend/tests/bug30702.phpt @@ -0,0 +1,39 @@ +--TEST--
+Bug #30702 cannot initialize class variable from class constant
+--FILE--
+<?php
+class foo {
+ const C1=1;
+}
+
+class bar extends foo {
+ const C2=2;
+
+ public $c1=bar::C1;
+ public $c2=bar::C2;
+
+ public $c3=self::C1;
+ public $c4=self::C2;
+
+ public $c5=foo::C1;
+ public $c6=parent::C1;
+}
+
+$x= new bar();
+var_dump($x);
+?>
+--EXPECT--
+object(bar)#1 (6) {
+ ["c1"]=>
+ int(1)
+ ["c2"]=>
+ int(2)
+ ["c3"]=>
+ int(1)
+ ["c4"]=>
+ int(2)
+ ["c5"]=>
+ int(1)
+ ["c6"]=>
+ int(1)
+}
diff --git a/Zend/tests/bug30707.phpt b/Zend/tests/bug30707.phpt new file mode 100755 index 000000000..d37d32974 --- /dev/null +++ b/Zend/tests/bug30707.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #30707 (Segmentation fault on exception in method) +--FILE-- +<?php +class C { + function byePHP($plop) { + echo "ok\n"; + } + + function plip() { + try { + $this->plap($this->plop()); + } catch(Exception $e) { + } + } + + function plap($a) { + } + + function plop() { + throw new Exception; + } +} + +$x = new C; +$x->byePHP($x->plip()); +?> +--EXPECT-- +ok diff --git a/Zend/tests/bug30791.phpt b/Zend/tests/bug30791.phpt new file mode 100755 index 000000000..64ee313e4 --- /dev/null +++ b/Zend/tests/bug30791.phpt @@ -0,0 +1,23 @@ +--TEST--
+Bug #30791 magic methods (__sleep/__wakeup/__toString) call __call if object is overloaded
+--FILE--
+<?php
+class a {
+ public $a = 4;
+ function __call($a,$b) {
+ return "unknown method";
+ }
+}
+$b = new a;
+echo $b,"\n";
+$c = unserialize(serialize($b));
+echo $c,"\n";
+var_dump($c);
+?>
+--EXPECT--
+Object id #1
+Object id #2
+object(a)#2 (1) {
+ ["a"]=>
+ int(4)
+}
diff --git a/Zend/tests/bug30820.phpt b/Zend/tests/bug30820.phpt new file mode 100755 index 000000000..6c136a5fc --- /dev/null +++ b/Zend/tests/bug30820.phpt @@ -0,0 +1,27 @@ +--TEST--
+Bug #30820 (static member conflict with $this->member silently ignored)
+--INI--
+error_reporting=4095
+--FILE--
+<?php
+class Blah {
+ private static $x;
+
+ public function show() {
+ Blah::$x = 1;
+ $this->x = 5; // no warning, but refers to different variable
+
+ echo 'Blah::$x = '. Blah::$x ."\n";
+ echo '$this->x = '. $this->x ."\n";
+ }
+}
+
+$b = new Blah();
+$b->show();
+?>
+--EXPECTF--
+Strict Standards: Accessing static property Blah::$x as non static in %sbug30820.php on line 7
+Blah::$x = 1
+
+Strict Standards: Accessing static property Blah::$x as non static in %sbug30820.php on line 10
+$this->x = 5
diff --git a/Zend/tests/bug30828.phpt b/Zend/tests/bug30828.phpt new file mode 100755 index 000000000..eb003f1de --- /dev/null +++ b/Zend/tests/bug30828.phpt @@ -0,0 +1,61 @@ +--TEST--
+Bug #30828 (debug_backtrace() reports incorrect class in overridden methods)
+--FILE--
+<?php
+class A {
+ function __construct() {
+ debug_print_backtrace();
+ $bt = debug_backtrace();
+ foreach ($bt as $t) {
+ print $t['class'].$t['type'].$t['function']."\n";
+ }
+ }
+
+ function foo() {
+ debug_print_backtrace();
+ $bt = debug_backtrace();
+ foreach ($bt as $t) {
+ print $t['class'].$t['type'].$t['function']."\n";
+ }
+ }
+
+ static function bar() {
+ debug_print_backtrace();
+ $bt = debug_backtrace();
+ foreach ($bt as $t) {
+ print $t['class'].$t['type'].$t['function']."\n";
+ }
+ }
+}
+
+class B extends A {
+ function __construct() {
+ parent::__construct();
+ }
+
+ function foo() {
+ parent::foo();
+ }
+
+ static function bar() {
+ parent::bar();
+ }
+}
+
+$b = new B();
+$b->foo();
+B::bar();
+?>
+--EXPECTF--
+#0 A->__construct() called at [%sbug30828.php:30]
+#1 B->__construct() called at [%sbug30828.php:42]
+A->__construct
+B->__construct
+#0 A->foo() called at [%sbug30828.php:34]
+#1 B->foo() called at [%sbug30828.php:43]
+A->foo
+B->foo
+#0 A::bar() called at [%sbug30828.php:38]
+#1 B::bar() called at [%sbug30828.php:44]
+A::bar
+B::bar
diff --git a/Zend/tests/bug30889.phpt b/Zend/tests/bug30889.phpt new file mode 100644 index 000000000..4578516a4 --- /dev/null +++ b/Zend/tests/bug30889.phpt @@ -0,0 +1,31 @@ +--TEST--
+Bug #30889 Conflict between __get/__set and ++ operator
+--FILE--
+<?php
+class overloaded
+{
+ private $values;
+ function __construct()
+ {
+ $this->values = array('a' => 0);
+ }
+ function __set($name, $value)
+ {
+ print "set $name = $value ($name was ".$this->values[$name].")\n";
+ $this->values[$name] = $value;
+ }
+ function __get($name)
+ {
+ print "get $name (returns ".$this->values[$name].")\n";
+ return $this->values[$name];
+ }
+}
+$test = new overloaded();
+$test->a++; // __get(), then __set()
+++$test->a;
+?>
+--EXPECT--
+get a (returns 0)
+set a = 1 (a was 0)
+get a (returns 1)
+set a = 2 (a was 1)
diff --git a/Zend/tests/bug30961.phpt b/Zend/tests/bug30961.phpt new file mode 100755 index 000000000..a453cddfb --- /dev/null +++ b/Zend/tests/bug30961.phpt @@ -0,0 +1,20 @@ +--TEST--
+Bug #30961 (Wrong linenumber in ReflectionClass getStartLine())
+--FILE--
+<?
+ class a
+ {
+ }
+
+ class b extends a
+ {
+ }
+
+ $ref1 = new ReflectionClass('a');
+ $ref2 = new ReflectionClass('b');
+ echo $ref1->getStartLine() . "\n";
+ echo $ref2->getStartLine() . "\n";
+?>
+--EXPECT--
+2
+6
diff --git a/Zend/tests/bug31177.phpt b/Zend/tests/bug31177.phpt new file mode 100755 index 000000000..ac0fd7289 --- /dev/null +++ b/Zend/tests/bug31177.phpt @@ -0,0 +1,44 @@ +--TEST--
+Bug #31177 (Memory leak)
+--FILE--
+<?php
+class DbGow {
+
+ public function query() {
+ throw new Exception;
+ }
+
+ public function select() {
+ return new DbGowRecordSet($this->query());
+ }
+
+ public function select2() {
+ new DbGowRecordSet($this->query());
+ }
+
+}
+
+class DbGowRecordSet {
+
+ public function __construct($resource) {
+ }
+
+}
+
+$db = new DbGow;
+
+try {
+ $rs = $db->select();
+} catch(Exception $e) {
+ echo "ok\n";
+}
+
+try {
+ $db->select2();
+} catch(Exception $e) {
+ echo "ok\n";
+}
+?>
+--EXPECT--
+ok
+ok
diff --git a/Zend/tests/bug31525.phpt b/Zend/tests/bug31525.phpt new file mode 100755 index 000000000..9c1c846ce --- /dev/null +++ b/Zend/tests/bug31525.phpt @@ -0,0 +1,22 @@ +--TEST--
+Bug #31525 (object reference being dropped. $this getting lost)
+--INI--
+error_reporting=4095
+--FILE--
+<?php
+class Foo {
+ function getThis() {
+ return $this;
+ }
+ function destroyThis() {
+ $baz =& $this->getThis();
+ }
+}
+$bar = new Foo();
+$bar->destroyThis();
+var_dump($bar);
+?>
+--EXPECTF--
+Strict Standards: Only variables should be assigned by reference in %sbug31525.php on line 7
+object(Foo)#1 (0) {
+}
diff --git a/Zend/tests/bug31828.phpt b/Zend/tests/bug31828.phpt new file mode 100644 index 000000000..e5c004fba --- /dev/null +++ b/Zend/tests/bug31828.phpt @@ -0,0 +1,25 @@ +--TEST--
+Bug #31828 (Crash with zend.ze1_compatibility_mode=On)
+--INI--
+zend.ze1_compatibility_mode=on
+error_reporting=4095
+--FILE--
+<?php
+$o = new stdClass();
+$o->id = 77;
+$o->name = "Aerospace";
+$a[] = $o;
+$a = $a[0];
+print_r($a);
+?>
+--EXPECTF--
+Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 2
+
+Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 5
+
+Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 6
+stdClass Object
+(
+ [id] => 77
+ [name] => Aerospace
+)
diff --git a/Zend/tests/bug32080.phpt b/Zend/tests/bug32080.phpt new file mode 100644 index 000000000..c7227b4f5 --- /dev/null +++ b/Zend/tests/bug32080.phpt @@ -0,0 +1,18 @@ +--TEST--
+Bug #32080 (segfault when assigning object to itself with zend.ze1_compatibility_mode=On)
+--INI--
+zend.ze1_compatibility_mode=on
+error_reporting=4095
+--FILE--
+<?php
+class test { }
+$t = new test;
+$t = $t; // gives segfault
+var_dump($t);
+?>
+--EXPECTF--
+Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 3
+
+Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 5
+object(test)#%d (0) {
+}
diff --git a/Zend/tests/bug32252.phpt b/Zend/tests/bug32252.phpt new file mode 100755 index 000000000..706da18cf --- /dev/null +++ b/Zend/tests/bug32252.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #32252 (Segfault when offsetSet throws an Exception (only without debug)) +--FILE-- +<?php + +class Test implements ArrayAccess +{ + function offsetExists($offset) + { + echo __METHOD__ . "($offset)\n"; + return false; + } + + function offsetGet($offset) + { + echo __METHOD__ . "($offset)\n"; + return null; + } + + function offsetSet($offset, $value) + { + echo __METHOD__ . "($offset, $value)\n"; + throw new Exception("Ooops"); + } + + function offsetUnset($offset) + { + echo __METHOD__ . "($offset)\n"; + } +} + +$list = new Test(); +try +{ + $list[-1] = 123; +} +catch (Exception $e) +{ + echo "CAUGHT\n"; +} + +?> +===DONE=== +--EXPECT-- +Test::offsetSet(-1, 123) +CAUGHT +===DONE=== diff --git a/Zend/tests/bug32296.phpt b/Zend/tests/bug32296.phpt new file mode 100755 index 000000000..1b15f5379 --- /dev/null +++ b/Zend/tests/bug32296.phpt @@ -0,0 +1,60 @@ +--TEST--
+Bug #32296 get_class_methods output has changed between 5.0.2 and 5.0.3
+--FILE--
+<?php
+abstract class space{
+ function __construct(){}
+ abstract protected function unfold();
+}
+
+abstract class shape extends space{
+ private function x1() {}
+ protected final function unfold(){}
+}
+
+abstract class quad extends shape{
+ private function x2() {}
+ function buggy(){
+ $c = get_class($this);
+ $a = get_class_methods(get_class($this));
+ $b = get_class_methods($this);
+ print($c."\n".'a:');
+ print_r($a);
+ print('b:');
+ print_r($b);
+ }
+}
+
+class square extends quad{}
+
+$a = new square();
+$a->buggy();
+print_r(get_class_methods("square"));
+print_r(get_class_methods($a));
+?>
+--EXPECT--
+square
+a:Array
+(
+ [0] => x2
+ [1] => buggy
+ [2] => unfold
+ [3] => __construct
+)
+b:Array
+(
+ [0] => x2
+ [1] => buggy
+ [2] => unfold
+ [3] => __construct
+)
+Array
+(
+ [0] => buggy
+ [1] => __construct
+)
+Array
+(
+ [0] => buggy
+ [1] => __construct
+)
diff --git a/Zend/tests/bug32322.phpt b/Zend/tests/bug32322.phpt new file mode 100755 index 000000000..fd79a0482 --- /dev/null +++ b/Zend/tests/bug32322.phpt @@ -0,0 +1,80 @@ +--TEST--
+Bug #32322 (Return values by reference broken( using self::),example singleton instance)
+--INI--
+error_reporting=4095
+--FILE--
+<?php
+class test
+{
+ private static $instance = null;
+ private $myname = '';
+
+ private function __construct( $value = '' )
+ {
+ echo "New class $value created \n";
+ $this -> myname = $value;
+ }
+ private function __clone() {}
+ static public function getInstance()
+ {
+ if ( self::$instance == null )
+ {
+ self::$instance = new test('Singleton1');
+ }
+ else {
+ echo "Using old class " . self::$instance -> myname . "\n";
+ }
+ return self::$instance;
+ }
+ static public function getInstance2()
+ {
+ static $instance2 = null;
+ if ( $instance2 == null )
+ {
+ $instance2 = new test('Singleton2');
+ }
+ else {
+ echo "Using old class " . $instance2 -> myname . "\n";
+ }
+ return $instance2;
+ }
+ public function __destruct()
+ {
+ if ( defined('SCRIPT_END') )
+ {
+ echo "Class " . $this -> myname . " destroyed at script end\n";
+ } else {
+ echo "Class " . $this -> myname . " destroyed beforce script end\n";
+ }
+ }
+}
+echo "Try static instance inside class :\n";
+$getCopyofSingleton = test::getInstance();
+$getCopyofSingleton = null;
+$getCopyofSingleton = &test::getInstance();
+$getCopyofSingleton = null;
+$getCopyofSingleton = test::getInstance();
+echo "Try static instance inside function :\n";
+$getCopyofSingleton2 = test::getInstance2();
+$getCopyofSingleton2 = null;
+$getCopyofSingleton2 = &test::getInstance2();
+$getCopyofSingleton2 = null;
+$getCopyofSingleton2 = test::getInstance2();
+
+define('SCRIPT_END',1);
+?>
+--EXPECTF--
+Try static instance inside class :
+New class Singleton1 created
+Using old class Singleton1
+
+Strict Standards: Only variables should be assigned by reference in %sbug32322.php on line 49
+Using old class Singleton1
+Try static instance inside function :
+New class Singleton2 created
+Using old class Singleton2
+
+Strict Standards: Only variables should be assigned by reference in %sbug32322.php on line 55
+Using old class Singleton2
+Class Singleton1 destroyed at script end
+Class Singleton2 destroyed at script end
diff --git a/Zend/tests/bug32596.phpt b/Zend/tests/bug32596.phpt new file mode 100755 index 000000000..35dcda7b3 --- /dev/null +++ b/Zend/tests/bug32596.phpt @@ -0,0 +1,27 @@ +--TEST--
+Bug #32596 (Segfault/Memory Leak by getClass (etc) in __destruct)
+--FILE--
+<?php
+class BUG {
+ public $error = "please fix this thing, it wasted a nice part of my life!\n";
+ static function instance() {return new BUG();}
+
+ function __destruct()
+ {
+ $c=get_class($this); unset($c);
+ echo get_class($this) ."\n";
+ if(defined('DEBUG_'.__CLASS__)){}
+ $c=get_class($this); //memory leak only
+ echo $this->error;
+ }
+}
+
+
+BUG::instance()->error;
+echo "this is still executed\n";
+?>
+--EXPECT--
+BUG
+please fix this thing, it wasted a nice part of my life!
+this is still executed
+
diff --git a/Zend/tests/bug32660.phpt b/Zend/tests/bug32660.phpt new file mode 100755 index 000000000..36a2f7872 --- /dev/null +++ b/Zend/tests/bug32660.phpt @@ -0,0 +1,36 @@ +--TEST--
+Bug #32660 Assignment by reference causes crash when field access is overloaded (__get)
+--FILE--
+<?php
+class A
+{
+ public $q;
+
+ function __construct()
+ {
+ $this->q = 3;//array();
+ }
+
+ function __get($name)
+ {
+ return $this->q;
+ }
+}
+
+$a = new A;
+
+$b = "short";
+$c =& $a->whatever;
+$c = "long";
+print_r($a);
+$a->whatever =& $b;
+$b = "much longer";
+print_r($a);
+?>
+--EXPECTF--
+A Object
+(
+ [q] => long
+)
+
+Fatal error: Cannot assign by reference to overloaded object in %sbug32660.php on line 23
diff --git a/Zend/tests/bug32674.phpt b/Zend/tests/bug32674.phpt new file mode 100644 index 000000000..700e3b4db --- /dev/null +++ b/Zend/tests/bug32674.phpt @@ -0,0 +1,62 @@ +--TEST--
+Bug #32674 exception in iterator causes crash
+--FILE--
+<?php
+class collection implements Iterator {
+
+ private $_elements = array();
+
+ public function __construct() {
+ }
+
+ public function rewind() {
+ reset($this->_elements);
+ }
+
+ public function count() {
+ return count($this->_elements);
+ }
+
+ public function current() {
+ $element = current($this->_elements);
+ return $element;
+ }
+
+ public function next() {
+ $element = next($this->_elements);
+ return $element;
+ }
+
+ public function key() {
+ $this->_fillCollection();
+ $element = key($this->_elements);
+ return $element;
+ }
+
+ public function valid() {
+ throw new Exception('shit happend');
+
+ return ($this->current() !== false);
+ }
+}
+
+class class2 {
+ public $dummy;
+}
+
+$obj = new class2();
+$col = new collection();
+
+try {
+ foreach($col as $co) {
+ //irrelevant
+ }
+ echo 'shouldn`t get here';
+ //$dummy = 'this will not crash';
+ $obj->dummy = 'this will crash';
+} catch (Exception $e) {
+ echo "ok\n";
+}
+?>
+--EXPECT--
+ok
diff --git a/Zend/tests/bug32799.phpt b/Zend/tests/bug32799.phpt new file mode 100755 index 000000000..12bffd4a4 --- /dev/null +++ b/Zend/tests/bug32799.phpt @@ -0,0 +1,21 @@ +--TEST--
+Bug #32799 (crash: calling the corresponding global var during the destruct)
+--FILE--
+<?php
+class test{
+ public $c=1;
+ function __destruct (){
+ $GLOBALS['p']->c++; // no warning
+ print $GLOBALS['p']->c."\n"; // segfault
+ var_dump($GLOBALS['p']);
+ }
+}
+$p=new test;
+$p=null; //destroy the object by a new assignment (segfault)
+?>
+--EXPECT--
+2
+object(test)#1 (1) {
+ ["c"]=>
+ int(2)
+}
diff --git a/Zend/tests/bug32852.phpt b/Zend/tests/bug32852.phpt new file mode 100644 index 000000000..8b44bdcdf --- /dev/null +++ b/Zend/tests/bug32852.phpt @@ -0,0 +1,38 @@ +--TEST--
+Bug #32852 (Crash with singleton and __destruct when zend.ze1_compatibility_mode = On)
+--INI--
+zend.ze1_compatibility_mode=on
+error_reporting=4095
+--FILE--
+<?php
+class crashme {
+ private static $instance = null;
+
+ public function __construct() {
+ self::$instance = $this;
+ }
+
+ public function __destruct() {
+ echo "i'm called\n";
+ }
+
+ public static function singleton() {
+ if (!isset(self::$instance)) {
+ self::$instance = new crashme();
+ }
+ return self::$instance;
+ }
+}
+
+crashme::singleton();
+?>
+--EXPECTF--
+Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 6
+i'm called
+
+Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 15
+i'm called
+
+Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 17
+i'm called
+i'm called
diff --git a/Zend/tests/bug32981.phpt b/Zend/tests/bug32981.phpt new file mode 100755 index 000000000..1f89ca682 --- /dev/null +++ b/Zend/tests/bug32981.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #32981 (ReflectionMethod::getStaticVariables() causes apache2.0.54 seg fault) +--FILE-- +<?php + +class TestClass +{ + static function test() + { + static $enabled = true; + } +} + +$class = new ReflectionClass('TestClass'); +foreach ($class->getMethods() as $method) +{ + var_dump($method->getName()); + $arr_static_vars[] = $method->getStaticVariables(); +} + +var_dump($arr_static_vars); + +?> +===DONE=== +--EXPECT-- +string(4) "test" +array(1) { + [0]=> + array(1) { + ["enabled"]=> + bool(true) + } +} +===DONE=== diff --git a/Zend/tests/bug32993.phpt b/Zend/tests/bug32993.phpt new file mode 100755 index 000000000..86d8e266f --- /dev/null +++ b/Zend/tests/bug32993.phpt @@ -0,0 +1,29 @@ +--TEST--
+Bug #32993 (implemented Iterator function current() don't throw exception)
+--FILE--
+<?php
+class Test implements Iterator {
+
+ public $arr = array();
+
+ public function rewind() { return reset($this->arr); }
+ public function current() { throw new Exception(); }
+ public function key() { return key($this->arr); }
+ public function next() { return next($this->arr); }
+ public function valid() { return (current($this->arr) !== false); }
+}
+
+$t = new Test();
+$t->arr = array(1, 2, 3);
+
+try {
+ foreach ($t as $v) {
+ echo "$v\n";
+ }
+} catch (Exception $e) {
+ ; // handle exception
+}
+echo "ok\n";
+?>
+--EXPECT--
+ok
diff --git a/Zend/tests/bug33116.phpt b/Zend/tests/bug33116.phpt new file mode 100755 index 000000000..641f4bb99 --- /dev/null +++ b/Zend/tests/bug33116.phpt @@ -0,0 +1,22 @@ +--TEST--
+Bug #33116 (crash when assigning class name to global variable in __autoload)
+--FILE--
+<?php
+function __autoload($class)
+{
+ $GLOBALS['include'][] = $class;
+ eval("class DefClass{}");
+}
+
+$a = new DefClass;
+print_r($a);
+print_r($GLOBALS['include']);
+?>
+--EXPECT--
+DefClass Object
+(
+)
+Array
+(
+ [0] => DefClass
+)
diff --git a/Zend/tests/bug33171.phpt b/Zend/tests/bug33171.phpt new file mode 100755 index 000000000..8cc44a27a --- /dev/null +++ b/Zend/tests/bug33171.phpt @@ -0,0 +1,27 @@ +--TEST--
+Bug #33171 (foreach enumerates private fields declared in base classes)
+--FILE--
+<?php
+class A
+{
+ private $c = "A's c";
+}
+
+class B extends A
+{
+ private $c = "B's c";
+
+ public function go()
+ {
+ foreach ($this as $key => $val)
+ {
+ echo "$key => $val\n";
+ }
+ }
+};
+
+$x = new B;
+$x->go();
+?>
+--EXPECT--
+c => B's c
diff --git a/Zend/tests/bug33243.phpt b/Zend/tests/bug33243.phpt new file mode 100755 index 000000000..9b5b39dec --- /dev/null +++ b/Zend/tests/bug33243.phpt @@ -0,0 +1,25 @@ +--TEST--
+Bug #33243 (ze1_compatibility_mode does not work as expected)
+--INI--
+zend.ze1_compatibility_mode=1
+error_reporting=4095
+--FILE--
+<?php
+$a->y->z = 0;
+$b = $a; // should perform deep copy of $a
+$b->y->z = 1; // hence this should have no effect on $a
+var_dump($a);
+?>
+--EXPECTF--
+Strict Standards: Creating default object from empty value in %sbug33243.php on line 2
+
+Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 3
+
+Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 5
+object(stdClass)#%d (1) {
+ ["y"]=>
+ object(stdClass)#%d (1) {
+ ["z"]=>
+ int(0)
+ }
+}
diff --git a/Zend/tests/bug33257.phpt b/Zend/tests/bug33257.phpt new file mode 100755 index 000000000..4563c8305 --- /dev/null +++ b/Zend/tests/bug33257.phpt @@ -0,0 +1,17 @@ +--TEST--
+Bug #33257 array_splice() inconsistent when passed function instead of variable
+--FILE--
+<?php
+class X {
+ protected static $arr = array("a", "b", "c");
+ public static function getArr() {
+ return self::$arr;
+ }
+}
+
+//$arr1 = X::getArr();
+array_splice(X::getArr(), 1, 1);
+print_r(X::getArr());
+?>
+--EXPECTF--
+Fatal error: Only variables can be passed by reference in %sbug33257.php on line 10
diff --git a/Zend/tests/bug33277.phpt b/Zend/tests/bug33277.phpt new file mode 100644 index 000000000..89a035b57 --- /dev/null +++ b/Zend/tests/bug33277.phpt @@ -0,0 +1,28 @@ +--TEST--
+Bug #33277 (private method accessed by child class)
+--FILE--
+<?
+class foo {
+ private function bar() {
+ echo "private!\n";
+ }
+}
+
+class fooson extends foo {
+ function barson() {
+ $this->bar();
+ }
+}
+
+class foo2son extends fooson {
+
+ function bar() {
+ echo "public!\n";
+ }
+}
+
+$b = new foo2son();
+$b->barson();
+?>
+--EXPECT--
+public!
diff --git a/Zend/tests/bug33558.phpt b/Zend/tests/bug33558.phpt new file mode 100755 index 000000000..15ac4a26a --- /dev/null +++ b/Zend/tests/bug33558.phpt @@ -0,0 +1,21 @@ +--TEST--
+Bug #33558 (warning with nested calls to functions returning by reference)
+--INI--
+error_reporting=4095
+--FILE--
+<?php
+function & foo() {
+ $var = 'ok';
+ return $var;
+}
+
+function & bar() {
+ return foo();
+}
+
+$a =& bar();
+echo "$a\n";
+?>
+--EXPECT--
+ok
+
diff --git a/Zend/tests/bug33802.phpt b/Zend/tests/bug33802.phpt new file mode 100755 index 000000000..d2f8cd736 --- /dev/null +++ b/Zend/tests/bug33802.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #33802 (throw Exception in error handler causes crash) +--FILE-- +<?php +set_error_handler('errorHandler', E_USER_ERROR); +try{ + test(); +}catch(Exception $e){ +} +restore_error_handler(); + +function test(){ + trigger_error("error", E_USER_ERROR); +} + +function errorHandler($errno, $errstr, $errfile, $errline) { + throw new Exception(); +} +?> +ok +--EXPECT-- +ok diff --git a/Zend/tests/bug34064.phpt b/Zend/tests/bug34064.phpt new file mode 100755 index 000000000..22ddb89c5 --- /dev/null +++ b/Zend/tests/bug34064.phpt @@ -0,0 +1,35 @@ +--TEST--
+Bug #34064 (arr[] as param to function in class gives invalid opcode)
+--FILE--
+<?php
+class XmlTest {
+
+ function test_ref(&$test)
+ {
+ $test = "ok";
+ }
+
+ function test($test)
+ {
+ }
+
+ function run()
+ {
+ $ar = array();
+ $this->test_ref($ar[]);
+ var_dump($ar);
+ $this->test($ar[]);
+ }
+}
+
+$o = new XmlTest();
+$o->run();
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ string(2) "ok"
+}
+
+Fatal error: Cannot use [] for reading in %sbug34064.php on line 18
+
diff --git a/Zend/tests/bug34137.phpt b/Zend/tests/bug34137.phpt new file mode 100755 index 000000000..4e0a09ffa --- /dev/null +++ b/Zend/tests/bug34137.phpt @@ -0,0 +1,10 @@ +--TEST--
+Bug #34137 (assigning array element by reference causes binary mess)
+--FILE--
+<?php
+$arr1 = array('a1' => array('alfa' => 'ok'));
+$arr1 =& $arr1['a1'];
+echo '-'.$arr1['alfa']."-\n";
+?>
+--EXPECT--
+-ok-
diff --git a/Zend/tests/bug34260.phpt b/Zend/tests/bug34260.phpt new file mode 100755 index 000000000..4a5920854 --- /dev/null +++ b/Zend/tests/bug34260.phpt @@ -0,0 +1,36 @@ +--TEST--
+Bug #34260 (Segfault with callbacks (array_map) + overloading)
+--FILE--
+<?php
+class Faulty
+{
+ function __call($Method,$Args)
+ {
+ switch($Method)
+ {
+ case 'seg':
+ echo "I hate me\n";
+ break;
+ }
+ }
+
+ function NormalMethod($Args)
+ {
+ echo "I heart me\n";
+ }
+}
+
+$Faulty = new Faulty();
+$Array = array('Some junk','Some other junk');
+
+// This causes a seg fault.
+$Failure = array_map(array($Faulty,'seg'),$Array);
+
+// This does not.
+$Failure = array_map(array($Faulty,'NormalMethod'),$Array);
+?>
+--EXPECT--
+I hate me
+I hate me
+I heart me
+I heart me
diff --git a/Zend/tests/object_handlers.phpt b/Zend/tests/object_handlers.phpt new file mode 100755 index 000000000..279f5cd5c --- /dev/null +++ b/Zend/tests/object_handlers.phpt @@ -0,0 +1,171 @@ +--TEST--
+Magic object handlers segfault and memory errors
+--FILE--
+<?php
+function f($x) {
+ return $x;
+}
+
+class foo implements ArrayAccess {
+ function __get($property) {
+ $GLOBALS["y"] = $property;
+ }
+ function __set($property, $value) {
+ $GLOBALS["y"] = $property;
+ }
+ function __call($func, $args) {
+ $GLOBALS["y"] = $func;
+ }
+ function offsetGet($index) {
+ $GLOBALS["y"] = $index;
+ }
+ function offsetSet($index, $newval) {
+ $GLOBALS["y"] = $index;
+ }
+ function offsetExists($index) {
+ $GLOBALS["y"] = $index;
+ }
+ function offsetUnset($index) {
+ $GLOBALS["y"] = $index;
+ }
+}
+
+$x = new foo();
+$y = null;
+
+// IS_CONST
+$z = $x->const_get;
+echo $y,"\n";
+$x->const_set = 1;
+echo $y,"\n";
+$x->const_call();
+echo $y,"\n";
+$z = $x["const_dim_get"];
+echo $y,"\n";
+$x["const_dim_set"] = 1;
+echo $y,"\n";
+isset($x["const_dim_isset"]);
+echo $y,"\n";
+unset($x["const_dim_unset"]);
+echo $y,"\n";
+
+// IS_CONST + conversion
+$z = $x->{1};
+echo $y,"\n";
+$x->{2} = 1;
+echo $y,"\n";
+
+// IS_TMP_VAR
+$c = "tmp";
+$z = $x->{$c."_get"};
+echo $y,"\n";
+$x->{$c."_set"} = 1;
+echo $y,"\n";
+$x->{$c."_call"}();
+echo $y,"\n";
+$z = $x[$c."_dim_get"];
+echo $y,"\n";
+$x[$c."_dim_set"] = 1;
+echo $y,"\n";
+isset($x[$c."_dim_isset"]);
+echo $y,"\n";
+unset($x[$c."_dim_unset"]);
+echo $y,"\n";
+
+// IS_TMP_VAR + conversion
+$c = 0;
+$z = $x->{$c+3};
+echo $y,"\n";
+$x->{$c+4} = 1;
+echo $y,"\n";
+
+// IS_CV
+$c = "cv_get";
+$z = $x->{$c};
+echo $y,"\n";
+$c = "cv_set";
+$x->{$c} = 1;
+echo $y,"\n";
+$c = "cv_call";
+$x->{$c}();
+echo $y,"\n";
+$c = "cv_dim_get";
+$z = $x[$c];
+echo $y,"\n";
+$c = "cv_dim_set";
+$x[$c] = 1;
+echo $y,"\n";
+$c = "cv_dim_isset";
+isset($x[$c]);
+echo $y,"\n";
+$c = "cv_dim_unset";
+unset($x[$c]);
+echo $y,"\n";
+
+// IS_CV + conversion
+$c = 5;
+$z = $x->{$c};
+echo $y,"\n";
+$c = 6;
+$x->{$c} = 1;
+echo $y,"\n";
+
+// IS_VAR
+$z = $x->{f("var_get")};
+echo $y,"\n";
+$x->{f("var_set")} = 1;
+echo $y,"\n";
+$x->{f("var_call")}();
+echo $y,"\n";
+$z = $x[f("var_dim_get")];
+echo $y,"\n";
+$x[f("var_dim_set")] = 1;
+echo $y,"\n";
+isset($x[f("var_dim_isset")]);
+echo $y,"\n";
+unset($x[f("var_dim_unset")]);
+echo $y,"\n";
+
+// IS_VAR + conversion
+$z = $x->{f(7)};
+echo $y,"\n";
+$x->{f(8)} = 1;
+echo $y,"\n";
+?>
+--EXPECT--
+const_get
+const_set
+const_call
+const_dim_get
+const_dim_set
+const_dim_isset
+const_dim_unset
+1
+2
+tmp_get
+tmp_set
+tmp_call
+tmp_dim_get
+tmp_dim_set
+tmp_dim_isset
+tmp_dim_unset
+3
+4
+cv_get
+cv_set
+cv_call
+cv_dim_get
+cv_dim_set
+cv_dim_isset
+cv_dim_unset
+5
+6
+var_get
+var_set
+var_call
+var_dim_get
+var_dim_set
+var_dim_isset
+var_dim_unset
+7
+8
diff --git a/Zend/zend.c b/Zend/zend.c index cc3df08c3..068247ae4 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.c,v 1.287.2.4 2005/03/15 23:47:12 wez Exp $ */ +/* $Id: zend.c,v 1.287.2.12 2005/07/22 07:33:27 dmitry Exp $ */ #include "zend.h" #include "zend_extensions.h" @@ -803,6 +803,13 @@ void zend_deactivate_modules(TSRMLS_D) } zend_end_try(); } +void zend_call_destructors(TSRMLS_D) +{ + zend_try { + shutdown_destructors(TSRMLS_C); + } zend_end_try(); +} + void zend_deactivate(TSRMLS_D) { /* we're no longer executing anything */ @@ -820,6 +827,8 @@ void zend_deactivate(TSRMLS_D) shutdown_compiler(TSRMLS_C); } zend_end_try(); + zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); + zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try(); @@ -872,8 +881,6 @@ ZEND_API void zend_error(int type, const char *format, ...) char *error_filename; uint error_lineno; zval *orig_user_error_handler; - zval *orig_garbage[2]; - int orig_garbage_ptr; TSRMLS_FETCH(); /* Obtain relevant filename and lineno */ @@ -962,7 +969,7 @@ ZEND_API void zend_error(int type, const char *format, ...) z_context->value.ht = EG(active_symbol_table); z_context->type = IS_ARRAY; - ZVAL_ADDREF(z_context); /* we don't want this one to be freed */ + zval_copy_ctor(z_context); params = (zval ***) emalloc(sizeof(zval **)*5); params[0] = &z_error_type; @@ -974,12 +981,6 @@ ZEND_API void zend_error(int type, const char *format, ...) orig_user_error_handler = EG(user_error_handler); EG(user_error_handler) = NULL; - orig_garbage_ptr = EG(garbage_ptr); - EG(garbage_ptr) = 0; - if (orig_garbage_ptr > 0) { - memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr); - } - if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) { if (retval) { if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) { @@ -992,24 +993,18 @@ ZEND_API void zend_error(int type, const char *format, ...) zend_error_cb(type, error_filename, error_lineno, format, args); } - if (orig_garbage_ptr > 0) { - while (EG(garbage_ptr)) { - zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); - } - EG(garbage_ptr) = orig_garbage_ptr; - memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr); + if (!EG(user_error_handler)) { + EG(user_error_handler) = orig_user_error_handler; + } else { + zval_ptr_dtor(&orig_user_error_handler); } - EG(user_error_handler) = orig_user_error_handler; - efree(params); zval_ptr_dtor(&z_error_message); zval_ptr_dtor(&z_error_type); zval_ptr_dtor(&z_error_filename); zval_ptr_dtor(&z_error_lineno); - if (ZVAL_REFCOUNT(z_context) == 2) { - FREE_ZVAL(z_context); - } + zval_ptr_dtor(&z_context); break; } diff --git a/Zend/zend.h b/Zend/zend.h index 389c80796..b50c5a1c8 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -17,12 +17,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.h,v 1.257.2.23 2005/03/10 11:30:44 hyanantha Exp $ */ +/* $Id: zend.h,v 1.257.2.25 2005/08/25 17:41:08 zeev Exp $ */ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "2.0.4-dev" +#define ZEND_VERSION "2.0.5" #define ZEND_ENGINE_2 @@ -452,6 +452,7 @@ END_EXTERN_C() void zend_activate(TSRMLS_D); void zend_deactivate(TSRMLS_D); +void zend_call_destructors(TSRMLS_D); void zend_activate_modules(TSRMLS_D); void zend_deactivate_modules(TSRMLS_D); void zend_post_deactivate_modules(TSRMLS_D); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 9957490f4..6f89fd1ac 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_API.c,v 1.256.2.10 2005/03/16 04:19:20 wez Exp $ */ +/* $Id: zend_API.c,v 1.256.2.18 2005/07/25 20:26:49 helly Exp $ */ #include "zend.h" #include "zend_execute.h" @@ -152,7 +152,29 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr } while (param_count-->0) { - *(argument_array++) = (zval **) p-(arg_count--); + zval **value = (zval**)(p-arg_count); + + if (EG(ze1_compatibility_mode) && Z_TYPE_PP(value) == IS_OBJECT) { + zval *value_ptr; + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC); + + ALLOC_ZVAL(value_ptr); + *value_ptr = **value; + INIT_PZVAL(value_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + if(!dup) { + efree(class_name); + } + value_ptr->value.obj = Z_OBJ_HANDLER_PP(value, clone_obj)(*value TSRMLS_CC); + zval_ptr_dtor(value); + *value = value_ptr; + } + *(argument_array++) = value; + arg_count--; } return SUCCESS; @@ -161,7 +183,10 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr ZEND_API void zend_wrong_param_count(TSRMLS_D) { - zend_error(E_WARNING, "Wrong parameter count for %s()", get_active_function_name(TSRMLS_C)); + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + + zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C)); } @@ -209,6 +234,20 @@ ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC) } } +/* returns 1 if you need to copy result, 0 if it's already a copy */ +ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) +{ + if (Z_OBJ_HT_P(object)->get_class_name == NULL || + Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) { + zend_class_entry *ce = Z_OBJCE_P(object); + + *class_name = ce->name; + *class_name_len = ce->name_length; + return 1; + } + return 0; +} + static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC) { @@ -452,8 +491,10 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int expected_type = zend_parse_arg_impl(arg, va, spec TSRMLS_CC); if (expected_type) { if (!quiet) { - zend_error(E_WARNING, "%s() expects parameter %d to be %s, %s given", - get_active_function_name(TSRMLS_C), arg_num, expected_type, + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given", + class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type, zend_zval_type_name(*arg)); } return FAILURE; @@ -690,8 +731,13 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) { if (!class_type->constants_updated) { + zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + zend_class_entry *old_scope = *scope; + + *scope = class_type; zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); + *scope = old_scope; class_type->constants_updated = 1; } } @@ -1305,7 +1351,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr if (ptr->flags) { if (!(ptr->flags & ZEND_ACC_PPP_MASK)) { zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname); - internal_function->fn_flags |= ZEND_ACC_PUBLIC; + internal_function->fn_flags = ZEND_ACC_PUBLIC; } else { internal_function->fn_flags = ptr->flags; } @@ -1712,7 +1758,7 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_ return 1; } -ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name) +ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name) { char *lcname; zend_bool retval = 0; @@ -1723,7 +1769,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char if (callable_name) { *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable)); } - if (syntax_only) { + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { return 1; } @@ -1760,7 +1806,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); } - if (syntax_only) + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) return 1; lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj)); @@ -1789,14 +1835,27 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); } - if (syntax_only) + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) return 1; } if (ce) { + zend_function *fbc; + lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method)); - if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method)+1)) { + if (zend_hash_find(&ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) { retval = 1; + if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { + if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { + if (!zend_check_private(fbc, (Z_TYPE_PP(obj) == IS_STRING)?EG(scope):(*obj)->value.obj.handlers->get_class_entry(*obj TSRMLS_CC), lcname, Z_STRLEN_PP(method) TSRMLS_CC)) { + retval = 0; + } + } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + if (!zend_check_protected(fbc->common.scope, EG(scope))) { + retval = 0; + } + } + } } /* check for __call too */ if (retval == 0 && ce->__call != 0) { @@ -1828,8 +1887,10 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) { - char *lcname, *func; + char *lcname, *func, *class_name; zend_bool retval = 0; + zend_class_entry **pce; + int class_name_len; if (zend_is_callable(callable, 0, callable_name)) { return 1; @@ -1839,12 +1900,18 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable)); if ((func = strstr(lcname, "::")) != NULL) { - zval_dtor(callable); - array_init(callable); - add_next_index_stringl(callable, lcname, func - lcname, 1); - func += 2; - add_next_index_stringl(callable, func, strlen(func), 1); - retval = 1; + *func = '\0'; + class_name_len = func - lcname; + class_name = estrndup(Z_STRVAL_P(callable), class_name_len); + if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == SUCCESS) { + zval_dtor(callable); + array_init(callable); + add_next_index_stringl(callable, lcname, class_name_len, 1); + func += 2; + add_next_index_stringl(callable, func, strlen(func), 1); + retval = 1; + } + efree(class_name); } efree(lcname); break; @@ -1984,7 +2051,12 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char * EG(scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", Z_OBJCE_P(object)->name, name); + char *class_name; + zend_uint class_name_len; + + zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); + + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name); } ZVAL_STRINGL(&property, name, name_length, 0); Z_OBJ_HT_P(object)->write_property(object, &property, value TSRMLS_CC); @@ -2033,7 +2105,11 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n EG(scope) = scope; if (!Z_OBJ_HT_P(object)->read_property) { - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", Z_OBJCE_P(object)->name, name); + char *class_name; + zend_uint class_name_len; + + zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name); } ZVAL_STRINGL(&property, name, name_length, 0); value = Z_OBJ_HT_P(object)->read_property(object, &property, silent TSRMLS_CC); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 46320eeb4..7df63c76d 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_API.h,v 1.185.2.2 2005/01/22 12:29:13 helly Exp $ */ +/* $Id: zend_API.h,v 1.185.2.4 2005/06/27 17:42:06 stas Exp $ */ #ifndef ZEND_API_H #define ZEND_API_H @@ -179,7 +179,11 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC); ZEND_API void zend_wrong_param_count(TSRMLS_D); -ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name); + +#define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) +#define IS_CALLABLE_CHECK_NO_ACCESS (1<<1) + +ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name); ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC); ZEND_API char *zend_get_module_version(char *module_name); ZEND_API int zend_get_module_started(char *module_name); @@ -197,6 +201,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC); ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC); +ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC); #define getThis() (this_ptr) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0a3e6d54d..0abe9d945 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_alloc.c,v 1.137.2.1 2004/08/27 16:49:54 andi Exp $ */ +/* $Id: zend_alloc.c,v 1.137.2.4 2005/08/18 15:14:23 iliaa Exp $ */ #include "zend.h" #include "zend_alloc.h" @@ -75,7 +75,8 @@ static long mem_block_end_magic = MEM_BLOCK_END_MAGIC; #define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\ if (AG(memory_limit)<AG(allocated_memory)) {\ int php_mem_limit = AG(memory_limit); \ - if (EG(in_execution) && AG(memory_limit)+1048576 > AG(allocated_memory) - rs) { \ + AG(allocated_memory) -= rs; \ + if (EG(in_execution) && AG(memory_limit)+1048576 > AG(allocated_memory)) { \ AG(memory_limit) = AG(allocated_memory) + 1048576; \ if (file) { \ zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s); \ @@ -388,7 +389,6 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) return p; } - ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { char *p; diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index d11618288..19cf49316 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_alloc.h,v 1.52.2.1 2004/08/11 06:13:12 derick Exp $ */ +/* $Id: zend_alloc.h,v 1.52.2.4 2005/06/07 13:37:13 derick Exp $ */ #ifndef ZEND_ALLOC_H #define ZEND_ALLOC_H @@ -85,8 +85,6 @@ ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LIN ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; -#define USE_ZEND_ALLOC 1 - #if USE_ZEND_ALLOC /* Standard wrapper macros */ @@ -124,15 +122,12 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE #define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size))) #define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s)) -#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):(empty_string)) -#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):(empty_string)) - #else #define _GNU_SOURCE #include <string.h> #undef _GNU_SOURCE - + /* Standard wrapper macros */ #define emalloc(size) malloc(size) #define safe_emalloc(nmemb, size, offset) malloc((nmemb) * (size) + (offset)) @@ -141,7 +136,7 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE #define erealloc(ptr, size) realloc((ptr), (size)) #define erealloc_recoverable(ptr, size) realloc((ptr), (size)) #define estrdup(s) strdup(s) -#define estrndup(s, length) strndup((s), (length)) +#define estrndup(s, length) zend_strndup((s), (length)) /* Relay wrapper macros */ #define emalloc_rel(size) malloc(size) @@ -151,7 +146,7 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE #define erealloc_rel(ptr, size) realloc((ptr), (size)) #define erealloc_recoverable_rel(ptr, size) realloc((ptr), (size)) #define estrdup_rel(s) strdup(s) -#define estrndup_rel(s, length) strndup((s), (length)) +#define estrndup_rel(s, length) zend_strndup((s), (length)) /* Selective persistent/non persistent allocation macros */ #define pemalloc(size, persistent) malloc(size) @@ -167,11 +162,10 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE #define perealloc_rel(ptr, size, persistent) realloc((ptr), (size)) #define perealloc_recoverable_rel(ptr, size, persistent) realloc((ptr), (size)) #define pestrdup_rel(s, persistent) strdup(s) +#endif /* !USE_ZEND_ALLOC */ -#define safe_estrdup(ptr) ((ptr)?(strdup(ptr)):(empty_string)) -#define safe_estrndup(ptr, len) ((ptr)?(strndup((ptr), (len))):(empty_string)) - -#endif +#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):(empty_string)) +#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):(empty_string)) ZEND_API int zend_set_memory_limit(unsigned int memory_limit); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index a2f010fca..6f9293091 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_builtin_functions.c,v 1.239.2.18 2005/03/14 09:13:14 stas Exp $ */ +/* $Id: zend_builtin_functions.c,v 1.239.2.27 2005/06/27 17:42:06 stas Exp $ */ #include "zend.h" #include "zend_API.h" @@ -523,6 +523,7 @@ ZEND_FUNCTION(get_class) zval **arg; char *name = ""; zend_uint name_len = 0; + int dup; if (!ZEND_NUM_ARGS()) { if (EG(scope)) { @@ -538,19 +539,9 @@ ZEND_FUNCTION(get_class) RETURN_FALSE; } - if (Z_OBJ_HT_PP(arg)->get_class_name == NULL || - Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_len, 0 TSRMLS_CC) != SUCCESS) { - zend_class_entry *ce; + dup = zend_get_object_classname(*arg, &name, &name_len TSRMLS_CC); - ce = zend_get_class_entry(*arg TSRMLS_CC); - if (!ce) { - RETURN_FALSE; - } - - RETURN_STRINGL(ce->name, ce->name_length, 1); - } - - RETURN_STRINGL(name, name_len, 0); + RETURN_STRINGL(name, name_len, dup); } /* }}} */ @@ -802,7 +793,6 @@ ZEND_FUNCTION(get_class_methods) zend_class_entry *ce = NULL, **pce; HashPosition pos; zend_function *mptr; - int instanceof; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class)==FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -824,14 +814,16 @@ ZEND_FUNCTION(get_class_methods) RETURN_NULL(); } - instanceof = EG(scope) && instanceof_function(EG(scope), ce TSRMLS_CC); - array_init(return_value); zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos); while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) { if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) - || (instanceof && ((mptr->common.fn_flags & ZEND_ACC_PROTECTED) || EG(scope) == mptr->common.scope))) { + || (EG(scope) && + (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && + instanceof_function(EG(scope), mptr->common.scope TSRMLS_CC)) + || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && + EG(scope) == mptr->common.scope)))) { MAKE_STD_ZVAL(method_name); ZVAL_STRING(method_name, mptr->common.function_name, 1); zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); @@ -1528,6 +1520,12 @@ static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC) (*arg)->refcount++; add_next_index_zval(arg_array, *arg); } + + /* skip args from incomplete frames */ + while ((((*curpos)-1) > EG(argument_stack).elements) && *((*curpos)-1)) { + (*curpos)--; + } + return arg_array; } @@ -1550,7 +1548,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) /* {{{ proto void debug_print_backtrace(void) */ ZEND_FUNCTION(debug_print_backtrace) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; @@ -1575,6 +1573,11 @@ ZEND_FUNCTION(debug_print_backtrace) args -= *(ulong*)args; frames_on_stack++; + /* skip args from incomplete frames */ + while (((args-1) > EG(argument_stack).elements) && *(args-1)) { + args--; + } + if ((args-1) == EG(argument_stack).elements) { arg_stack_consistent = 1; break; @@ -1588,14 +1591,35 @@ ZEND_FUNCTION(debug_print_backtrace) cur_arg_pos -= 2; frames_on_stack--; + if (arg_stack_consistent) { + /* skip args from incomplete frames */ + while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { + cur_arg_pos--; + } + } + array_init(return_value); while (ptr) { - class_name = call_type = NULL; + char *free_class_name = NULL; + + class_name = call_type = NULL; arg_array = NULL; - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; } else { filename = NULL; lineno = 0; @@ -1605,7 +1629,18 @@ ZEND_FUNCTION(debug_print_backtrace) if (function_name) { if (ptr->object) { - class_name = Z_OBJCE(*ptr->object)->name; + if (ptr->function_state.function->common.scope) { + class_name = ptr->function_state.function->common.scope->name; + } else { + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC); + if(!dup) { + free_class_name = class_name; + } + } + call_type = "->"; } else if (ptr->function_state.function->common.scope) { class_name = ptr->function_state.function->common.scope->name; @@ -1624,6 +1659,11 @@ ZEND_FUNCTION(debug_print_backtrace) /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; + if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + /* can happen when calling eval from a custom sapi */ + function_name = "unknown"; + build_filename_arg = 0; + } else switch (ptr->opline->op2.u.constant.value.lval) { case ZEND_EVAL: function_name = "eval"; @@ -1668,8 +1708,11 @@ ZEND_FUNCTION(debug_print_backtrace) } zend_printf(") called at [%s:%d]\n", filename, lineno); include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; ++indent; + if (free_class_name) { + efree(free_class_name); + } } } @@ -1677,12 +1720,11 @@ ZEND_FUNCTION(debug_print_backtrace) ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRMLS_DC) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; char *class_name; - char *call_type; char *include_filename = NULL; zval *stack_frame; void **cur_arg_pos = EG(argument_stack).top_element; @@ -1697,6 +1739,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML args -= *(ulong*)args; frames_on_stack++; + /* skip args from incomplete frames */ + while (((args-1) > EG(argument_stack).elements) && *(args-1)) { + args--; + } + if ((args-1) == EG(argument_stack).elements) { arg_stack_consistent = 1; break; @@ -1705,12 +1752,24 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML ptr = EG(current_execute_data); + /* skip "new Exception()" */ + if ((skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) { + ptr = ptr->prev_execute_data; + } + /* skip debug_backtrace() */ if (skip_last--) { int arg_count = *((ulong*)(cur_arg_pos - 2)); cur_arg_pos -= (arg_count + 2); frames_on_stack--; ptr = ptr->prev_execute_data; + + if (arg_stack_consistent) { + /* skip args from incomplete frames */ + while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { + cur_arg_pos--; + } + } } array_init(return_value); @@ -1719,9 +1778,20 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML MAKE_STD_ZVAL(stack_frame); array_init(stack_frame); - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); @@ -1738,19 +1808,20 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1); if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) { - class_name = Z_OBJCE(*ptr->object)->name; - call_type = "->"; + if (ptr->function_state.function->common.scope) { + add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1); + } else { + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC); + add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup); + + } + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1); } else if (ptr->function_state.function->common.scope) { - class_name = ptr->function_state.function->common.scope->name; - call_type = "::"; - } else { - class_name = NULL; - call_type = NULL; - } - - if (class_name) { - add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, 1); - add_assoc_string_ex(stack_frame, "type", sizeof("type"), call_type, 1); + add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1); + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1); } if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { @@ -1763,7 +1834,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; - if (!ptr->opline) { + if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { /* can happen when calling eval from a custom sapi */ function_name = "unknown"; build_filename_arg = 0; @@ -1814,7 +1885,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; } } /* }}} */ @@ -1893,7 +1964,6 @@ ZEND_FUNCTION(get_extension_funcs) } /* }}} */ - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c19317ea7..febd65c50 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.c,v 1.567.2.15 2005/03/10 13:24:32 helly Exp $ */ +/* $Id: zend_compile.c,v 1.567.2.30 2005/07/19 07:33:24 dmitry Exp $ */ #include <zend_language_parser.h> #include "zend.h" @@ -418,6 +418,9 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body } if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) { + if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) { + zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val); + } if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -483,6 +486,12 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) } } +static inline zend_bool zend_is_function_or_method_call(znode *variable) +{ + zend_uint type = variable->u.EA.type; + + return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL)); +} void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) { @@ -494,6 +503,11 @@ void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) if (opline_is_fetch_this(last_op TSRMLS_CC)) { zend_error(E_COMPILE_ERROR, "Cannot re-assign $this"); } + if (zend_is_function_or_method_call(rvar)) { + opline->extended_value = ZEND_RETURNS_FUNCTION; + } else { + opline->extended_value = 0; + } if (result) { opline->result.op_type = IS_VAR; opline->result.u.EA.type = 0; @@ -717,13 +731,6 @@ void zend_check_writable_variable(znode *variable) } } -static inline zend_bool zend_is_function_or_method_call(znode *variable) -{ - zend_uint type = variable->u.EA.type; - - return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL)); -} - void zend_do_begin_variable_parse(TSRMLS_D) { zend_llist fetch_list; @@ -738,51 +745,53 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) zend_llist *fetch_list_ptr; zend_llist_element *le; zend_op *opline, *opline_ptr=NULL; - int num_of_created_opcodes = 0; zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); le = fetch_list_ptr->head; - while (le) { + if (le) { opline_ptr = (zend_op *)le->data; - opline = get_next_op(CG(active_op_array) TSRMLS_CC); - memcpy(opline, opline_ptr, sizeof(zend_op)); - switch (type) { - case BP_VAR_R: - if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { - zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); - } - opline->opcode -= 3; - break; - case BP_VAR_W: - break; - case BP_VAR_RW: - opline->opcode += 3; - break; - case BP_VAR_IS: - if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { - zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); - } - opline->opcode += 6; /* 3+3 */ - break; - case BP_VAR_FUNC_ARG: - opline->opcode += 9; /* 3+3+3 */ - opline->extended_value = arg_offset; - break; - case BP_VAR_UNSET: - if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { - zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting"); - } - opline->opcode += 12; /* 3+3+3+3 */ - break; + if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) { + CG(active_op_array)->uses_this = 1; } - le = le->next; - num_of_created_opcodes++; - } - if (num_of_created_opcodes == 1 && opline_is_fetch_this(opline_ptr TSRMLS_CC)) { - CG(active_op_array)->uses_this = 1; + while (1) { + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + memcpy(opline, opline_ptr, sizeof(zend_op)); + switch (type) { + case BP_VAR_R: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + opline->opcode -= 3; + break; + case BP_VAR_W: + break; + case BP_VAR_RW: + opline->opcode += 3; + break; + case BP_VAR_IS: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + opline->opcode += 6; /* 3+3 */ + break; + case BP_VAR_FUNC_ARG: + opline->opcode += 9; /* 3+3+3 */ + opline->extended_value = arg_offset; + break; + case BP_VAR_UNSET: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting"); + } + opline->opcode += 12; /* 3+3+3+3 */ + break; + } + le = le->next; + if (le == NULL) break; + opline_ptr = (zend_op *)le->data; + } } zend_llist_destroy(fetch_list_ptr); @@ -894,7 +903,8 @@ void zend_do_free(znode *op1 TSRMLS_DC) * Find JMP_NO_CTOR, mark the preceding ASSIGN and the * proceeding INIT_FCALL_BY_NAME as unused */ - if (opline->opcode == ZEND_JMP_NO_CTOR) { + if (opline->opcode == ZEND_JMP_NO_CTOR && + opline->op1.u.var == op1->u.var) { opline->op1.u.EA.type |= EXT_TYPE_UNUSED; (opline-1)->result.u.EA.type |= EXT_TYPE_UNUSED; (opline+1)->op1.u.EA.type |= EXT_TYPE_UNUSED; @@ -965,7 +975,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n op_array.fn_flags = fn_flags; op_array.pass_rest_by_reference = 0; - op_array.scope = CG(active_class_entry); + op_array.scope = is_method?CG(active_class_entry):NULL; op_array.prototype = NULL; op_array.line_start = zend_get_compiled_lineno(TSRMLS_C); @@ -1074,9 +1084,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } if (CG(doc_comment)) { - CG(active_op_array)->doc_comment = estrndup(CG(doc_comment), CG(doc_comment_len)); + CG(active_op_array)->doc_comment = CG(doc_comment); CG(active_op_array)->doc_comment_len = CG(doc_comment_len); - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; } } @@ -1286,6 +1297,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) opline->op2 = *class_name; } opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.u.EA.type = opline->extended_value; opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */ *result = opline->result; } @@ -1370,6 +1382,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) int original_op=op; zend_function **function_ptr_ptr, *function_ptr; int send_by_reference; + int send_function = 0; zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr); function_ptr = *function_ptr_ptr; @@ -1394,6 +1407,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) { /* Method call */ op = ZEND_SEND_VAR_NO_REF; + send_function = ZEND_ARG_SEND_FUNCTION; } else if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) { op = ZEND_SEND_VAR_NO_REF; } @@ -1432,9 +1446,9 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) if (op == ZEND_SEND_VAR_NO_REF) { if (function_ptr) { - opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference; + opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function; } else { - opline->extended_value = 0; + opline->extended_value = send_function; } } else { if (function_ptr) { @@ -1455,7 +1469,7 @@ static int generate_free_switch_expr(zend_switch_entry *switch_entry TSRMLS_DC) zend_op *opline; if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) { - return 0; + return (switch_entry->cond.op_type == IS_UNUSED); } opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -1854,9 +1868,18 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro zend_property_info *child_info; zend_class_entry *parent_ce = ce->parent; - if (parent_info->flags & ZEND_ACC_PRIVATE) { + if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) { if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) { child_info->flags |= ZEND_ACC_CHANGED; + } else { + zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info); + if(ce->type & ZEND_INTERNAL_CLASS) { + zend_duplicate_property_info_internal(child_info); + } else { + zend_duplicate_property_info(child_info); + } + child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */ + child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */ } return 0; /* don't copy access information to child */ } @@ -1868,6 +1891,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey); } + + if(parent_info->flags & ZEND_ACC_CHANGED) { + child_info->flags |= ZEND_ACC_CHANGED; + } + if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) { zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) { @@ -2167,6 +2195,19 @@ void zend_do_early_binding(TSRMLS_D) if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) { return; } + /* clear unnecessary ZEND_FETCH_CLASS opcode */ + if (opline > CG(active_op_array)->opcodes && + (opline-1)->opcode == ZEND_FETCH_CLASS) { + zend_op *fetch_class_opline = opline-1; + + zval_dtor(&fetch_class_opline->op2.u.constant); + fetch_class_opline->opcode = ZEND_NOP; + memset(&fetch_class_opline->op1, 0, sizeof(znode)); + memset(&fetch_class_opline->op2, 0, sizeof(znode)); + SET_UNUSED(fetch_class_opline->op1); + SET_UNUSED(fetch_class_opline->op2); + SET_UNUSED(fetch_class_opline->result); + } } else { /* We currently don't early-bind classes that implement interfaces */ return; @@ -2496,10 +2537,20 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC); new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C); - new_class_entry->line_start = zend_get_compiled_lineno(TSRMLS_C); - new_class_entry->ce_flags |= class_token->u.constant.value.lval; + new_class_entry->line_start = class_token->u.opline_num; + new_class_entry->ce_flags |= class_token->u.EA.type; if (parent_class_name && parent_class_name->op_type != IS_UNUSED) { + switch (parent_class_name->u.EA.type) { + case ZEND_FETCH_CLASS_SELF: + zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved"); + break; + case ZEND_FETCH_CLASS_PARENT: + zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved"); + break; + default: + break; + } doing_inheritance = 1; } @@ -2529,9 +2580,10 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod CG(implementing_class) = opline->result; if (CG(doc_comment)) { - CG(active_class_entry)->doc_comment = estrndup(CG(doc_comment), CG(doc_comment_len)); + CG(active_class_entry)->doc_comment = CG(doc_comment); CG(active_class_entry)->doc_comment_len = CG(doc_comment_len); - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; } } @@ -2575,7 +2627,8 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML /* Inherit interfaces */ if (ce->num_interfaces > 0) { - ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *)*ce->num_interfaces); + ce->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *)*ce->num_interfaces); + memset(ce->interfaces, 0, sizeof(zend_class_entry *)*ce->num_interfaces); } if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) { @@ -2590,8 +2643,26 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML void zend_do_implements_interface(znode *interface_znode TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *opline; + switch (interface_znode->u.EA.type) { + case ZEND_FETCH_CLASS_SELF: + zend_error(E_COMPILE_ERROR, "Cannot use 'self' as interface name as it is reserved"); + break; + case ZEND_FETCH_CLASS_PARENT: + zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as interface name as it is reserved"); + break; + default: + if (CG(active_op_array)->last > 0) { + opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; + if (opline->opcode == ZEND_FETCH_CLASS) { + opline->extended_value = ZEND_FETCH_CLASS_INTERFACE; + } + } + break; + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ADD_INTERFACE; opline->op1 = CG(implementing_class); opline->op2 = *interface_znode; @@ -2958,9 +3029,16 @@ void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr) zend_symtable_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL); zval_dtor(&offset->u.constant); break; + case IS_NULL: + zend_symtable_update(result->u.constant.value.ht, "", 1, &element, sizeof(zval *), NULL); + break; case IS_LONG: + case IS_BOOL: zend_hash_index_update(result->u.constant.value.ht, offset->u.constant.value.lval, &element, sizeof(zval *), NULL); break; + case IS_DOUBLE: + zend_hash_index_update(result->u.constant.value.ht, (long)offset->u.constant.value.dval, &element, sizeof(zval *), NULL); + break; } } else { zend_hash_next_index_insert(result->u.constant.value.ht, &element, sizeof(zval *), NULL); @@ -3013,7 +3091,6 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) zend_llist_element *dimension; zend_op *opline; znode last_container; - int opcode_index; int last_op_number; zend_op *last_op; @@ -3055,14 +3132,10 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) ((list_llist_element *) le->data)->value = last_container; zend_llist_destroy(&((list_llist_element *) le->data)->dimensions); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); - opcode_index = - 1; last_op_number = get_next_op_number(CG(active_op_array))-1; last_op = &CG(active_op_array)->opcodes[last_op_number]; - if (last_op->opcode == ZEND_FETCH_OBJ_W) { - opcode_index = - 2; - } zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC); - CG(active_op_array)->opcodes[CG(active_op_array)->last + opcode_index].result.u.EA.type |= EXT_TYPE_UNUSED; + zend_do_free(result TSRMLS_CC); le = le->next; } zend_llist_destroy(&CG(dimension_llist)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f31249cd4..942a04227 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_compile.h,v 1.284.2.2 2004/09/16 00:44:12 andi Exp $ */ +/* $Id: zend_compile.h,v 1.284.2.6 2005/06/24 08:45:43 dmitry Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -41,10 +41,13 @@ #define DEC_BPC(op_array) if (CG(interactive)) { ((op_array)->backpatch_count--); } #define HANDLE_INTERACTIVE() if (CG(interactive)) { execute_new_code(TSRMLS_C); } -#define RESET_DOC_COMMENT() \ - { \ - CG(doc_comment) = NULL; \ - CG(doc_comment_len) = 0; \ +#define RESET_DOC_COMMENT() \ + { \ + if (CG(doc_comment)) { \ + efree(CG(doc_comment)); \ + CG(doc_comment) = NULL; \ + } \ + CG(doc_comment_len) = 0; \ } typedef struct _zend_op_array zend_op_array; @@ -131,6 +134,9 @@ typedef struct _zend_try_catch_element { /* method flag (bc only), any method that has this flag can be used statically and non statically. */ #define ZEND_ACC_ALLOW_STATIC 0x10000 +/* shadow of parent's private method/property */ +#define ZEND_ACC_SHADOW 0x20000 + char *zend_visibility_string(zend_uint fn_flags); @@ -738,6 +744,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_MAIN 3 #define ZEND_FETCH_CLASS_GLOBAL 4 #define ZEND_FETCH_CLASS_AUTO 5 +#define ZEND_FETCH_CLASS_INTERFACE 6 /* variable parsing type (compile-time) */ @@ -798,6 +805,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ARG_SEND_BY_REF (1<<0) #define ZEND_ARG_COMPILE_TIME_BOUND (1<<1) +#define ZEND_ARG_SEND_FUNCTION (1<<2) #define AI_USE_PTR(ai) \ if ((ai).ptr_ptr) { \ diff --git a/Zend/zend_config.w32.h b/Zend/zend_config.w32.h index ca5558cd5..0d046effe 100644 --- a/Zend/zend_config.w32.h +++ b/Zend/zend_config.w32.h @@ -17,11 +17,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_config.w32.h,v 1.36.2.1 2004/09/15 12:29:24 derick Exp $ */ +/* $Id: zend_config.w32.h,v 1.36.2.2 2005/06/08 15:57:46 sniper Exp $ */ #ifndef ZEND_CONFIG_W32_H #define ZEND_CONFIG_W32_H +#define USE_ZEND_ALLOC 1 #define HAVE_ALLOCA 1 #define HAVE_LIMITS_H 1 #define _CRTDBG_MAP_ALLOC diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index fe0ae5bd5..07ebd8187 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_exceptions.c,v 1.65.2.3 2004/12/27 13:55:46 zeev Exp $ */ +/* $Id: zend_exceptions.c,v 1.65.2.4 2005/06/27 17:42:06 stas Exp $ */ #include "zend.h" #include "zend_API.h" @@ -298,10 +298,20 @@ static int _build_trace_args(zval **arg, int num_args, va_list args, zend_hash_k TRACE_APPEND_STR("Array, "); break; case IS_OBJECT: { + char *class_name; + zend_uint class_name_len; + int dup; TSRMLS_FETCH(); TRACE_APPEND_STR("Object("); - TRACE_APPEND_STRL(Z_OBJCE_PP(arg)->name, strlen(Z_OBJCE_PP(arg)->name)); + + dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC); + + TRACE_APPEND_STRL(class_name, class_name_len); + if(!dup) { + efree(class_name); + } + TRACE_APPEND_STR("), "); break; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ebff3e976..5bdc015c0 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.c,v 1.652.2.22 2005/03/21 16:22:10 andi Exp $ */ +/* $Id: zend_execute.c,v 1.652.2.49 2005/09/01 13:21:56 dmitry Exp $ */ #define ZEND_INTENSIVE_DEBUGGING 0 @@ -54,6 +54,17 @@ static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_ #define TEMP_VAR_STACK_LIMIT 2000 +#define MAKE_REAL_ZVAL_PTR(val) \ + do { \ + zval *_tmp; \ + ALLOC_ZVAL(_tmp); \ + _tmp->value = (val)->value; \ + _tmp->type = (val)->type; \ + _tmp->refcount = 1; \ + _tmp->is_ref = 0; \ + val = _tmp; \ + } while (0) + /* former zend_execute_locks.h */ static inline void zend_pzval_lock_func(zval *z) { @@ -154,22 +165,9 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC) static inline void zend_fetch_property_address_inner(zval *object, znode *op2, znode *result, temp_variable *Ts, int type TSRMLS_DC) { zval *prop_ptr = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval tmp; - - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *prop_ptr; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - prop_ptr = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(prop_ptr); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(prop_ptr); } if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { @@ -192,10 +190,9 @@ static inline void zend_fetch_property_address_inner(zval *object, znode *op2, z T(result->u.var).var.ptr_ptr = &EG(error_zval_ptr); } - if (prop_ptr == &tmp) { - zval_dtor(prop_ptr); + if (EG(free_op2)) { + zval_ptr_dtor(&prop_ptr); } - FREE_OP(Ts, op2, EG(free_op2)); } @@ -240,12 +237,6 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) { variable_ptr_ptr = &EG(uninitialized_zval_ptr); } else if (variable_ptr != value_ptr) { - variable_ptr->refcount--; - if (variable_ptr->refcount==0) { - zendi_zval_dtor(*variable_ptr); - FREE_ZVAL(variable_ptr); - } - if (!PZVAL_IS_REF(value_ptr)) { /* break it away */ value_ptr->refcount--; @@ -258,9 +249,14 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z value_ptr->refcount = 1; value_ptr->is_ref = 1; } - *variable_ptr_ptr = value_ptr; value_ptr->refcount++; + + variable_ptr->refcount--; + if (variable_ptr->refcount==0) { + zendi_zval_dtor(*variable_ptr); + FREE_ZVAL(variable_ptr); + } } else if (!variable_ptr->is_ref) { if (variable_ptr_ptr == value_ptr_ptr) { SEPARATE_ZVAL(variable_ptr_ptr); @@ -393,15 +389,27 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode /* separate our value if necessary */ if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { zval *orig_value = value; - + char *class_name; + zend_uint class_name_len; + int dup; + ALLOC_ZVAL(value); *value = *orig_value; value->is_ref = 0; value->refcount = 0; + + dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(orig_value)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(orig_value)->name); + + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + + if(!dup) { + efree(class_name); + } + value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC); } else if (value_op->op_type == IS_TMP_VAR) { zval *orig_value = value; @@ -423,40 +431,29 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode value->refcount++; if (opcode == ZEND_ASSIGN_OBJ) { - zval tmp; - - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *property_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - property_name = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(property_name); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property_name); } Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC); - if (property_name == &tmp) { - zval_dtor(property_name); - } } else { /* Note: property_name in this case is really the array index! */ if (!Z_OBJ_HT_P(object)->write_dimension) { zend_error(E_ERROR, "Cannot use object as array"); } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property_name); + } Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC); } - FREE_OP(Ts, op2, EG(free_op2)); if (result) { T(result->u.var).var.ptr = value; T(result->u.var).var.ptr_ptr = &T(result->u.var).var.ptr; /* this is so that we could use it in FETCH_DIM_R, etc. - see bug #27876 */ SELECTIVE_PZVAL_LOCK(value, result); } + if (EG(free_op2)) { + zval_ptr_dtor(&property_name); + } zval_ptr_dtor(&value); } @@ -566,40 +563,60 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 } if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(value)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } else if (PZVAL_IS_REF(variable_ptr)) { - if (variable_ptr != value) { + if (variable_ptr != value) { zend_uint refcount = variable_ptr->refcount; zval garbage; - + if (type != IS_TMP_VAR) { value->refcount++; } + garbage = *variable_ptr; *variable_ptr = *value; variable_ptr->refcount = refcount; variable_ptr->is_ref = 1; - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(value)->name); + + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + if (type != IS_TMP_VAR) { value->refcount--; } + zendi_zval_dtor(garbage); } } else { - variable_ptr->refcount--; - if (variable_ptr->refcount == 0) { - zendi_zval_dtor(*variable_ptr); - } else { - ALLOC_ZVAL(variable_ptr); - *variable_ptr_ptr = variable_ptr; + if (variable_ptr != value) { + value->refcount++; + variable_ptr->refcount--; + if (variable_ptr->refcount == 0) { + zendi_zval_dtor(*variable_ptr); + } else { + ALLOC_ZVAL(variable_ptr); + *variable_ptr_ptr = variable_ptr; + } + *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + zval_ptr_dtor(&value); } - *variable_ptr = *value; - INIT_PZVAL(variable_ptr); - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(value)->name); - variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); } + + if(!dup) { + efree(class_name); + } + } else if (PZVAL_IS_REF(variable_ptr)) { if (variable_ptr!=value) { zend_uint refcount = variable_ptr->refcount; @@ -945,7 +962,7 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, new_zval->refcount++; if (zend_hash_next_index_insert(container->value.ht, &new_zval, sizeof(zval *), (void **) retval) == FAILURE) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - *retval = &EG(uninitialized_zval_ptr); + *retval = &EG(error_zval_ptr); new_zval->refcount--; } } else { @@ -1003,8 +1020,12 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, zend_error(E_ERROR, "Cannot use object as array"); } else { zval *dim = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval *overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); + zval *overloaded_result; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(dim); + } + overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); if (overloaded_result) { switch (type) { case BP_VAR_RW: @@ -1021,8 +1042,10 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, *retval = &EG(error_zval_ptr); } AI_USE_PTR(T(result->u.var).var); - FREE_OP(Ts, op2, EG(free_op2)); SELECTIVE_PZVAL_LOCK(**retval, result); + if (EG(free_op2)) { + zval_ptr_dtor(&dim); + } } break; default: { @@ -1140,41 +1163,29 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o } else { *retval = EG(error_zval_ptr); } + SELECTIVE_PZVAL_LOCK(*retval, result); } else { zval *offset; - zval tmp; offset = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *offset; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - offset = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(offset); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (offset == &tmp) { - zval_dtor(offset); - } - FREE_OP(Ts, op2, EG(free_op2)); if (RETURN_VALUE_UNUSED(result) && ((*retval)->refcount == 0)) { zval_dtor(*retval); FREE_ZVAL(*retval); - return; /* no need for locking */ + } else { + SELECTIVE_PZVAL_LOCK(*retval, result); + } + + if (EG(free_op2)) { + zval_ptr_dtor(&offset); } } - - SELECTIVE_PZVAL_LOCK(*retval, result); } static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1197,6 +1208,10 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp return; } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); + } + /* here we are sure we are dealing with an object */ if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { @@ -1232,7 +1247,9 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp zval_ptr_dtor(&z); } - FREE_OP(Ts, op2, EG(free_op2)); + if (EG(free_op2)) { + zval_ptr_dtor(&property); + } } static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1253,6 +1270,10 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem return; } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); + } + /* here we are sure we are dealing with an object */ if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { @@ -1271,6 +1292,7 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem if (!have_get_ptr) { zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC); + zval *z_copy; if (z->type == IS_OBJECT && Z_OBJ_HT_P(z)->get) { zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC); @@ -1283,13 +1305,22 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem } *retval = *z; zendi_zval_copy_ctor(*retval); - incdec_op(z); + ALLOC_ZVAL(z_copy); + *z_copy = *z; + zendi_zval_copy_ctor(*z_copy); + INIT_PZVAL(z_copy); + incdec_op(z_copy); z->refcount++; - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC); + zval_ptr_dtor(&z_copy); + /* this would destroy z if it was returned with refcount == 0 and undo + recount++ above otherwise */ zval_ptr_dtor(&z); } - FREE_OP(Ts, op2, EG(free_op2)); + if (EG(free_op2)) { + zval_ptr_dtor(&property); + } } @@ -1328,7 +1359,7 @@ static int zend_check_symbol(zval **pz TSRMLS_DC) #define SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ - EX(opline) = new_op; + EX(opline) = new_op; \ #define INC_OPCODE() \ if (!EG(exception)) { \ @@ -1638,7 +1669,6 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result zval *property = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); zval *free_value; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_value, BP_VAR_R); - zval tmp; znode *result = &opline->result; zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; @@ -1657,19 +1687,8 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result SELECTIVE_PZVAL_LOCK(*retval, result); } else { /* here we are sure we are dealing with an object */ - switch (opline->op2.op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *property; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - property = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(property); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); } /* here property is a string */ @@ -1722,11 +1741,9 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result zval_ptr_dtor(&z); } - if (property == &tmp) { - zval_dtor(property); + if (EG(free_op2)) { + zval_ptr_dtor(&property); } - - FREE_OP(Ts, op2, EG(free_op2)); FREE_OP(Ts, value, free_value); } @@ -2114,6 +2131,9 @@ int zend_fetch_dim_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) /* Behave like FETCH_DIM_W */ zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC); } else { + if (opline->op2.op_type == IS_UNUSED) { + zend_error(E_ERROR, "Cannot use [] for reading"); + } /* Behave like FETCH_DIM_R, except for locking used for list() */ zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); AI_USE_PTR(EX_T(opline->result.u.var).var); @@ -2246,7 +2266,7 @@ int zend_assign_dim_handler(ZEND_OPCODE_HANDLER_ARGS) zend_fetch_dimension_address(&op_data->op2, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (EG(free_op1)?IS_TMP_VAR:opline->op1.op_type), EX(Ts) TSRMLS_CC); + zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (EG(free_op1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); } /* assign_dim has two opcodes! */ INC_OPCODE(); @@ -2270,6 +2290,19 @@ int zend_assign_ref_handler(ZEND_OPCODE_HANDLER_ARGS) { zval **value_ptr_ptr = get_zval_ptr_ptr(&opline->op2, EX(Ts), BP_VAR_W); + if (opline->op2.op_type == IS_VAR && + value_ptr_ptr && + !(*value_ptr_ptr)->is_ref && + opline->extended_value == ZEND_RETURNS_FUNCTION && + !EX_T(opline->op2.u.var).var.fcall_returned_reference) { + PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */ + zend_error(E_STRICT, "Only variables should be assigned by reference"); + return zend_assign_handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + if (opline->op1.op_type == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) { + zend_error(E_ERROR, "Cannot assign by reference to overloaded object"); + } + zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_W), value_ptr_ptr, EX(Ts) TSRMLS_CC); NEXT_OPCODE(); @@ -2454,7 +2487,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) if (opline->op2.op_type == IS_UNUSED) { - EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, ZEND_FETCH_CLASS_AUTO, opline->extended_value TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); NEXT_OPCODE(); } @@ -2465,7 +2498,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name); break; case IS_STRING: - EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC); break; default: zend_error(E_ERROR, "Class name must be a valid object or a string"); @@ -2806,9 +2839,11 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS) if (EG(exception) && EX(fbc) && EX(fbc)->common.fn_flags&ZEND_ACC_CTOR) { EG(This)->refcount--; if (EG(This)->refcount == 1) { - zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + if (should_change_scope && EG(This) != current_this) { + zval_ptr_dtor(&EG(This)); } - zval_ptr_dtor(&EG(This)); } else if (should_change_scope) { zval_ptr_dtor(&EG(This)); } @@ -2879,10 +2914,11 @@ int zend_return_handler(ZEND_OPCODE_HANDLER_ARGS) } if (!(*retval_ptr_ptr)->is_ref) { - if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr - || (opline->extended_value == ZEND_RETURNS_FUNCTION && !EX_T(opline->op1.u.var).var.fcall_returned_reference)) { - zend_error(E_STRICT, "Only variable references should be returned by reference"); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && + EX_T(opline->op1.u.var).var.fcall_returned_reference) { + } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) { PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */ + zend_error(E_STRICT, "Only variable references should be returned by reference"); goto return_by_value; } } @@ -2896,16 +2932,27 @@ return_by_value: retval_ptr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); **EG(return_value_ptr_ptr) = *retval_ptr; INIT_PZVAL(*EG(return_value_ptr_ptr)); if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(retval_ptr)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); (*EG(return_value_ptr_ptr))->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + + if(!dup) { + efree(class_name); + } } else if (!EG(free_op1)) { /* Not a temp var */ - if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { + if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || + (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); **EG(return_value_ptr_ptr) = *retval_ptr; (*EG(return_value_ptr_ptr))->is_ref = 0; @@ -3036,7 +3083,10 @@ int zend_send_var_no_ref_handler(ZEND_OPCODE_HANDLER_ARGS) } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) { return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - { + if ((opline->extended_value & ZEND_ARG_SEND_FUNCTION) && + !EX_T(opline->op1.u.var).var.fcall_returned_reference) { + zend_error(E_ERROR, "Only variables can be passed by reference"); + } else { zval *varptr; varptr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); @@ -3291,7 +3341,7 @@ int zend_clone_handler(ZEND_OPCODE_HANDLER_ARGS) NEXT_OPCODE(); } - ce = Z_OBJCE_P(obj); + ce = (Z_OBJ_HT_P(obj)->get_class_entry) ? Z_OBJCE_P(obj) : NULL; clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { @@ -3654,62 +3704,70 @@ int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS) long index; if (container) { - HashTable *ht; - if (opline->extended_value == ZEND_UNSET_DIM) { switch (Z_TYPE_PP(container)) { - case IS_ARRAY: - ht = Z_ARRVAL_PP(container); + case IS_ARRAY: { + HashTable *ht = Z_ARRVAL_PP(container); + switch (offset->type) { + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: + if (offset->type == IS_DOUBLE) { + index = (long) offset->value.dval; + } else { + index = offset->value.lval; + } + + zend_hash_index_del(ht, index); + break; + case IS_STRING: + zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1); + break; + case IS_NULL: + zend_hash_del(ht, "", sizeof("")); + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); break; + } case IS_OBJECT: - ht = NULL; if (!Z_OBJ_HT_P(*container)->unset_dimension) { zend_error(E_ERROR, "Cannot use object as array"); } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } Z_OBJ_HT_P(*container)->unset_dimension(*container, offset TSRMLS_CC); + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } break; case IS_STRING: zend_error(E_ERROR, "Cannot unset string offsets"); return 0; /* bailed out before */ default: - ht = NULL; + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); break; } } else { /* ZEND_UNSET_OBJ */ - ht = NULL; if (Z_TYPE_PP(container) == IS_OBJECT) { + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC); - } - } - if (ht) { - switch (offset->type) { - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - if (offset->type == IS_DOUBLE) { - index = (long) offset->value.dval; - } else { - index = offset->value.lval; - } - - zend_hash_index_del(ht, index); - break; - case IS_STRING: - zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1); - break; - case IS_NULL: - zend_hash_del(ht, "", sizeof("")); - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } } } } else { /* overloaded element */ + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } - FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); NEXT_OPCODE(); } @@ -3727,6 +3785,12 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) if (array_ptr_ptr == NULL) { ALLOC_INIT_ZVAL(array_ptr); } else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) { + if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) { + zend_error(E_WARNING, "foreach() can not iterate over objects without PHP class"); + opline++; + SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); + return 0; + } ce = Z_OBJCE_PP(array_ptr_ptr); if (!ce || ce->get_iterator == NULL) { SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr); @@ -3747,7 +3811,7 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) *tmp = *array_ptr; INIT_PZVAL(tmp); array_ptr = tmp; - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJ_HT_P(array_ptr)->get_class_entry) { ce = Z_OBJCE_P(array_ptr); } else { array_ptr->refcount++; @@ -3760,7 +3824,6 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) if (iter && !EG(exception)) { array_ptr = zend_iterator_wrap(iter TSRMLS_CC); } else { - zval_ptr_dtor(&array_ptr); FREE_OP(Ts, op1, EG(free_op1)); if (!EG(exception)) { zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name); @@ -3779,6 +3842,11 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); + if (EG(exception)) { + array_ptr->refcount--; + zval_ptr_dtor(&array_ptr); + NEXT_OPCODE(); + } } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { /* probably redundant */ @@ -3855,13 +3923,28 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) /* This could cause an endless loop if index becomes zero again. * In case that ever happens we need an additional flag. */ iter->funcs->move_forward(iter TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) { /* reached end of iteration */ + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); return 0; /* CHECK_ME */ } iter->funcs->get_current_data(iter, &value TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } if (!value) { /* failure in get_current_data */ SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); @@ -3869,6 +3952,11 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) } if (iter->funcs->get_current_key) { key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } else { key_type = HASH_KEY_IS_LONG; int_key = iter->index; @@ -3991,12 +4079,13 @@ int zend_isset_isempty_var_handler(ZEND_OPCODE_HANDLER_ARGS) static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HANDLER_ARGS) { zval **container = get_obj_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); - zval *offset = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); zval **value = NULL; int result = 0; long index; if (container) { + zval *offset = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + if ((*container)->type == IS_ARRAY) { HashTable *ht; int isset = 0; @@ -4049,12 +4138,19 @@ static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HAN } break; } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } else if ((*container)->type == IS_OBJECT) { + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } if (prop_dim) { result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC); } else { result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC); } + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */ zval tmp; @@ -4076,6 +4172,9 @@ static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HAN } break; } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); + } else { + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } } @@ -4090,8 +4189,6 @@ static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HAN break; } - FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); - NEXT_OPCODE(); } @@ -4234,7 +4331,7 @@ int zend_instanceof_handler(ZEND_OPCODE_HANDLER_ARGS) zval *expr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); zend_bool result; - if (Z_TYPE_P(expr) == IS_OBJECT) { + if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC); } else { result = 0; @@ -4284,6 +4381,7 @@ int zend_handle_exception_handler(ZEND_OPCODE_HANDLER_ARGS) while (*stack_zval_pp != NULL) { zval_ptr_dtor(stack_zval_pp); EG(argument_stack).top_element--; + EG(argument_stack).top--; stack_zval_pp--; } @@ -4298,6 +4396,13 @@ int zend_handle_exception_handler(ZEND_OPCODE_HANDLER_ARGS) } } + while (EX(fbc)) { + if (EX(object)) { + zval_ptr_dtor(&EX(object)); + } + zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &EX(calling_scope), &EX(object), &EX(fbc)); + } + if (encapsulating_block == -1) { RETURN_FROM_EXECUTE_LOOP(execute_data); } else { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 324a76385..ddf92e1b0 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute.h,v 1.72 2004/03/16 10:14:52 helly Exp $ */ +/* $Id: zend_execute.h,v 1.72.2.1 2005/04/24 14:49:00 sniper Exp $ */ #ifndef ZEND_EXECUTE_H #define ZEND_EXECUTE_H @@ -49,6 +49,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); +void shutdown_destructors(TSRMLS_D); ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); ZEND_API int zend_is_true(zval *op); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e17c21f6c..ea8b6d3c4 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_execute_API.c,v 1.287.2.11 2005/03/19 14:29:18 helly Exp $ */ +/* $Id: zend_execute_API.c,v 1.287.2.25 2005/09/02 07:46:39 dmitry Exp $ */ #include <stdio.h> #include <signal.h> @@ -185,6 +185,15 @@ void init_executor(TSRMLS_D) EG(This) = NULL; } +void shutdown_destructors(TSRMLS_D) { + zend_try { + zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); + } zend_catch { + /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ + zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); + } zend_end_try(); +} + void shutdown_executor(TSRMLS_D) { zend_try { @@ -204,7 +213,6 @@ void shutdown_executor(TSRMLS_D) } */ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); - zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); zend_hash_graceful_reverse_destroy(&EG(symbol_table)); } zend_catch { /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ @@ -277,11 +285,6 @@ void shutdown_executor(TSRMLS_D) clean_non_persistent_constants(TSRMLS_C); } zend_end_try(); - /* The regular list must be destroyed after the main symbol table, - * op arrays, and constants are destroyed. - */ - zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); - zend_try { #if ZEND_DEBUG signal(SIGSEGV, original_sigsegv_handler); @@ -384,15 +387,17 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D) ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) { + zval *zv = *zval_ptr; + #if DEBUG_ZEND>=2 printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1); #endif - (*zval_ptr)->refcount--; - if ((*zval_ptr)->refcount==0) { - zval_dtor(*zval_ptr); - safe_free_zval_ptr_rel(*zval_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); - } else if ((*zval_ptr)->refcount == 1) { - (*zval_ptr)->is_ref = 0; + zv->refcount--; + if (zv->refcount==0) { + zval_dtor(zv); + safe_free_zval_ptr_rel(zv ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); + } else if (zv->refcount == 1) { + zv->is_ref = 0; } } @@ -427,11 +432,13 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) if (p->type == IS_CONSTANT) { int refcount; + zend_uchar is_ref; - SEPARATE_ZVAL(pp); + SEPARATE_ZVAL_IF_NOT_REF(pp); p = *pp; refcount = p->refcount; + is_ref = p->is_ref; if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", @@ -448,15 +455,15 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) *p = const_value; } - INIT_PZVAL(p); p->refcount = refcount; + p->is_ref = is_ref; } else if (p->type == IS_CONSTANT_ARRAY) { zval **element, *new_val; char *str_index; uint str_index_len; ulong num_index; - SEPARATE_ZVAL(pp); + SEPARATE_ZVAL_IF_NOT_REF(pp); p = *pp; p->type = IS_ARRAY; @@ -562,6 +569,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_op_array *original_op_array; zend_op **original_opline_ptr; zval *orig_free_op1, *orig_free_op2; + zval *orig_garbage[2]; + int orig_garbage_ptr; int (*orig_unary_op)(zval *result, zval *op1); int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC); zend_class_entry *current_scope; @@ -587,6 +596,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS /* Initialize execute_data */ if (EG(current_execute_data)) { execute_data = *EG(current_execute_data); + EX(op_array) = NULL; + EX(opline) = NULL; } else { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, @@ -732,7 +743,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS return FAILURE; } } - if (fci_cache) { + if (fci_cache && + (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION || + ((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call)) { fci_cache->function_handler = EX(function_state).function; fci_cache->object_pp = fci->object_pp; fci_cache->calling_scope = calling_scope; @@ -753,6 +766,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zval *new_zval; if (fci->no_separation) { + if(i) { + /* hack to clean up the stack */ + zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) i, NULL); + zend_ptr_stack_clear_multiple(TSRMLS_C); + } return FAILURE; } ALLOC_ZVAL(new_zval); @@ -849,6 +867,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS orig_free_op2 = EG(free_op2); orig_unary_op = EG(unary_op); orig_binary_op = EG(binary_op); + orig_garbage_ptr = EG(garbage_ptr); + EG(garbage_ptr) = 0; + if (orig_garbage_ptr > 0) { + memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr); + } zend_execute(EG(active_op_array) TSRMLS_CC); if (!fci->symbol_table) { zend_hash_destroy(EG(active_symbol_table)); @@ -862,6 +885,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(free_op2) = orig_free_op2; EG(unary_op) = orig_unary_op; EG(binary_op) = orig_binary_op; + if (orig_garbage_ptr > 0) { + while (EG(garbage_ptr)) { + zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + } + EG(garbage_ptr) = orig_garbage_ptr; + memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr); + } } else { ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); if (EX(function_state).function->common.scope) { @@ -895,7 +925,7 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** { zval **args[1]; zval autoload_function; - zval class_name, *class_name_ptr = &class_name; + zval *class_name_ptr; zval *retval_ptr; int retval; char *lc_name; @@ -934,8 +964,9 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0); + ALLOC_ZVAL(class_name_ptr); INIT_PZVAL(class_name_ptr); - ZVAL_STRINGL(class_name_ptr, name, name_length, 0); + ZVAL_STRINGL(class_name_ptr, name, name_length, 1); args[0] = &class_name_ptr; @@ -943,6 +974,8 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** EG(exception) = NULL; retval = call_user_function_ex(EG(function_table), NULL, &autoload_function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC); + zval_ptr_dtor(&class_name_ptr); + zend_hash_del(EG(in_autoload), lc_name, name_length+1); if (retval == FAILURE) { @@ -1081,6 +1114,17 @@ void execute_new_code(TSRMLS_D) opline->op2.u.constant.is_ref = 1; opline->op2.u.constant.refcount = 2; } + switch (opline->opcode) { + case ZEND_JMP: + opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num]; + break; + } opline->handler = zend_opcode_handlers[opline->opcode]; opline++; } @@ -1238,10 +1282,17 @@ void zend_set_timeout(long seconds) t_r.it_value.tv_sec = seconds; t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0; +# ifdef __CYGWIN__ + setitimer(ITIMER_REAL, &t_r, NULL); + signal(SIGALRM, zend_timeout); + sigemptyset(&sigset); + sigaddset(&sigset, SIGALRM); +# else setitimer(ITIMER_PROF, &t_r, NULL); signal(SIGPROF, zend_timeout); sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); +# endif sigprocmask(SIG_UNBLOCK, &sigset, NULL); } # endif @@ -1260,7 +1311,11 @@ void zend_unset_timeout(TSRMLS_D) no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0; +#ifdef __CYGWIN__ + setitimer(ITIMER_REAL, &no_timeout, NULL); +#else setitimer(ITIMER_PROF, &no_timeout, NULL); +#endif } # endif #endif @@ -1296,7 +1351,11 @@ check_fetch_type: } if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) { - zend_error(E_ERROR, "Class '%s' not found", class_name); + 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 *pce; } @@ -1339,8 +1398,9 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); if (ai.cnt) { - zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", ce->name, ai.cnt, + ai.cnt > 1 ? "s" : "", DISPLAY_ABSTRACT_FN(0), DISPLAY_ABSTRACT_FN(1), DISPLAY_ABSTRACT_FN(2) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index d35646419..5ae039d65 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_hash.c,v 1.115 2004/07/10 07:45:49 andi Exp $ */ +/* $Id: zend_hash.c,v 1.115.2.1 2005/04/25 06:11:00 dmitry Exp $ */ #include "zend.h" @@ -1054,7 +1054,7 @@ ZEND_API int zend_hash_get_current_key_ex(HashTable *ht, char **str_index, uint if (p) { if (p->nKeyLength) { if (duplicate) { - *str_index = estrndup(p->arKey, p->nKeyLength); + *str_index = estrndup(p->arKey, p->nKeyLength-1); } else { *str_index = p->arKey; } diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index 75de52fbd..1a3c82ccc 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_highlight.c,v 1.43.2.4 2005/01/02 23:54:59 iliaa Exp $ */ +/* $Id: zend_highlight.c,v 1.43.2.5 2005/05/22 16:40:49 iliaa Exp $ */ #include "zend.h" #include <zend_language_parser.h> @@ -71,17 +71,9 @@ ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) while (ptr<end) { if (*ptr==' ') { - /* Series of spaces should be displayed as 's - * whereas single spaces should be displayed as a space - */ - if ((ptr+1) < end && *(ptr+1)==' ') { - do { - zend_html_putc(*ptr); - } while ((++ptr < end) && (*ptr==' ')); - } else { - ZEND_PUTC(*ptr); - ptr++; - } + do { + zend_html_putc(*ptr); + } while ((++ptr < end) && (*ptr==' ')); } else { zend_html_putc(*ptr++); } diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 020e6f2e5..de9a8e1f3 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_ini.c,v 1.33.2.2 2004/11/03 23:14:31 derick Exp $ */ +/* $Id: zend_ini.c,v 1.33.2.4 2005/09/02 21:08:43 sniper Exp $ */ #include "zend.h" #include "zend_qsort.h" @@ -48,7 +48,12 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS { if (ini_entry->modified) { if (ini_entry->on_modify) { - ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC); + zend_try { + /* even if on_modify bails out, we have to continue on with restoring, + since there can be allocated variables that would be freed on MM shutdown + and would lead to memory corruption later ini entry is modified again */ + ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC); + } zend_end_try(); } efree(ini_entry->value); ini_entry->value = ini_entry->orig_value; @@ -149,6 +154,7 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num zend_ini_entry *hashed_ini_entry; zval default_value; HashTable *directives = registered_zend_ini_directives; + zend_bool config_directive_success = 0; #ifdef ZTS /* if we are called during the request, eg: from dl(), @@ -166,6 +172,7 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num while (p->name) { p->module_number = module_number; + config_directive_success = 0; if (zend_hash_add(directives, p->name, p->name_length, p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry)==FAILURE) { zend_unregister_ini_entries(module_number TSRMLS_CC); return FAILURE; @@ -175,11 +182,12 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num || hashed_ini_entry->on_modify(hashed_ini_entry, default_value.value.str.val, default_value.value.str.len, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC)==SUCCESS) { hashed_ini_entry->value = default_value.value.str.val; hashed_ini_entry->value_length = default_value.value.str.len; + config_directive_success = 1; } - } else { - if (hashed_ini_entry->on_modify) { - hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); - } + } + + if (!config_directive_success && hashed_ini_entry->on_modify) { + hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); } p++; } diff --git a/Zend/zend_language_parser.c b/Zend/zend_language_parser.c index 502571692..4a74878d7 100644 --- a/Zend/zend_language_parser.c +++ b/Zend/zend_language_parser.c @@ -148,7 +148,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.144.2.2 2004/09/16 05:44:39 sebastian Exp $ */ +/* $Id: zend_language_parser.y,v 1.144.2.3 2005/06/08 06:48:38 dmitry Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -2566,13 +2566,13 @@ case 86: { zend_do_end_class_declaration(&yyvsp[-6], &yyvsp[-5] TSRMLS_CC); } break; case 87: -{ yyval.u.constant.value.lval = 0; } +{ yyval.u.opline_num = CG(zend_lineno); yyval.u.EA.type = 0; } break; case 88: -{ yyval.u.constant.value.lval = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } +{ yyval.u.opline_num = CG(zend_lineno); yyval.u.EA.type = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } break; case 89: -{ yyval.u.constant.value.lval = ZEND_ACC_FINAL_CLASS; } +{ yyval.u.opline_num = CG(zend_lineno); yyval.u.EA.type = ZEND_ACC_FINAL_CLASS; } break; case 90: { yyval.op_type = IS_UNUSED; } @@ -2581,7 +2581,7 @@ case 91: { yyval = yyvsp[0]; } break; case 92: -{ yyval.u.constant.value.lval = ZEND_ACC_INTERFACE; } +{ yyval.u.opline_num = CG(zend_lineno); yyval.u.EA.type = ZEND_ACC_INTERFACE; } break; case 97: { zend_do_implements_interface(&yyvsp[0] TSRMLS_CC); } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 56d7b21e1..f1d36a580 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_parser.y,v 1.144.2.2 2004/09/16 05:44:39 sebastian Exp $ */ +/* $Id: zend_language_parser.y,v 1.144.2.3 2005/06/08 06:48:38 dmitry Exp $ */ /* * LALR shift/reduce conflicts and how they are resolved: @@ -291,9 +291,9 @@ unticked_class_declaration_statement: class_entry_type: - T_CLASS { $$.u.constant.value.lval = 0; } - | T_ABSTRACT T_CLASS { $$.u.constant.value.lval = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } - | T_FINAL T_CLASS { $$.u.constant.value.lval = ZEND_ACC_FINAL_CLASS; } + T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = 0; } + | T_ABSTRACT T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } + | T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_FINAL_CLASS; } ; extends_from: @@ -302,7 +302,7 @@ extends_from: ; interface_entry: - T_INTERFACE { $$.u.constant.value.lval = ZEND_ACC_INTERFACE; } + T_INTERFACE { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_INTERFACE; } ; interface_extends_list: diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index 634e5e5de..f50c4b4a6 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -2780,7 +2780,7 @@ char *yytext; +----------------------------------------------------------------------+ */ -/* $Id: zend_language_scanner.l,v 1.111.2.8 2005/03/07 16:48:12 zeev Exp $ */ +/* $Id: zend_language_scanner.l,v 1.111.2.10 2005/06/09 08:54:24 dmitry Exp $ */ #define yyleng SCNG(yy_leng) #define yytext SCNG(yy_text) @@ -2892,7 +2892,8 @@ void startup_scanner(TSRMLS_D) { CG(heredoc) = NULL; CG(heredoc_len)=0; - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; SCNG(yy_start_stack_ptr) = 0; SCNG(yy_start_stack_depth) = 0; SCNG(current_buffer) = NULL; @@ -4729,6 +4730,7 @@ case 124: YY_RULE_SETUP { CG(comment_start_line) = CG(zend_lineno); + RESET_DOC_COMMENT(); BEGIN(ST_DOC_COMMENT); yymore(); } @@ -4750,7 +4752,7 @@ YY_RULE_SETUP case 127: YY_RULE_SETUP { - CG(doc_comment) = yytext; /* no copying - intentional */ + CG(doc_comment) = estrndup(yytext, yyleng); CG(doc_comment_len) = yyleng; HANDLE_NEWLINES(yytext, yyleng); BEGIN(ST_IN_SCRIPTING); diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 28f7ff079..5125e2322 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_language_scanner.l,v 1.111.2.8 2005/03/07 16:48:12 zeev Exp $ */ +/* $Id: zend_language_scanner.l,v 1.111.2.10 2005/06/09 08:54:24 dmitry Exp $ */ #define yyleng SCNG(yy_leng) #define yytext SCNG(yy_text) @@ -125,7 +125,8 @@ void startup_scanner(TSRMLS_D) { CG(heredoc) = NULL; CG(heredoc_len)=0; - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; SCNG(yy_start_stack_ptr) = 0; SCNG(yy_start_stack_depth) = 0; SCNG(current_buffer) = NULL; @@ -1464,6 +1465,7 @@ NEWLINE ("\r"|"\n"|"\r\n") <ST_IN_SCRIPTING>"/**"{WHITESPACE} { CG(comment_start_line) = CG(zend_lineno); + RESET_DOC_COMMENT(); BEGIN(ST_DOC_COMMENT); yymore(); } @@ -1480,7 +1482,7 @@ NEWLINE ("\r"|"\n"|"\r\n") } <ST_DOC_COMMENT>"*/" { - CG(doc_comment) = yytext; /* no copying - intentional */ + CG(doc_comment) = estrndup(yytext, yyleng); CG(doc_comment_len) = yyleng; HANDLE_NEWLINES(yytext, yyleng); BEGIN(ST_IN_SCRIPTING); diff --git a/Zend/zend_list.c b/Zend/zend_list.c index 809f9066e..8b12ad206 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_list.c,v 1.64 2004/02/17 22:04:05 sniper Exp $ */ +/* $Id: zend_list.c,v 1.64.2.1 2005/06/17 11:28:43 tony2001 Exp $ */ /* resource lists */ @@ -114,16 +114,20 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c void *resource; va_list resource_types; int i; - + char *space; + char *class_name; + if (default_id==-1) { /* use id */ if (!passed_id) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): no %s resource supplied", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; } else if ((*passed_id)->type != IS_RESOURCE) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): supplied argument is not a valid %s resource", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; } @@ -135,7 +139,8 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c resource = zend_list_find(id, &actual_resource_type); if (!resource) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): %d is not a valid %s resource", get_active_function_name(TSRMLS_C), id, resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), id, resource_type_name); } return NULL; } @@ -153,7 +158,8 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c va_end(resource_types); if (resource_type_name) { - zend_error(E_WARNING, "%s(): supplied resource is not a valid %s resource", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 63e910cd3..6f9af54b7 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_object_handlers.c,v 1.101.2.7 2005/03/19 15:38:19 helly Exp $ */ +/* $Id: zend_object_handlers.c,v 1.101.2.18 2005/06/20 18:25:12 dmitry Exp $ */ #include "zend.h" #include "zend_globals.h" @@ -162,13 +162,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c case ZEND_ACC_PUBLIC: return 1; case ZEND_ACC_PROTECTED: - while (ce) { - if (ce==EG(scope)) { - return 1; - } - ce = ce->parent; - } - return 0; + return zend_check_protected(ce, EG(scope));; case ZEND_ACC_PRIVATE: if (ce==EG(scope) && EG(scope)) { return 1; @@ -198,22 +192,41 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval zend_property_info *property_info = NULL; zend_property_info *scope_property_info; zend_bool denied_access = 0; - - ulong h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member)+1); - if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { - if (zend_verify_property_access(property_info, zobj->ce TSRMLS_CC)) { - if (property_info->flags & ZEND_ACC_CHANGED - && !(property_info->flags & ZEND_ACC_PRIVATE)) { - /* We still need to make sure that we're not in a context - * where the right property is a different 'statically linked' private - * continue checking below... - */ + ulong h; + + if (Z_STRVAL_P(member)[0] == '\0') { + if (!silent) { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); } else { - return property_info; + zend_error(E_ERROR, "Cannot access property started with '\\0'"); } + } + return NULL; + } + h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1); + if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { + if(property_info->flags & ZEND_ACC_SHADOW) { + /* if it's a shadow - go to access it's private */ + property_info = NULL; } else { - /* Try to look in the scope instead */ - denied_access = 1; + if (zend_verify_property_access(property_info, zobj->ce TSRMLS_CC)) { + if (property_info->flags & ZEND_ACC_CHANGED + && !(property_info->flags & ZEND_ACC_PRIVATE)) { + /* We still need to make sure that we're not in a context + * where the right property is a different 'statically linked' private + * continue checking below... + */ + } else { + if (!silent && (property_info->flags & ZEND_ACC_STATIC)) { + zend_error(E_STRICT, "Accessing static property %s::$%s as non static", zobj->ce->name, Z_STRVAL_P(member)); + } + return property_info; + } + } else { + /* Try to look in the scope instead */ + denied_access = 1; + } } } if (EG(scope) != zobj->ce @@ -221,6 +234,9 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval && EG(scope) && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS && scope_property_info->flags & ZEND_ACC_PRIVATE) { + if (!silent && (scope_property_info->flags & ZEND_ACC_STATIC)) { + zend_error(E_STRICT, "Accessing static property %s::$%s as non static", EG(scope)->name, Z_STRVAL_P(member)); + } return scope_property_info; } else if (property_info) { if (denied_access) { @@ -255,9 +271,14 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name if (!property_info) { return FAILURE; } - if (prop_info_name[0] == '\0' && prop_info_name[1] != '*' && !(property_info->flags & ZEND_ACC_PRIVATE)) { - /* we we're looking for a private prop but found a non private one of the same name */ - return FAILURE; + if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') { + if (!(property_info->flags & ZEND_ACC_PRIVATE)) { + /* we we're looking for a private prop but found a non private one of the same name */ + return FAILURE; + } else if (strcmp(prop_info_name+1, property_info->name+1)) { + /* we we're looking for a private prop but found a private one of the same name but another class */ + return FAILURE; + } } return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE; } @@ -265,7 +286,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) { zend_object *zobj; - zval tmp_member; + zval *tmp_member = NULL; zval **retval; zval *rv = NULL; zend_property_info *property_info; @@ -275,10 +296,12 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) zobj = Z_OBJ_P(object); if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; } #if DEBUG_OBJECT_HANDLERS @@ -306,8 +329,10 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) retval = &EG(uninitialized_zval_ptr); } } - if (member == &tmp_member) { - zval_dtor(member); + if (tmp_member) { + (*retval)->refcount++; + zval_ptr_dtor(&tmp_member); + (*retval)->refcount--; } return *retval; } @@ -316,7 +341,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) { zend_object *zobj; - zval tmp_member; + zval *tmp_member = NULL; zval **variable_ptr; int setter_done = 0; zend_property_info *property_info; @@ -324,10 +349,12 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM zobj = Z_OBJ_P(object); if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; } property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); @@ -371,8 +398,8 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM } zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo); } - if (member == &tmp_member) { - zval_dtor(member); + if (tmp_member) { + zval_ptr_dtor(&tmp_member); } } @@ -612,7 +639,7 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) * Returns the function address that should be called, or NULL * if no such function exists. */ -static inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_DC) +static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) { if (!ce) { return 0; @@ -647,6 +674,11 @@ static inline zend_function *zend_check_private(zend_function *fbc, zend_class_e } +ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) +{ + return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen TSRMLS_CC) != NULL; +} + /* Ensures that we're allowed to call a protected method. */ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) @@ -714,7 +746,8 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name zend_function *priv_fbc; if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS - && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE + && priv_fbc->common.scope == EG(scope)) { fbc = priv_fbc; } } @@ -723,7 +756,7 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name /* Ensure that if we're calling a private function, we're allowed to do so. */ - updated_fbc = zend_check_private(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), fbc->common.fn_flags, lc_method_name, method_len TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC); if (!updated_fbc) { zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : ""); } @@ -761,7 +794,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f /* Ensure that if we're calling a private function, we're allowed to do so. */ - updated_fbc = zend_check_private(fbc, EG(scope), fbc->common.fn_flags, function_name_strval, function_name_strlen TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC); if (!updated_fbc) { zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); } @@ -785,7 +818,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert zend_property_info *property_info; zend_property_info std_property_info; - if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) { + if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { std_property_info.flags = ZEND_ACC_PUBLIC; std_property_info.name = property_name; std_property_info.name_length = property_name_len; @@ -793,7 +826,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert property_info = &std_property_info; } -#if 1&&DEBUG_OBJECT_HANDLERS +#if DEBUG_OBJECT_HANDLERS zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags)); #endif @@ -944,6 +977,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty switch (type) { case IS_STRING: + if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) { + return FAILURE; + } ZVAL_STRING(&fname, "__tostring", 0); if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) { if (retval) { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index e111de835..417360c96 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_object_handlers.h,v 1.41.2.2 2004/11/25 20:26:48 zeev Exp $ */ +/* $Id: zend_object_handlers.h,v 1.41.2.3 2005/04/27 15:44:06 dmitry Exp $ */ #ifndef ZEND_OBJECT_HANDLERS_H #define ZEND_OBJECT_HANDLERS_H @@ -137,6 +137,8 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty #define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) #define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) +ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC); + ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 2c920b378..fb80df3c3 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_objects.c,v 1.47.2.1 2004/09/06 19:16:35 helly Exp $ */ +/* $Id: zend_objects.c,v 1.47.2.4 2005/08/04 08:46:53 dmitry Exp $ */ #include "zend.h" #include "zend_globals.h" @@ -111,9 +111,33 @@ ZEND_API zend_object *zend_objects_get_address(zval *zobject TSRMLS_DC) return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC); } +static void zval_add_ref_or_clone(zval **p) +{ + if (Z_TYPE_PP(p) == IS_OBJECT && !PZVAL_IS_REF(*p)) { + TSRMLS_FETCH(); + + if (Z_OBJ_HANDLER_PP(p, clone_obj) == NULL) { + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_PP(p)->name); + } else { + zval *orig = *p; + + ALLOC_ZVAL(*p); + **p = *orig; + INIT_PZVAL(*p); + (*p)->value.obj = Z_OBJ_HT_PP(p)->clone_obj(orig TSRMLS_CC); + } + } else { + (*p)->refcount++; + } +} + ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC) { - zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + if (EG(ze1_compatibility_mode)) { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref_or_clone, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } else { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } if (old_object->ce->clone) { zval *new_obj; zval *clone_func_name; diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 5dcb41dec..e65115fb0 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_objects_API.c,v 1.41.2.4 2005/02/22 14:54:33 helly Exp $ */ +/* $Id: zend_objects_API.c,v 1.41.2.5 2005/06/06 10:38:22 dmitry Exp $ */ #include "zend.h" #include "zend_globals.h" @@ -151,7 +151,9 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) EG(objects_store).object_buckets[handle].destructor_called = 1; if (obj->dtor) { + zobject->refcount++; obj->dtor(obj->object, handle TSRMLS_CC); + zobject->refcount--; } } if (obj->refcount == 1) { diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 57527df07..f75320a73 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_operators.c,v 1.193.2.8 2004/11/29 09:39:57 derick Exp $ */ +/* $Id: zend_operators.c,v 1.193.2.9 2005/04/08 14:36:39 helly Exp $ */ #include <ctype.h> @@ -1284,24 +1284,26 @@ static inline void zend_free_obj_get_result(zval *op, int free_op) } #define COMPARE_RETURN_AND_FREE(retval) \ - zend_free_obj_get_result(op1, free_op1); \ - zend_free_obj_get_result(op2, free_op2); \ + zend_free_obj_get_result(op1_orig, free_op1); \ + zend_free_obj_get_result(op2_orig, free_op2); \ return retval; ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; zend_bool free_op1 = 0, free_op2 = 0; + zval *op1_orig, *op2_orig; if (op1->type == IS_OBJECT && Z_OBJ_HT_P(op1)->get) { op1 = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); free_op1 = 1; } + op1_orig = op1; if (op2->type == IS_OBJECT && Z_OBJ_HT_P(op2)->get) { op2 = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); free_op2 = 1; } - + op2_orig = op2; if ((op1->type == IS_NULL && op2->type == IS_STRING) || (op2->type == IS_NULL && op1->type == IS_STRING)) { diff --git a/Zend/zend_reflection_api.c b/Zend/zend_reflection_api.c index 336bf9820..39cc7fed3 100644 --- a/Zend/zend_reflection_api.c +++ b/Zend/zend_reflection_api.c @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_reflection_api.c,v 1.111.2.19 2005/03/13 13:24:07 helly Exp $ */ +/* $Id: zend_reflection_api.c,v 1.111.2.25 2005/08/30 06:46:35 helly Exp $ */ #include "zend.h" #include "zend_API.h" #include "zend_exceptions.h" @@ -257,7 +257,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde /* {{{ _class_string */ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC) { - int count, count_static_props = 0, count_static_funcs = 0; + int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0; string sub_indent; string_init(&sub_indent); @@ -349,7 +349,9 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if(prop->flags & ZEND_ACC_SHADOW) { + count_shadow_props++; + } else if (prop->flags & ZEND_ACC_STATIC) { count_static_props++; } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -365,9 +367,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } + zend_hash_move_forward_ex(&ce->properties_info, &pos); } } @@ -415,7 +418,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in /* Default/Implicit properties */ if (&ce->properties_info) { - count = zend_hash_num_elements(&ce->properties_info) - count_static_props; + count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props; string_printf(str, "\n%s - Properties [%d] {\n", indent, count); if (count > 0) { HashPosition pos; @@ -424,7 +427,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (!(prop->flags & ZEND_ACC_STATIC)) { + if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -1332,6 +1335,7 @@ ZEND_METHOD(reflection_function, getStaticVariables) /* Return an empty array in case no static variables exist */ array_init(return_value); if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) { + zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } } @@ -1745,7 +1749,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) zv_copy = precv->op2.u.constant; zv = &zv_copy; - zval_update_constant(&zv, (void*)1 TSRMLS_CC); + zval_update_constant(&zv, (void*)0 TSRMLS_CC); RETURN_ZVAL(zv, 1, 1); } /* }}} */ @@ -2315,7 +2319,7 @@ ZEND_METHOD(reflection_class, getConstructor) /* }}} */ /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException - Returns the class' method specified by it's name */ + Returns the class' method specified by its name */ ZEND_METHOD(reflection_class, getMethod) { reflection_object *intern; @@ -2388,7 +2392,7 @@ ZEND_METHOD(reflection_class, getMethods) /* }}} */ /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException - Returns the class' property specified by it's name */ + Returns the class' property specified by its name */ ZEND_METHOD(reflection_class, getProperty) { reflection_object *intern; @@ -2403,7 +2407,7 @@ ZEND_METHOD(reflection_class, getProperty) } GET_REFLECTION_OBJECT_PTR(ce); - if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) { + if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) { reflection_property_factory(ce, property_info, return_value TSRMLS_CC); } else { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, @@ -2421,6 +2425,10 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze zval *retval = va_arg(args, zval*); long filter = va_arg(args, long); + if (pptr->flags & ZEND_ACC_SHADOW) { + return 0; + } + if (pptr->flags & filter) { TSRMLS_FETCH(); ALLOC_ZVAL(property); @@ -2519,7 +2527,7 @@ ZEND_METHOD(reflection_class, isInstantiable) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); - if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_ABSTRACT)) { + if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { RETURN_FALSE; } @@ -2904,7 +2912,7 @@ ZEND_METHOD(reflection_property, __construct) /* returns out of this function */ } - if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE) { + if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %s::$%s does not exist", ce->name, name_str); return; diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c index 28af35d76..1f358e033 100644 --- a/Zend/zend_stream.c +++ b/Zend/zend_stream.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_stream.c,v 1.8.2.1 2005/03/13 17:48:12 stas Exp $ */ +/* $Id: zend_stream.c,v 1.8.2.2 2005/07/07 15:39:35 hyanantha Exp $ */ #include "zend.h" @@ -94,7 +94,16 @@ ZEND_API size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_ if (file_handle->handle.stream.interactive) { int c = '*', n; +#ifdef NETWARE + /* + c != 4 check is there as fread of a character in NetWare LibC gives 4 upon ^D character. + Ascii value 4 is actually EOT character which is not defined anywhere in the LibC + or else we can use instead of hardcoded 4. + */ + for ( n = 0; n < len && (c = zend_stream_getc( file_handle TSRMLS_CC)) != EOF && c != 4 && c != '\n'; ++n ) +#else for ( n = 0; n < len && (c = zend_stream_getc( file_handle TSRMLS_CC)) != EOF && c != '\n'; ++n ) +#endif buf[n] = (char) c; if ( c == '\n' ) buf[n++] = (char) c; |
