summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'Zend')
-rw-r--r--Zend/Zend.m420
-rw-r--r--Zend/acconfig.h9
-rwxr-xr-xZend/tests/bug20240.phpt2
-rw-r--r--Zend/tests/bug22836.phpt8
-rwxr-xr-xZend/tests/bug27268.phpt28
-rwxr-xr-xZend/tests/bug27304.phpt23
-rwxr-xr-xZend/tests/bug27598.phpt12
-rwxr-xr-xZend/tests/bug28377.phpt23
-rw-r--r--Zend/tests/bug29015.phpt11
-rw-r--r--Zend/tests/bug29104.phpt27
-rw-r--r--Zend/tests/bug29210.phpt104
-rw-r--r--Zend/tests/bug29689.phpt62
-rw-r--r--Zend/tests/bug29890.phpt23
-rwxr-xr-xZend/tests/bug29896.phpt28
-rw-r--r--Zend/tests/bug29944.phpt16
-rwxr-xr-xZend/tests/bug30080.phpt18
-rwxr-xr-xZend/tests/bug30140.phpt30
-rwxr-xr-xZend/tests/bug30162.phpt52
-rw-r--r--Zend/tests/bug30332.phpt40
-rwxr-xr-xZend/tests/bug30394.phpt30
-rw-r--r--Zend/tests/bug30451.phpt36
-rwxr-xr-xZend/tests/bug30519.phpt10
-rw-r--r--Zend/tests/bug30702.phpt39
-rwxr-xr-xZend/tests/bug30707.phpt29
-rwxr-xr-xZend/tests/bug30791.phpt23
-rwxr-xr-xZend/tests/bug30820.phpt27
-rwxr-xr-xZend/tests/bug30828.phpt61
-rw-r--r--Zend/tests/bug30889.phpt31
-rwxr-xr-xZend/tests/bug30961.phpt20
-rwxr-xr-xZend/tests/bug31177.phpt44
-rwxr-xr-xZend/tests/bug31525.phpt22
-rw-r--r--Zend/tests/bug31828.phpt25
-rw-r--r--Zend/tests/bug32080.phpt18
-rwxr-xr-xZend/tests/bug32252.phpt47
-rwxr-xr-xZend/tests/bug32296.phpt60
-rwxr-xr-xZend/tests/bug32322.phpt80
-rwxr-xr-xZend/tests/bug32596.phpt27
-rwxr-xr-xZend/tests/bug32660.phpt36
-rw-r--r--Zend/tests/bug32674.phpt62
-rwxr-xr-xZend/tests/bug32799.phpt21
-rw-r--r--Zend/tests/bug32852.phpt38
-rwxr-xr-xZend/tests/bug32981.phpt34
-rwxr-xr-xZend/tests/bug32993.phpt29
-rwxr-xr-xZend/tests/bug33116.phpt22
-rwxr-xr-xZend/tests/bug33171.phpt27
-rwxr-xr-xZend/tests/bug33243.phpt25
-rwxr-xr-xZend/tests/bug33257.phpt17
-rw-r--r--Zend/tests/bug33277.phpt28
-rwxr-xr-xZend/tests/bug33558.phpt21
-rwxr-xr-xZend/tests/bug33802.phpt22
-rwxr-xr-xZend/tests/bug34064.phpt35
-rwxr-xr-xZend/tests/bug34137.phpt10
-rwxr-xr-xZend/tests/bug34260.phpt36
-rwxr-xr-xZend/tests/object_handlers.phpt171
-rw-r--r--Zend/zend.c37
-rw-r--r--Zend/zend.h5
-rw-r--r--Zend/zend_API.c116
-rw-r--r--Zend/zend_API.h9
-rw-r--r--Zend/zend_alloc.c6
-rw-r--r--Zend/zend_alloc.h20
-rw-r--r--Zend/zend_builtin_functions.c158
-rw-r--r--Zend/zend_compile.c203
-rw-r--r--Zend/zend_compile.h18
-rw-r--r--Zend/zend_config.w32.h3
-rw-r--r--Zend/zend_exceptions.c14
-rw-r--r--Zend/zend_execute.c427
-rw-r--r--Zend/zend_execute.h3
-rw-r--r--Zend/zend_execute_API.c102
-rw-r--r--Zend/zend_hash.c4
-rw-r--r--Zend/zend_highlight.c16
-rw-r--r--Zend/zend_ini.c20
-rw-r--r--Zend/zend_language_parser.c10
-rw-r--r--Zend/zend_language_parser.y10
-rw-r--r--Zend/zend_language_scanner.c8
-rw-r--r--Zend/zend_language_scanner.l8
-rw-r--r--Zend/zend_list.c18
-rw-r--r--Zend/zend_object_handlers.c124
-rw-r--r--Zend/zend_object_handlers.h4
-rw-r--r--Zend/zend_objects.c28
-rw-r--r--Zend/zend_objects_API.c4
-rw-r--r--Zend/zend_operators.c10
-rw-r--r--Zend/zend_reflection_api.c32
-rw-r--r--Zend/zend_stream.c11
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 &nbsp;'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;