You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2757 lines
76 KiB

8 years ago
24 years ago
24 years ago
24 years ago
26 years ago
26 years ago
23 years ago
26 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
11 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
24 years ago
23 years ago
24 years ago
24 years ago
Squashed commit of the following: commit 2d3cac9e005d6bef9aa73ab57cc674aa53125954 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:54:47 2018 +0300 Fixed static property access commit 31786ee27282f319f3ef2a07635b1f325cbd67c6 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:05:29 2018 +0300 Avoid duplicate checks commit 5ae502b979ea33d058d01a9421eec5afd0084e8d Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 10:39:17 2018 +0300 Optimization commit 82c17f0e8af02c9cf7d1bbdae4e3158330148203 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:26:50 2018 +0300 Removed unused zend_duplicate_property_info() commit ba53d1d0dd91d5530328a11cac93ff9e75c462b5 Merge: eacc11b8fd c4b14370cf Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:24:13 2018 +0300 Merge branch 'master' into shadow * master: 7.0.33 next Sync NEWS [ci skip] add NEWS for 76582 Enforce ordering of property compare in object comparisons Fixed wrong assertion Skip test on unsuitable env commit eacc11b8fdeb002ee6a149defd8b5a8c3412896a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 13:12:39 2018 +0300 Fixed failure of ext/spl/tests/array_017.phpt commit 62d1871430a1b81c84b790460afff0682648689a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 11:55:07 2018 +0300 Fixed issues commit 1d37e3a40e4d07c4b933ed6f9d2e649dd01180f0 Merge: d6c3f098b6 1e550e6f7e Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 10:21:20 2018 +0300 Merge branch 'master' into shadow * master: Update NEWS Fix for bug #76582 Fix ssl stream reneg limit test to print only after first renegotiation Make a copy unconditionally Fix memory leak in pcre cache Remove not needed checking for <errno.h> Remove HAVE_ASSERT_H Add test for bug #76850 Fixed bug #76850 Exit code mangled by set locale/preg_match Remove empty PHP tags from test Fix #75273: php_zlib_inflate_filter() may not update bytes_consumed Fix PCRE2 exclusion and remove dead libs in Makefile.gcov Report mem leaks to stderr if no Win debugger is present Use combined assignment contanation operator Fixed bug #76796 Support fixed address mmap without replacement commit d6c3f098b6015e76d042691de0af2e1426c66829 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Sep 7 13:56:30 2018 +0300 Get rid of ZEND_ACC_SHADOW
7 years ago
Squashed commit of the following: commit 2d3cac9e005d6bef9aa73ab57cc674aa53125954 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:54:47 2018 +0300 Fixed static property access commit 31786ee27282f319f3ef2a07635b1f325cbd67c6 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:05:29 2018 +0300 Avoid duplicate checks commit 5ae502b979ea33d058d01a9421eec5afd0084e8d Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 10:39:17 2018 +0300 Optimization commit 82c17f0e8af02c9cf7d1bbdae4e3158330148203 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:26:50 2018 +0300 Removed unused zend_duplicate_property_info() commit ba53d1d0dd91d5530328a11cac93ff9e75c462b5 Merge: eacc11b8fd c4b14370cf Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:24:13 2018 +0300 Merge branch 'master' into shadow * master: 7.0.33 next Sync NEWS [ci skip] add NEWS for 76582 Enforce ordering of property compare in object comparisons Fixed wrong assertion Skip test on unsuitable env commit eacc11b8fdeb002ee6a149defd8b5a8c3412896a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 13:12:39 2018 +0300 Fixed failure of ext/spl/tests/array_017.phpt commit 62d1871430a1b81c84b790460afff0682648689a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 11:55:07 2018 +0300 Fixed issues commit 1d37e3a40e4d07c4b933ed6f9d2e649dd01180f0 Merge: d6c3f098b6 1e550e6f7e Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 10:21:20 2018 +0300 Merge branch 'master' into shadow * master: Update NEWS Fix for bug #76582 Fix ssl stream reneg limit test to print only after first renegotiation Make a copy unconditionally Fix memory leak in pcre cache Remove not needed checking for <errno.h> Remove HAVE_ASSERT_H Add test for bug #76850 Fixed bug #76850 Exit code mangled by set locale/preg_match Remove empty PHP tags from test Fix #75273: php_zlib_inflate_filter() may not update bytes_consumed Fix PCRE2 exclusion and remove dead libs in Makefile.gcov Report mem leaks to stderr if no Win debugger is present Use combined assignment contanation operator Fixed bug #76796 Support fixed address mmap without replacement commit d6c3f098b6015e76d042691de0af2e1426c66829 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Sep 7 13:56:30 2018 +0300 Get rid of ZEND_ACC_SHADOW
7 years ago
12 years ago
20 years ago
22 years ago
22 years ago
11 years ago
11 years ago
24 years ago
26 years ago
Squashed commit of the following: commit 2399fc84c541da9c2176c5b7f6dd039a3c84dc64 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:38:08 2015 +0300 Removed useless assignment commit 796b6338174348eee0d74a67706d77b7ce1a60c3 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:35:31 2015 +0300 Fixed execution with overriden zend_execute_ex() commit 4a9fb125aa999059f8bc42ebb6ee573c7866b35b Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 02:02:58 2015 +0300 Fixed executor without global registers commit d456c30e00589ccda35a4b57ae903ef2d3c07d95 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 01:30:35 2015 +0300 Restored original behavior for tests/classes/__call_004.phpt commit 479646d37fef050536f1afb12b082618f1f1a3d0 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:32:17 2015 +0300 Fixed test. We don't keep stack frame for fake function anymore. commit 9ae61e33e24b2c811d4ab1ca4ab22847c64a780e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:30:09 2015 +0300 Use ZEND_ACC_CALL_VIA_TRAMPOLINE instead of ZEND_ACC_CALL_VIA_HANDLER. Keep ZEND_ACC_CALL_VIA_HANDLER for compatibility. commit 0a8403a2a0c27aa3db271774f8559739a6b8400e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:05:43 2015 +0300 Rename PROXY_CALL into CALL_TRAMPLINE. Generalize API to allow reuse EG(trampline) for other purposes. commit 4ea0525c10554e36185a0b8b6303106813b6a1c2 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 23:22:25 2015 +0300 Reuse EG(proxy_call_op) for all proxy. Move proxy related functions from zend_objects_API to zend_object_handlers. commit 529bf737ca388ad56fb4ae20ccb81e6276f25ec0 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 21:42:23 2015 +0300 Accurate use of proxy_call commit 5d62837d5ba3855743fe1981786ebd65d9da0b63 Merge: 83e749f 690843f Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:40:00 2015 +0300 Merge branch 'master' into opcodefy-call * master: Fixed GOTO executor Fixed typo Changed ArrayIterator implementation using zend_hash_iterator_... API. Allowed modification of itterated ArrayObject using the same behavior as proposed in `Fix "foreach" behavior`. Removed "Array was modified outside object and internal position is no longer valid" hack. commit 83e749ff3b6623e39b236a72e9b907d5b788ae5e Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:39:10 2015 +0300 Improved ZEND_PROXY_CALL commit 0c829afc534e6d5ff27a0dea3a4815da303bd1ef Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 15:14:49 2015 +0300 Reverted white-space changes commit df65144488afa3e9020d75e1ada5529b138afc5a Merge: 5fd2f97 97756d9 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 14:37:07 2015 +0300 Merge branch 'opcodefy-call' of github.com:laruence/php-src into opcodefy-call * 'opcodefy-call' of github.com:laruence/php-src: Ready for PR Fixed static call Improve performance by using prealloated op_arrray Respect called_scope Support internal magical __call/__callStatic opcode-fy magical __callStatic Opcode-fy magical __call commit 97756d9190e07a072a7b48135304dc25a964845f Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:07:59 2015 +0800 Ready for PR commit 74f993084627061e783645a866390b68e2981698 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:03:00 2015 +0800 Fixed static call commit ec1d9eb592db0c3b7b0e3d21e7f445ed8bccfd4d Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 18:23:17 2015 +0800 Improve performance by using prealloated op_arrray commit df7fbbf949c99f2c5ae3da2a1199235651c7cc82 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 15:10:02 2015 +0800 Respect called_scope commit 769d1d59fb48b6f7f93d7412eefbf26135fa3e59 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 12:19:23 2015 +0800 Support internal magical __call/__callStatic commit a980fedd5b0e0683713dd4f6eaad62adf4b4732f Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 18:35:41 2015 +0800 opcode-fy magical __callStatic commit 73855f7d53baa2efc2b8a88314f51c784c81b59d Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 14:21:55 2015 +0800 Opcode-fy magical __call
11 years ago
Squashed commit of the following: commit 2399fc84c541da9c2176c5b7f6dd039a3c84dc64 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:38:08 2015 +0300 Removed useless assignment commit 796b6338174348eee0d74a67706d77b7ce1a60c3 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:35:31 2015 +0300 Fixed execution with overriden zend_execute_ex() commit 4a9fb125aa999059f8bc42ebb6ee573c7866b35b Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 02:02:58 2015 +0300 Fixed executor without global registers commit d456c30e00589ccda35a4b57ae903ef2d3c07d95 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 01:30:35 2015 +0300 Restored original behavior for tests/classes/__call_004.phpt commit 479646d37fef050536f1afb12b082618f1f1a3d0 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:32:17 2015 +0300 Fixed test. We don't keep stack frame for fake function anymore. commit 9ae61e33e24b2c811d4ab1ca4ab22847c64a780e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:30:09 2015 +0300 Use ZEND_ACC_CALL_VIA_TRAMPOLINE instead of ZEND_ACC_CALL_VIA_HANDLER. Keep ZEND_ACC_CALL_VIA_HANDLER for compatibility. commit 0a8403a2a0c27aa3db271774f8559739a6b8400e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:05:43 2015 +0300 Rename PROXY_CALL into CALL_TRAMPLINE. Generalize API to allow reuse EG(trampline) for other purposes. commit 4ea0525c10554e36185a0b8b6303106813b6a1c2 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 23:22:25 2015 +0300 Reuse EG(proxy_call_op) for all proxy. Move proxy related functions from zend_objects_API to zend_object_handlers. commit 529bf737ca388ad56fb4ae20ccb81e6276f25ec0 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 21:42:23 2015 +0300 Accurate use of proxy_call commit 5d62837d5ba3855743fe1981786ebd65d9da0b63 Merge: 83e749f 690843f Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:40:00 2015 +0300 Merge branch 'master' into opcodefy-call * master: Fixed GOTO executor Fixed typo Changed ArrayIterator implementation using zend_hash_iterator_... API. Allowed modification of itterated ArrayObject using the same behavior as proposed in `Fix "foreach" behavior`. Removed "Array was modified outside object and internal position is no longer valid" hack. commit 83e749ff3b6623e39b236a72e9b907d5b788ae5e Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:39:10 2015 +0300 Improved ZEND_PROXY_CALL commit 0c829afc534e6d5ff27a0dea3a4815da303bd1ef Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 15:14:49 2015 +0300 Reverted white-space changes commit df65144488afa3e9020d75e1ada5529b138afc5a Merge: 5fd2f97 97756d9 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 14:37:07 2015 +0300 Merge branch 'opcodefy-call' of github.com:laruence/php-src into opcodefy-call * 'opcodefy-call' of github.com:laruence/php-src: Ready for PR Fixed static call Improve performance by using prealloated op_arrray Respect called_scope Support internal magical __call/__callStatic opcode-fy magical __callStatic Opcode-fy magical __call commit 97756d9190e07a072a7b48135304dc25a964845f Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:07:59 2015 +0800 Ready for PR commit 74f993084627061e783645a866390b68e2981698 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:03:00 2015 +0800 Fixed static call commit ec1d9eb592db0c3b7b0e3d21e7f445ed8bccfd4d Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 18:23:17 2015 +0800 Improve performance by using prealloated op_arrray commit df7fbbf949c99f2c5ae3da2a1199235651c7cc82 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 15:10:02 2015 +0800 Respect called_scope commit 769d1d59fb48b6f7f93d7412eefbf26135fa3e59 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 12:19:23 2015 +0800 Support internal magical __call/__callStatic commit a980fedd5b0e0683713dd4f6eaad62adf4b4732f Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 18:35:41 2015 +0800 opcode-fy magical __callStatic commit 73855f7d53baa2efc2b8a88314f51c784c81b59d Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 14:21:55 2015 +0800 Opcode-fy magical __call
11 years ago
Squashed commit of the following: commit 2d3cac9e005d6bef9aa73ab57cc674aa53125954 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:54:47 2018 +0300 Fixed static property access commit 31786ee27282f319f3ef2a07635b1f325cbd67c6 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 11:05:29 2018 +0300 Avoid duplicate checks commit 5ae502b979ea33d058d01a9421eec5afd0084e8d Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 10:39:17 2018 +0300 Optimization commit 82c17f0e8af02c9cf7d1bbdae4e3158330148203 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:26:50 2018 +0300 Removed unused zend_duplicate_property_info() commit ba53d1d0dd91d5530328a11cac93ff9e75c462b5 Merge: eacc11b8fd c4b14370cf Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Sep 11 09:24:13 2018 +0300 Merge branch 'master' into shadow * master: 7.0.33 next Sync NEWS [ci skip] add NEWS for 76582 Enforce ordering of property compare in object comparisons Fixed wrong assertion Skip test on unsuitable env commit eacc11b8fdeb002ee6a149defd8b5a8c3412896a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 13:12:39 2018 +0300 Fixed failure of ext/spl/tests/array_017.phpt commit 62d1871430a1b81c84b790460afff0682648689a Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 11:55:07 2018 +0300 Fixed issues commit 1d37e3a40e4d07c4b933ed6f9d2e649dd01180f0 Merge: d6c3f098b6 1e550e6f7e Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Sep 10 10:21:20 2018 +0300 Merge branch 'master' into shadow * master: Update NEWS Fix for bug #76582 Fix ssl stream reneg limit test to print only after first renegotiation Make a copy unconditionally Fix memory leak in pcre cache Remove not needed checking for <errno.h> Remove HAVE_ASSERT_H Add test for bug #76850 Fixed bug #76850 Exit code mangled by set locale/preg_match Remove empty PHP tags from test Fix #75273: php_zlib_inflate_filter() may not update bytes_consumed Fix PCRE2 exclusion and remove dead libs in Makefile.gcov Report mem leaks to stderr if no Win debugger is present Use combined assignment contanation operator Fixed bug #76796 Support fixed address mmap without replacement commit d6c3f098b6015e76d042691de0af2e1426c66829 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Sep 7 13:56:30 2018 +0300 Get rid of ZEND_ACC_SHADOW
7 years ago
24 years ago
24 years ago
26 years ago
18 years ago
26 years ago
26 years ago
24 years ago
26 years ago
26 years ago
26 years ago
11 years ago
23 years ago
11 years ago
24 years ago
11 years ago
11 years ago
24 years ago
26 years ago
26 years ago
24 years ago
24 years ago
11 years ago
11 years ago
11 years ago
24 years ago
12 years ago
12 years ago
24 years ago
22 years ago
11 years ago
23 years ago
23 years ago
23 years ago
23 years ago
11 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
Squashed commit of the following: commit 2399fc84c541da9c2176c5b7f6dd039a3c84dc64 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:38:08 2015 +0300 Removed useless assignment commit 796b6338174348eee0d74a67706d77b7ce1a60c3 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 12:35:31 2015 +0300 Fixed execution with overriden zend_execute_ex() commit 4a9fb125aa999059f8bc42ebb6ee573c7866b35b Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 02:02:58 2015 +0300 Fixed executor without global registers commit d456c30e00589ccda35a4b57ae903ef2d3c07d95 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 01:30:35 2015 +0300 Restored original behavior for tests/classes/__call_004.phpt commit 479646d37fef050536f1afb12b082618f1f1a3d0 Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:32:17 2015 +0300 Fixed test. We don't keep stack frame for fake function anymore. commit 9ae61e33e24b2c811d4ab1ca4ab22847c64a780e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:30:09 2015 +0300 Use ZEND_ACC_CALL_VIA_TRAMPOLINE instead of ZEND_ACC_CALL_VIA_HANDLER. Keep ZEND_ACC_CALL_VIA_HANDLER for compatibility. commit 0a8403a2a0c27aa3db271774f8559739a6b8400e Author: Dmitry Stogov <dmitry@zend.com> Date: Fri Apr 10 00:05:43 2015 +0300 Rename PROXY_CALL into CALL_TRAMPLINE. Generalize API to allow reuse EG(trampline) for other purposes. commit 4ea0525c10554e36185a0b8b6303106813b6a1c2 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 23:22:25 2015 +0300 Reuse EG(proxy_call_op) for all proxy. Move proxy related functions from zend_objects_API to zend_object_handlers. commit 529bf737ca388ad56fb4ae20ccb81e6276f25ec0 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 21:42:23 2015 +0300 Accurate use of proxy_call commit 5d62837d5ba3855743fe1981786ebd65d9da0b63 Merge: 83e749f 690843f Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:40:00 2015 +0300 Merge branch 'master' into opcodefy-call * master: Fixed GOTO executor Fixed typo Changed ArrayIterator implementation using zend_hash_iterator_... API. Allowed modification of itterated ArrayObject using the same behavior as proposed in `Fix "foreach" behavior`. Removed "Array was modified outside object and internal position is no longer valid" hack. commit 83e749ff3b6623e39b236a72e9b907d5b788ae5e Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 19:39:10 2015 +0300 Improved ZEND_PROXY_CALL commit 0c829afc534e6d5ff27a0dea3a4815da303bd1ef Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 15:14:49 2015 +0300 Reverted white-space changes commit df65144488afa3e9020d75e1ada5529b138afc5a Merge: 5fd2f97 97756d9 Author: Dmitry Stogov <dmitry@zend.com> Date: Thu Apr 9 14:37:07 2015 +0300 Merge branch 'opcodefy-call' of github.com:laruence/php-src into opcodefy-call * 'opcodefy-call' of github.com:laruence/php-src: Ready for PR Fixed static call Improve performance by using prealloated op_arrray Respect called_scope Support internal magical __call/__callStatic opcode-fy magical __callStatic Opcode-fy magical __call commit 97756d9190e07a072a7b48135304dc25a964845f Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:07:59 2015 +0800 Ready for PR commit 74f993084627061e783645a866390b68e2981698 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 19:03:00 2015 +0800 Fixed static call commit ec1d9eb592db0c3b7b0e3d21e7f445ed8bccfd4d Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 18:23:17 2015 +0800 Improve performance by using prealloated op_arrray commit df7fbbf949c99f2c5ae3da2a1199235651c7cc82 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 15:10:02 2015 +0800 Respect called_scope commit 769d1d59fb48b6f7f93d7412eefbf26135fa3e59 Author: Xinchen Hui <laruence@gmail.com> Date: Thu Apr 9 12:19:23 2015 +0800 Support internal magical __call/__callStatic commit a980fedd5b0e0683713dd4f6eaad62adf4b4732f Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 18:35:41 2015 +0800 opcode-fy magical __callStatic commit 73855f7d53baa2efc2b8a88314f51c784c81b59d Author: Xinchen Hui <laruence@gmail.com> Date: Wed Apr 8 14:21:55 2015 +0800 Opcode-fy magical __call
11 years ago
24 years ago
24 years ago
24 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #include "zend.h"
  20. #include "zend_API.h"
  21. #include "zend_gc.h"
  22. #include "zend_builtin_functions.h"
  23. #include "zend_constants.h"
  24. #include "zend_ini.h"
  25. #include "zend_exceptions.h"
  26. #include "zend_extensions.h"
  27. #include "zend_closures.h"
  28. #include "zend_generators.h"
  29. static ZEND_FUNCTION(zend_version);
  30. static ZEND_FUNCTION(func_num_args);
  31. static ZEND_FUNCTION(func_get_arg);
  32. static ZEND_FUNCTION(func_get_args);
  33. static ZEND_FUNCTION(strlen);
  34. static ZEND_FUNCTION(strcmp);
  35. static ZEND_FUNCTION(strncmp);
  36. static ZEND_FUNCTION(strcasecmp);
  37. static ZEND_FUNCTION(strncasecmp);
  38. static ZEND_FUNCTION(each);
  39. static ZEND_FUNCTION(error_reporting);
  40. static ZEND_FUNCTION(define);
  41. static ZEND_FUNCTION(defined);
  42. static ZEND_FUNCTION(get_class);
  43. static ZEND_FUNCTION(get_called_class);
  44. static ZEND_FUNCTION(get_parent_class);
  45. static ZEND_FUNCTION(method_exists);
  46. static ZEND_FUNCTION(property_exists);
  47. static ZEND_FUNCTION(class_exists);
  48. static ZEND_FUNCTION(interface_exists);
  49. static ZEND_FUNCTION(trait_exists);
  50. static ZEND_FUNCTION(function_exists);
  51. static ZEND_FUNCTION(class_alias);
  52. static ZEND_FUNCTION(get_included_files);
  53. static ZEND_FUNCTION(is_subclass_of);
  54. static ZEND_FUNCTION(is_a);
  55. static ZEND_FUNCTION(get_class_vars);
  56. static ZEND_FUNCTION(get_object_vars);
  57. static ZEND_FUNCTION(get_class_methods);
  58. static ZEND_FUNCTION(trigger_error);
  59. static ZEND_FUNCTION(set_error_handler);
  60. static ZEND_FUNCTION(restore_error_handler);
  61. static ZEND_FUNCTION(set_exception_handler);
  62. static ZEND_FUNCTION(restore_exception_handler);
  63. static ZEND_FUNCTION(get_declared_classes);
  64. static ZEND_FUNCTION(get_declared_traits);
  65. static ZEND_FUNCTION(get_declared_interfaces);
  66. static ZEND_FUNCTION(get_defined_functions);
  67. static ZEND_FUNCTION(get_defined_vars);
  68. static ZEND_FUNCTION(create_function);
  69. static ZEND_FUNCTION(get_resource_type);
  70. static ZEND_FUNCTION(get_resources);
  71. static ZEND_FUNCTION(get_loaded_extensions);
  72. static ZEND_FUNCTION(extension_loaded);
  73. static ZEND_FUNCTION(get_extension_funcs);
  74. static ZEND_FUNCTION(get_defined_constants);
  75. static ZEND_FUNCTION(debug_backtrace);
  76. static ZEND_FUNCTION(debug_print_backtrace);
  77. #if ZEND_DEBUG && defined(ZTS)
  78. static ZEND_FUNCTION(zend_thread_id);
  79. #endif
  80. static ZEND_FUNCTION(gc_mem_caches);
  81. static ZEND_FUNCTION(gc_collect_cycles);
  82. static ZEND_FUNCTION(gc_enabled);
  83. static ZEND_FUNCTION(gc_enable);
  84. static ZEND_FUNCTION(gc_disable);
  85. static ZEND_FUNCTION(gc_status);
  86. /* {{{ arginfo */
  87. ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
  88. ZEND_END_ARG_INFO()
  89. ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1)
  90. ZEND_ARG_INFO(0, arg_num)
  91. ZEND_END_ARG_INFO()
  92. ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1)
  93. ZEND_ARG_INFO(0, str)
  94. ZEND_END_ARG_INFO()
  95. ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2)
  96. ZEND_ARG_INFO(0, str1)
  97. ZEND_ARG_INFO(0, str2)
  98. ZEND_END_ARG_INFO()
  99. ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3)
  100. ZEND_ARG_INFO(0, str1)
  101. ZEND_ARG_INFO(0, str2)
  102. ZEND_ARG_INFO(0, len)
  103. ZEND_END_ARG_INFO()
  104. ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1)
  105. ZEND_ARG_INFO(1, arr)
  106. ZEND_END_ARG_INFO()
  107. ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0)
  108. ZEND_ARG_INFO(0, new_error_level)
  109. ZEND_END_ARG_INFO()
  110. ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 2)
  111. ZEND_ARG_INFO(0, constant_name)
  112. ZEND_ARG_INFO(0, value)
  113. ZEND_ARG_INFO(0, case_insensitive)
  114. ZEND_END_ARG_INFO()
  115. ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1)
  116. ZEND_ARG_INFO(0, constant_name)
  117. ZEND_END_ARG_INFO()
  118. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0)
  119. ZEND_ARG_INFO(0, object)
  120. ZEND_END_ARG_INFO()
  121. ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
  122. ZEND_ARG_INFO(0, object)
  123. ZEND_ARG_INFO(0, class_name)
  124. ZEND_ARG_INFO(0, allow_string)
  125. ZEND_END_ARG_INFO()
  126. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
  127. ZEND_ARG_INFO(0, class_name)
  128. ZEND_END_ARG_INFO()
  129. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
  130. ZEND_ARG_INFO(0, obj)
  131. ZEND_END_ARG_INFO()
  132. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
  133. ZEND_ARG_INFO(0, class)
  134. ZEND_END_ARG_INFO()
  135. ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2)
  136. ZEND_ARG_INFO(0, object)
  137. ZEND_ARG_INFO(0, method)
  138. ZEND_END_ARG_INFO()
  139. ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2)
  140. ZEND_ARG_INFO(0, object_or_class)
  141. ZEND_ARG_INFO(0, property_name)
  142. ZEND_END_ARG_INFO()
  143. ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
  144. ZEND_ARG_INFO(0, classname)
  145. ZEND_ARG_INFO(0, autoload)
  146. ZEND_END_ARG_INFO()
  147. ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1)
  148. ZEND_ARG_INFO(0, traitname)
  149. ZEND_ARG_INFO(0, autoload)
  150. ZEND_END_ARG_INFO()
  151. ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
  152. ZEND_ARG_INFO(0, function_name)
  153. ZEND_END_ARG_INFO()
  154. ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
  155. ZEND_ARG_INFO(0, user_class_name)
  156. ZEND_ARG_INFO(0, alias_name)
  157. ZEND_ARG_INFO(0, autoload)
  158. ZEND_END_ARG_INFO()
  159. ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
  160. ZEND_ARG_INFO(0, message)
  161. ZEND_ARG_INFO(0, error_type)
  162. ZEND_END_ARG_INFO()
  163. ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1)
  164. ZEND_ARG_INFO(0, error_handler)
  165. ZEND_ARG_INFO(0, error_types)
  166. ZEND_END_ARG_INFO()
  167. ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
  168. ZEND_ARG_INFO(0, exception_handler)
  169. ZEND_END_ARG_INFO()
  170. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0)
  171. ZEND_ARG_INFO(0, exclude_disabled)
  172. ZEND_END_ARG_INFO()
  173. ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2)
  174. ZEND_ARG_INFO(0, args)
  175. ZEND_ARG_INFO(0, code)
  176. ZEND_END_ARG_INFO()
  177. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
  178. ZEND_ARG_INFO(0, res)
  179. ZEND_END_ARG_INFO()
  180. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0)
  181. ZEND_ARG_INFO(0, type)
  182. ZEND_END_ARG_INFO()
  183. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
  184. ZEND_ARG_INFO(0, zend_extensions)
  185. ZEND_END_ARG_INFO()
  186. ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
  187. ZEND_ARG_INFO(0, categorize)
  188. ZEND_END_ARG_INFO()
  189. ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
  190. ZEND_ARG_INFO(0, options)
  191. ZEND_ARG_INFO(0, limit)
  192. ZEND_END_ARG_INFO()
  193. ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0)
  194. ZEND_ARG_INFO(0, options)
  195. ZEND_ARG_INFO(0, limit)
  196. ZEND_END_ARG_INFO()
  197. ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
  198. ZEND_ARG_INFO(0, extension_name)
  199. ZEND_END_ARG_INFO()
  200. /* }}} */
  201. static const zend_function_entry builtin_functions[] = { /* {{{ */
  202. ZEND_FE(zend_version, arginfo_zend__void)
  203. ZEND_FE(func_num_args, arginfo_zend__void)
  204. ZEND_FE(func_get_arg, arginfo_func_get_arg)
  205. ZEND_FE(func_get_args, arginfo_zend__void)
  206. ZEND_FE(strlen, arginfo_strlen)
  207. ZEND_FE(strcmp, arginfo_strcmp)
  208. ZEND_FE(strncmp, arginfo_strncmp)
  209. ZEND_FE(strcasecmp, arginfo_strcmp)
  210. ZEND_FE(strncasecmp, arginfo_strncmp)
  211. ZEND_FE(each, arginfo_each)
  212. ZEND_FE(error_reporting, arginfo_error_reporting)
  213. ZEND_FE(define, arginfo_define)
  214. ZEND_FE(defined, arginfo_defined)
  215. ZEND_FE(get_class, arginfo_get_class)
  216. ZEND_FE(get_called_class, arginfo_zend__void)
  217. ZEND_FE(get_parent_class, arginfo_get_class)
  218. ZEND_FE(method_exists, arginfo_method_exists)
  219. ZEND_FE(property_exists, arginfo_property_exists)
  220. ZEND_FE(class_exists, arginfo_class_exists)
  221. ZEND_FE(interface_exists, arginfo_class_exists)
  222. ZEND_FE(trait_exists, arginfo_trait_exists)
  223. ZEND_FE(function_exists, arginfo_function_exists)
  224. ZEND_FE(class_alias, arginfo_class_alias)
  225. ZEND_FE(get_included_files, arginfo_zend__void)
  226. ZEND_FALIAS(get_required_files, get_included_files, arginfo_zend__void)
  227. ZEND_FE(is_subclass_of, arginfo_is_subclass_of)
  228. ZEND_FE(is_a, arginfo_is_subclass_of)
  229. ZEND_FE(get_class_vars, arginfo_get_class_vars)
  230. ZEND_FE(get_object_vars, arginfo_get_object_vars)
  231. ZEND_FE(get_class_methods, arginfo_get_class_methods)
  232. ZEND_FE(trigger_error, arginfo_trigger_error)
  233. ZEND_FALIAS(user_error, trigger_error, arginfo_trigger_error)
  234. ZEND_FE(set_error_handler, arginfo_set_error_handler)
  235. ZEND_FE(restore_error_handler, arginfo_zend__void)
  236. ZEND_FE(set_exception_handler, arginfo_set_exception_handler)
  237. ZEND_FE(restore_exception_handler, arginfo_zend__void)
  238. ZEND_FE(get_declared_classes, arginfo_zend__void)
  239. ZEND_FE(get_declared_traits, arginfo_zend__void)
  240. ZEND_FE(get_declared_interfaces, arginfo_zend__void)
  241. ZEND_FE(get_defined_functions, arginfo_get_defined_functions)
  242. ZEND_FE(get_defined_vars, arginfo_zend__void)
  243. ZEND_DEP_FE(create_function, arginfo_create_function)
  244. ZEND_FE(get_resource_type, arginfo_get_resource_type)
  245. ZEND_FE(get_resources, arginfo_get_resources)
  246. ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions)
  247. ZEND_FE(extension_loaded, arginfo_extension_loaded)
  248. ZEND_FE(get_extension_funcs, arginfo_extension_loaded)
  249. ZEND_FE(get_defined_constants, arginfo_get_defined_constants)
  250. ZEND_FE(debug_backtrace, arginfo_debug_backtrace)
  251. ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace)
  252. #if ZEND_DEBUG && defined(ZTS)
  253. ZEND_FE(zend_thread_id, NULL)
  254. #endif
  255. ZEND_FE(gc_mem_caches, arginfo_zend__void)
  256. ZEND_FE(gc_collect_cycles, arginfo_zend__void)
  257. ZEND_FE(gc_enabled, arginfo_zend__void)
  258. ZEND_FE(gc_enable, arginfo_zend__void)
  259. ZEND_FE(gc_disable, arginfo_zend__void)
  260. ZEND_FE(gc_status, arginfo_zend__void)
  261. ZEND_FE_END
  262. };
  263. /* }}} */
  264. ZEND_MINIT_FUNCTION(core) { /* {{{ */
  265. zend_class_entry class_entry;
  266. INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
  267. zend_standard_class_def = zend_register_internal_class(&class_entry);
  268. zend_register_default_classes();
  269. return SUCCESS;
  270. }
  271. /* }}} */
  272. zend_module_entry zend_builtin_module = { /* {{{ */
  273. STANDARD_MODULE_HEADER,
  274. "Core",
  275. builtin_functions,
  276. ZEND_MINIT(core),
  277. NULL,
  278. NULL,
  279. NULL,
  280. NULL,
  281. ZEND_VERSION,
  282. STANDARD_MODULE_PROPERTIES
  283. };
  284. /* }}} */
  285. int zend_startup_builtin_functions(void) /* {{{ */
  286. {
  287. zend_builtin_module.module_number = 0;
  288. zend_builtin_module.type = MODULE_PERSISTENT;
  289. return (EG(current_module) = zend_register_module_ex(&zend_builtin_module)) == NULL ? FAILURE : SUCCESS;
  290. }
  291. /* }}} */
  292. /* {{{ proto string zend_version(void)
  293. Get the version of the Zend Engine */
  294. ZEND_FUNCTION(zend_version)
  295. {
  296. if (zend_parse_parameters_none() == FAILURE) {
  297. return;
  298. }
  299. RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
  300. }
  301. /* }}} */
  302. /* {{{ proto int gc_mem_caches(void)
  303. Reclaims memory used by MM caches.
  304. Returns number of freed bytes */
  305. ZEND_FUNCTION(gc_mem_caches)
  306. {
  307. if (zend_parse_parameters_none() == FAILURE) {
  308. return;
  309. }
  310. RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
  311. }
  312. /* }}} */
  313. /* {{{ proto int gc_collect_cycles(void)
  314. Forces collection of any existing garbage cycles.
  315. Returns number of freed zvals */
  316. ZEND_FUNCTION(gc_collect_cycles)
  317. {
  318. if (zend_parse_parameters_none() == FAILURE) {
  319. return;
  320. }
  321. RETURN_LONG(gc_collect_cycles());
  322. }
  323. /* }}} */
  324. /* {{{ proto void gc_enabled(void)
  325. Returns status of the circular reference collector */
  326. ZEND_FUNCTION(gc_enabled)
  327. {
  328. if (zend_parse_parameters_none() == FAILURE) {
  329. return;
  330. }
  331. RETURN_BOOL(gc_enabled());
  332. }
  333. /* }}} */
  334. /* {{{ proto void gc_enable(void)
  335. Activates the circular reference collector */
  336. ZEND_FUNCTION(gc_enable)
  337. {
  338. zend_string *key;
  339. if (zend_parse_parameters_none() == FAILURE) {
  340. return;
  341. }
  342. key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
  343. zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  344. zend_string_release_ex(key, 0);
  345. }
  346. /* }}} */
  347. /* {{{ proto void gc_disable(void)
  348. Deactivates the circular reference collector */
  349. ZEND_FUNCTION(gc_disable)
  350. {
  351. zend_string *key;
  352. if (zend_parse_parameters_none() == FAILURE) {
  353. return;
  354. }
  355. key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
  356. zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  357. zend_string_release_ex(key, 0);
  358. }
  359. /* }}} */
  360. /* {{{ proto array gc_status(void)
  361. Returns current GC statistics */
  362. ZEND_FUNCTION(gc_status)
  363. {
  364. zend_gc_status status;
  365. if (zend_parse_parameters_none() == FAILURE) {
  366. return;
  367. }
  368. zend_gc_get_status(&status);
  369. array_init_size(return_value, 3);
  370. add_assoc_long_ex(return_value, "runs", sizeof("runs")-1, (long)status.runs);
  371. add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);
  372. add_assoc_long_ex(return_value, "threshold", sizeof("threshold")-1, (long)status.threshold);
  373. add_assoc_long_ex(return_value, "roots", sizeof("roots")-1, (long)status.num_roots);
  374. }
  375. /* }}} */
  376. /* {{{ proto int func_num_args(void)
  377. Get the number of arguments that were passed to the function */
  378. ZEND_FUNCTION(func_num_args)
  379. {
  380. zend_execute_data *ex = EX(prev_execute_data);
  381. if (zend_parse_parameters_none() == FAILURE) {
  382. return;
  383. }
  384. if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
  385. zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
  386. RETURN_LONG(-1);
  387. }
  388. if (zend_forbid_dynamic_call("func_num_args()") == FAILURE) {
  389. RETURN_LONG(-1);
  390. }
  391. RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
  392. }
  393. /* }}} */
  394. /* {{{ proto mixed func_get_arg(int arg_num)
  395. Get the $arg_num'th argument that was passed to the function */
  396. ZEND_FUNCTION(func_get_arg)
  397. {
  398. uint32_t arg_count, first_extra_arg;
  399. zval *arg;
  400. zend_long requested_offset;
  401. zend_execute_data *ex;
  402. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
  403. return;
  404. }
  405. if (requested_offset < 0) {
  406. zend_error(E_WARNING, "func_get_arg(): The argument number should be >= 0");
  407. RETURN_FALSE;
  408. }
  409. ex = EX(prev_execute_data);
  410. if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
  411. zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
  412. RETURN_FALSE;
  413. }
  414. if (zend_forbid_dynamic_call("func_get_arg()") == FAILURE) {
  415. RETURN_FALSE;
  416. }
  417. arg_count = ZEND_CALL_NUM_ARGS(ex);
  418. if ((zend_ulong)requested_offset >= arg_count) {
  419. zend_error(E_WARNING, "func_get_arg(): Argument " ZEND_LONG_FMT " not passed to function", requested_offset);
  420. RETURN_FALSE;
  421. }
  422. first_extra_arg = ex->func->op_array.num_args;
  423. if ((zend_ulong)requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
  424. arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
  425. } else {
  426. arg = ZEND_CALL_ARG(ex, requested_offset + 1);
  427. }
  428. if (EXPECTED(!Z_ISUNDEF_P(arg))) {
  429. ZVAL_COPY_DEREF(return_value, arg);
  430. }
  431. }
  432. /* }}} */
  433. /* {{{ proto array func_get_args()
  434. Get an array of the arguments that were passed to the function */
  435. ZEND_FUNCTION(func_get_args)
  436. {
  437. zval *p, *q;
  438. uint32_t arg_count, first_extra_arg;
  439. uint32_t i;
  440. zend_execute_data *ex = EX(prev_execute_data);
  441. if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
  442. zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
  443. RETURN_FALSE;
  444. }
  445. if (zend_forbid_dynamic_call("func_get_args()") == FAILURE) {
  446. RETURN_FALSE;
  447. }
  448. arg_count = ZEND_CALL_NUM_ARGS(ex);
  449. if (arg_count) {
  450. array_init_size(return_value, arg_count);
  451. first_extra_arg = ex->func->op_array.num_args;
  452. zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
  453. ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
  454. i = 0;
  455. p = ZEND_CALL_ARG(ex, 1);
  456. if (arg_count > first_extra_arg) {
  457. while (i < first_extra_arg) {
  458. q = p;
  459. if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
  460. ZVAL_DEREF(q);
  461. if (Z_OPT_REFCOUNTED_P(q)) {
  462. Z_ADDREF_P(q);
  463. }
  464. } else {
  465. q = &EG(uninitialized_zval);
  466. }
  467. ZEND_HASH_FILL_ADD(q);
  468. p++;
  469. i++;
  470. }
  471. p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
  472. }
  473. while (i < arg_count) {
  474. q = p;
  475. if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
  476. ZVAL_DEREF(q);
  477. if (Z_OPT_REFCOUNTED_P(q)) {
  478. Z_ADDREF_P(q);
  479. }
  480. } else {
  481. q = &EG(uninitialized_zval);
  482. }
  483. ZEND_HASH_FILL_ADD(q);
  484. p++;
  485. i++;
  486. }
  487. } ZEND_HASH_FILL_END();
  488. Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
  489. } else {
  490. ZVAL_EMPTY_ARRAY(return_value);
  491. }
  492. }
  493. /* }}} */
  494. /* {{{ proto int strlen(string str)
  495. Get string length
  496. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  497. ZEND_FUNCTION(strlen)
  498. {
  499. zend_string *s;
  500. ZEND_PARSE_PARAMETERS_START(1, 1)
  501. Z_PARAM_STR(s)
  502. ZEND_PARSE_PARAMETERS_END();
  503. RETVAL_LONG(ZSTR_LEN(s));
  504. }
  505. /* }}} */
  506. /* {{{ proto int strcmp(string str1, string str2)
  507. Binary safe string comparison */
  508. ZEND_FUNCTION(strcmp)
  509. {
  510. zend_string *s1, *s2;
  511. ZEND_PARSE_PARAMETERS_START(2, 2)
  512. Z_PARAM_STR(s1)
  513. Z_PARAM_STR(s2)
  514. ZEND_PARSE_PARAMETERS_END();
  515. RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
  516. }
  517. /* }}} */
  518. /* {{{ proto int strncmp(string str1, string str2, int len)
  519. Binary safe string comparison */
  520. ZEND_FUNCTION(strncmp)
  521. {
  522. zend_string *s1, *s2;
  523. zend_long len;
  524. ZEND_PARSE_PARAMETERS_START(3, 3)
  525. Z_PARAM_STR(s1)
  526. Z_PARAM_STR(s2)
  527. Z_PARAM_LONG(len)
  528. ZEND_PARSE_PARAMETERS_END();
  529. if (len < 0) {
  530. zend_error(E_WARNING, "Length must be greater than or equal to 0");
  531. RETURN_FALSE;
  532. }
  533. RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
  534. }
  535. /* }}} */
  536. /* {{{ proto int strcasecmp(string str1, string str2)
  537. Binary safe case-insensitive string comparison */
  538. ZEND_FUNCTION(strcasecmp)
  539. {
  540. zend_string *s1, *s2;
  541. ZEND_PARSE_PARAMETERS_START(2, 2)
  542. Z_PARAM_STR(s1)
  543. Z_PARAM_STR(s2)
  544. ZEND_PARSE_PARAMETERS_END();
  545. RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
  546. }
  547. /* }}} */
  548. /* {{{ proto int strncasecmp(string str1, string str2, int len)
  549. Binary safe string comparison */
  550. ZEND_FUNCTION(strncasecmp)
  551. {
  552. zend_string *s1, *s2;
  553. zend_long len;
  554. ZEND_PARSE_PARAMETERS_START(3, 3)
  555. Z_PARAM_STR(s1)
  556. Z_PARAM_STR(s2)
  557. Z_PARAM_LONG(len)
  558. ZEND_PARSE_PARAMETERS_END();
  559. if (len < 0) {
  560. zend_error(E_WARNING, "Length must be greater than or equal to 0");
  561. RETURN_FALSE;
  562. }
  563. RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
  564. }
  565. /* }}} */
  566. /* {{{ proto mixed each(array &arr)
  567. Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */
  568. ZEND_FUNCTION(each)
  569. {
  570. zval *array, *entry, tmp;
  571. zend_ulong num_key;
  572. HashTable *target_hash;
  573. zend_string *key;
  574. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) {
  575. return;
  576. }
  577. if (!EG(each_deprecation_thrown)) {
  578. zend_error(E_DEPRECATED, "The each() function is deprecated. This message will be suppressed on further calls");
  579. EG(each_deprecation_thrown) = 1;
  580. }
  581. target_hash = HASH_OF(array);
  582. if (!target_hash) {
  583. zend_error(E_WARNING,"Variable passed to each() is not an array or object");
  584. return;
  585. }
  586. while (1) {
  587. entry = zend_hash_get_current_data(target_hash);
  588. if (!entry) {
  589. RETURN_FALSE;
  590. } else if (Z_TYPE_P(entry) == IS_INDIRECT) {
  591. entry = Z_INDIRECT_P(entry);
  592. if (Z_TYPE_P(entry) == IS_UNDEF) {
  593. zend_hash_move_forward(target_hash);
  594. continue;
  595. }
  596. }
  597. break;
  598. }
  599. array_init_size(return_value, 4);
  600. zend_hash_real_init_mixed(Z_ARRVAL_P(return_value));
  601. /* add value elements */
  602. ZVAL_DEREF(entry);
  603. if (Z_REFCOUNTED_P(entry)) {
  604. GC_ADDREF_EX(Z_COUNTED_P(entry), 2);
  605. }
  606. zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry);
  607. zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_VALUE), entry);
  608. /* add the key elements */
  609. if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) {
  610. ZVAL_STR_COPY(&tmp, key);
  611. Z_TRY_ADDREF(tmp);
  612. } else {
  613. ZVAL_LONG(&tmp, num_key);
  614. }
  615. zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
  616. zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_KEY), &tmp);
  617. zend_hash_move_forward(target_hash);
  618. }
  619. /* }}} */
  620. /* {{{ proto int error_reporting([int new_error_level])
  621. Return the current error_reporting level, and if an argument was passed - change to the new level */
  622. ZEND_FUNCTION(error_reporting)
  623. {
  624. zval *err = NULL;
  625. int old_error_reporting;
  626. ZEND_PARSE_PARAMETERS_START(0, 1)
  627. Z_PARAM_OPTIONAL
  628. Z_PARAM_ZVAL(err)
  629. ZEND_PARSE_PARAMETERS_END();
  630. old_error_reporting = EG(error_reporting);
  631. if (ZEND_NUM_ARGS() != 0) {
  632. zend_string *new_val = zval_get_string(err);
  633. do {
  634. zend_ini_entry *p = EG(error_reporting_ini_entry);
  635. if (!p) {
  636. zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1);
  637. if (zv) {
  638. p = EG(error_reporting_ini_entry) = (zend_ini_entry*)Z_PTR_P(zv);
  639. } else {
  640. break;
  641. }
  642. }
  643. if (!p->modified) {
  644. if (!EG(modified_ini_directives)) {
  645. ALLOC_HASHTABLE(EG(modified_ini_directives));
  646. zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
  647. }
  648. if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) {
  649. p->orig_value = p->value;
  650. p->orig_modifiable = p->modifiable;
  651. p->modified = 1;
  652. }
  653. } else if (p->orig_value != p->value) {
  654. zend_string_release_ex(p->value, 0);
  655. }
  656. p->value = new_val;
  657. if (Z_TYPE_P(err) == IS_LONG) {
  658. EG(error_reporting) = Z_LVAL_P(err);
  659. } else {
  660. EG(error_reporting) = atoi(ZSTR_VAL(p->value));
  661. }
  662. } while (0);
  663. }
  664. RETVAL_LONG(old_error_reporting);
  665. }
  666. /* }}} */
  667. static int validate_constant_array(HashTable *ht) /* {{{ */
  668. {
  669. int ret = 1;
  670. zval *val;
  671. GC_PROTECT_RECURSION(ht);
  672. ZEND_HASH_FOREACH_VAL_IND(ht, val) {
  673. ZVAL_DEREF(val);
  674. if (Z_REFCOUNTED_P(val)) {
  675. if (Z_TYPE_P(val) == IS_ARRAY) {
  676. if (Z_REFCOUNTED_P(val)) {
  677. if (Z_IS_RECURSIVE_P(val)) {
  678. zend_error(E_WARNING, "Constants cannot be recursive arrays");
  679. ret = 0;
  680. break;
  681. } else if (!validate_constant_array(Z_ARRVAL_P(val))) {
  682. ret = 0;
  683. break;
  684. }
  685. }
  686. } else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
  687. zend_error(E_WARNING, "Constants may only evaluate to scalar values, arrays or resources");
  688. ret = 0;
  689. break;
  690. }
  691. }
  692. } ZEND_HASH_FOREACH_END();
  693. GC_UNPROTECT_RECURSION(ht);
  694. return ret;
  695. }
  696. /* }}} */
  697. static void copy_constant_array(zval *dst, zval *src) /* {{{ */
  698. {
  699. zend_string *key;
  700. zend_ulong idx;
  701. zval *new_val, *val;
  702. array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
  703. ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(src), idx, key, val) {
  704. /* constant arrays can't contain references */
  705. ZVAL_DEREF(val);
  706. if (key) {
  707. new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
  708. } else {
  709. new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
  710. }
  711. if (Z_TYPE_P(val) == IS_ARRAY) {
  712. if (Z_REFCOUNTED_P(val)) {
  713. copy_constant_array(new_val, val);
  714. }
  715. } else {
  716. Z_TRY_ADDREF_P(val);
  717. }
  718. } ZEND_HASH_FOREACH_END();
  719. }
  720. /* }}} */
  721. /* {{{ proto bool define(string constant_name, mixed value[, bool case_insensitive])
  722. Define a new constant */
  723. ZEND_FUNCTION(define)
  724. {
  725. zend_string *name;
  726. zval *val, val_free;
  727. zend_bool non_cs = 0;
  728. int case_sensitive = CONST_CS;
  729. zend_constant c;
  730. ZEND_PARSE_PARAMETERS_START(2, 3)
  731. Z_PARAM_STR(name)
  732. Z_PARAM_ZVAL(val)
  733. Z_PARAM_OPTIONAL
  734. Z_PARAM_BOOL(non_cs)
  735. ZEND_PARSE_PARAMETERS_END();
  736. if (non_cs) {
  737. case_sensitive = 0;
  738. }
  739. if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
  740. zend_error(E_WARNING, "Class constants cannot be defined or redefined");
  741. RETURN_FALSE;
  742. }
  743. ZVAL_UNDEF(&val_free);
  744. repeat:
  745. switch (Z_TYPE_P(val)) {
  746. case IS_LONG:
  747. case IS_DOUBLE:
  748. case IS_STRING:
  749. case IS_FALSE:
  750. case IS_TRUE:
  751. case IS_NULL:
  752. case IS_RESOURCE:
  753. break;
  754. case IS_ARRAY:
  755. if (Z_REFCOUNTED_P(val)) {
  756. if (!validate_constant_array(Z_ARRVAL_P(val))) {
  757. RETURN_FALSE;
  758. } else {
  759. copy_constant_array(&c.value, val);
  760. goto register_constant;
  761. }
  762. }
  763. break;
  764. case IS_OBJECT:
  765. if (Z_TYPE(val_free) == IS_UNDEF) {
  766. if (Z_OBJ_HT_P(val)->get) {
  767. zval rv;
  768. val = Z_OBJ_HT_P(val)->get(val, &rv);
  769. ZVAL_COPY_VALUE(&val_free, val);
  770. goto repeat;
  771. } else if (Z_OBJ_HT_P(val)->cast_object) {
  772. if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) {
  773. val = &val_free;
  774. break;
  775. }
  776. }
  777. }
  778. /* no break */
  779. default:
  780. zend_error(E_WARNING, "Constants may only evaluate to scalar values, arrays or resources");
  781. zval_ptr_dtor(&val_free);
  782. RETURN_FALSE;
  783. }
  784. ZVAL_COPY(&c.value, val);
  785. zval_ptr_dtor(&val_free);
  786. register_constant:
  787. if (non_cs) {
  788. zend_error(E_DEPRECATED,
  789. "define(): Declaration of case-insensitive constants is deprecated");
  790. }
  791. /* non persistent */
  792. ZEND_CONSTANT_SET_FLAGS(&c, case_sensitive, PHP_USER_CONSTANT);
  793. c.name = zend_string_copy(name);
  794. if (zend_register_constant(&c) == SUCCESS) {
  795. RETURN_TRUE;
  796. } else {
  797. RETURN_FALSE;
  798. }
  799. }
  800. /* }}} */
  801. /* {{{ proto bool defined(string constant_name)
  802. Check whether a constant exists
  803. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  804. ZEND_FUNCTION(defined)
  805. {
  806. zend_string *name;
  807. ZEND_PARSE_PARAMETERS_START(1, 1)
  808. Z_PARAM_STR(name)
  809. ZEND_PARSE_PARAMETERS_END();
  810. if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT | ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) {
  811. RETURN_TRUE;
  812. } else {
  813. RETURN_FALSE;
  814. }
  815. }
  816. /* }}} */
  817. /* {{{ proto string get_class([object object])
  818. Retrieves the class name */
  819. ZEND_FUNCTION(get_class)
  820. {
  821. zval *obj = NULL;
  822. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) {
  823. RETURN_FALSE;
  824. }
  825. if (!obj) {
  826. zend_class_entry *scope = zend_get_executed_scope();
  827. if (scope) {
  828. RETURN_STR_COPY(scope->name);
  829. } else {
  830. zend_error(E_WARNING, "get_class() called without object from outside a class");
  831. RETURN_FALSE;
  832. }
  833. }
  834. RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
  835. }
  836. /* }}} */
  837. /* {{{ proto string get_called_class()
  838. Retrieves the "Late Static Binding" class name */
  839. ZEND_FUNCTION(get_called_class)
  840. {
  841. zend_class_entry *called_scope;
  842. if (zend_parse_parameters_none() == FAILURE) {
  843. return;
  844. }
  845. called_scope = zend_get_called_scope(execute_data);
  846. if (called_scope) {
  847. RETURN_STR_COPY(called_scope->name);
  848. } else {
  849. zend_class_entry *scope = zend_get_executed_scope();
  850. if (!scope) {
  851. zend_error(E_WARNING, "get_called_class() called from outside a class");
  852. }
  853. }
  854. RETURN_FALSE;
  855. }
  856. /* }}} */
  857. /* {{{ proto mixed get_parent_class([mixed object])
  858. Retrieves the parent class name for object or class or current scope or false if not in a scope. */
  859. ZEND_FUNCTION(get_parent_class)
  860. {
  861. zval *arg;
  862. zend_class_entry *ce = NULL;
  863. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
  864. return;
  865. }
  866. if (!ZEND_NUM_ARGS()) {
  867. ce = zend_get_executed_scope();
  868. if (ce && ce->parent) {
  869. RETURN_STR_COPY(ce->parent->name);
  870. } else {
  871. RETURN_FALSE;
  872. }
  873. }
  874. if (Z_TYPE_P(arg) == IS_OBJECT) {
  875. ce = Z_OBJ_P(arg)->ce;
  876. } else if (Z_TYPE_P(arg) == IS_STRING) {
  877. ce = zend_lookup_class(Z_STR_P(arg));
  878. }
  879. if (ce && ce->parent) {
  880. RETURN_STR_COPY(ce->parent->name);
  881. } else {
  882. RETURN_FALSE;
  883. }
  884. }
  885. /* }}} */
  886. static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* {{{ */
  887. {
  888. zval *obj;
  889. zend_string *class_name;
  890. zend_class_entry *instance_ce;
  891. zend_class_entry *ce;
  892. zend_bool allow_string = only_subclass;
  893. zend_bool retval;
  894. ZEND_PARSE_PARAMETERS_START(2, 3)
  895. Z_PARAM_ZVAL(obj)
  896. Z_PARAM_STR(class_name)
  897. Z_PARAM_OPTIONAL
  898. Z_PARAM_BOOL(allow_string)
  899. ZEND_PARSE_PARAMETERS_END();
  900. /*
  901. * allow_string - is_a default is no, is_subclass_of is yes.
  902. * if it's allowed, then the autoloader will be called if the class does not exist.
  903. * default behaviour is different, as 'is_a' used to be used to test mixed return values
  904. * and there is no easy way to deprecate this.
  905. */
  906. if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
  907. instance_ce = zend_lookup_class(Z_STR_P(obj));
  908. if (!instance_ce) {
  909. RETURN_FALSE;
  910. }
  911. } else if (Z_TYPE_P(obj) == IS_OBJECT) {
  912. instance_ce = Z_OBJCE_P(obj);
  913. } else {
  914. RETURN_FALSE;
  915. }
  916. if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
  917. retval = 1;
  918. } else {
  919. ce = zend_lookup_class_ex(class_name, NULL, 0);
  920. if (!ce) {
  921. retval = 0;
  922. } else {
  923. if (only_subclass && instance_ce == ce) {
  924. retval = 0;
  925. } else {
  926. retval = instanceof_function(instance_ce, ce);
  927. }
  928. }
  929. }
  930. RETURN_BOOL(retval);
  931. }
  932. /* }}} */
  933. /* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string])
  934. Returns true if the object has this class as one of its parents */
  935. ZEND_FUNCTION(is_subclass_of)
  936. {
  937. is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  938. }
  939. /* }}} */
  940. /* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string])
  941. Returns true if the first argument is an object and is this class or has this class as one of its parents, */
  942. ZEND_FUNCTION(is_a)
  943. {
  944. is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  945. }
  946. /* }}} */
  947. /* {{{ add_class_vars */
  948. static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int statics, zval *return_value)
  949. {
  950. zend_property_info *prop_info;
  951. zval *prop, prop_copy;
  952. zend_string *key;
  953. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
  954. if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
  955. !zend_check_protected(prop_info->ce, scope)) ||
  956. ((prop_info->flags & ZEND_ACC_PRIVATE) &&
  957. prop_info->ce != scope)) {
  958. continue;
  959. }
  960. prop = NULL;
  961. if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
  962. prop = &ce->default_static_members_table[prop_info->offset];
  963. ZVAL_DEINDIRECT(prop);
  964. } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
  965. prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
  966. }
  967. if (!prop || Z_TYPE_P(prop) == IS_UNDEF) {
  968. continue;
  969. }
  970. /* copy: enforce read only access */
  971. ZVAL_COPY_OR_DUP(&prop_copy, prop);
  972. prop = &prop_copy;
  973. /* this is necessary to make it able to work with default array
  974. * properties, returned to user */
  975. if (Z_OPT_TYPE_P(prop) == IS_CONSTANT_AST) {
  976. if (UNEXPECTED(zval_update_constant_ex(prop, NULL) != SUCCESS)) {
  977. return;
  978. }
  979. }
  980. zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
  981. } ZEND_HASH_FOREACH_END();
  982. }
  983. /* }}} */
  984. /* {{{ proto array get_class_vars(string class_name)
  985. Returns an array of default properties of the class. */
  986. ZEND_FUNCTION(get_class_vars)
  987. {
  988. zend_string *class_name;
  989. zend_class_entry *ce, *scope;
  990. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) {
  991. return;
  992. }
  993. ce = zend_lookup_class(class_name);
  994. if (!ce) {
  995. RETURN_FALSE;
  996. } else {
  997. array_init(return_value);
  998. if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
  999. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  1000. return;
  1001. }
  1002. }
  1003. scope = zend_get_executed_scope();
  1004. add_class_vars(scope, ce, 0, return_value);
  1005. add_class_vars(scope, ce, 1, return_value);
  1006. }
  1007. }
  1008. /* }}} */
  1009. /* {{{ proto array get_object_vars(object obj)
  1010. Returns an array of object properties */
  1011. ZEND_FUNCTION(get_object_vars)
  1012. {
  1013. zval *obj;
  1014. zval *value;
  1015. HashTable *properties;
  1016. zend_string *key;
  1017. zend_object *zobj;
  1018. zend_ulong num_key;
  1019. ZEND_PARSE_PARAMETERS_START(1, 1)
  1020. Z_PARAM_OBJECT(obj)
  1021. ZEND_PARSE_PARAMETERS_END();
  1022. properties = Z_OBJ_HT_P(obj)->get_properties(obj);
  1023. if (properties == NULL) {
  1024. RETURN_FALSE;
  1025. }
  1026. zobj = Z_OBJ_P(obj);
  1027. if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) {
  1028. /* fast copy */
  1029. if (EXPECTED(zobj->handlers == &std_object_handlers)) {
  1030. RETURN_ARR(zend_proptable_to_symtable(properties, 0));
  1031. }
  1032. RETURN_ARR(zend_proptable_to_symtable(properties, 1));
  1033. } else {
  1034. array_init_size(return_value, zend_hash_num_elements(properties));
  1035. ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
  1036. zend_bool unmangle = 0;
  1037. if (Z_TYPE_P(value) == IS_INDIRECT) {
  1038. value = Z_INDIRECT_P(value);
  1039. if (UNEXPECTED(Z_ISUNDEF_P(value))) {
  1040. continue;
  1041. }
  1042. ZEND_ASSERT(key);
  1043. if (zend_check_property_access(zobj, key) == FAILURE) {
  1044. continue;
  1045. }
  1046. unmangle = 1;
  1047. }
  1048. if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
  1049. value = Z_REFVAL_P(value);
  1050. }
  1051. Z_TRY_ADDREF_P(value);
  1052. if (UNEXPECTED(!key)) {
  1053. /* This case is only possible due to loopholes, e.g. ArrayObject */
  1054. zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
  1055. } else if (unmangle && ZSTR_VAL(key)[0] == 0) {
  1056. const char *prop_name, *class_name;
  1057. size_t prop_len;
  1058. zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
  1059. /* We assume here that a mangled property name is never
  1060. * numeric. This is probably a safe assumption, but
  1061. * theoretically someone might write an extension with
  1062. * private, numeric properties. Well, too bad.
  1063. */
  1064. zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
  1065. } else {
  1066. zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value);
  1067. }
  1068. } ZEND_HASH_FOREACH_END();
  1069. }
  1070. }
  1071. /* }}} */
  1072. static int same_name(zend_string *key, zend_string *name) /* {{{ */
  1073. {
  1074. zend_string *lcname;
  1075. int ret;
  1076. if (key == name) {
  1077. return 1;
  1078. }
  1079. if (ZSTR_LEN(key) != ZSTR_LEN(name)) {
  1080. return 0;
  1081. }
  1082. lcname = zend_string_tolower(name);
  1083. ret = memcmp(ZSTR_VAL(lcname), ZSTR_VAL(key), ZSTR_LEN(key)) == 0;
  1084. zend_string_release_ex(lcname, 0);
  1085. return ret;
  1086. }
  1087. /* }}} */
  1088. /* {{{ proto array get_class_methods(mixed class)
  1089. Returns an array of method names for class or class instance. */
  1090. ZEND_FUNCTION(get_class_methods)
  1091. {
  1092. zval *klass;
  1093. zval method_name;
  1094. zend_class_entry *ce = NULL;
  1095. zend_class_entry *scope;
  1096. zend_function *mptr;
  1097. zend_string *key;
  1098. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &klass) == FAILURE) {
  1099. return;
  1100. }
  1101. if (Z_TYPE_P(klass) == IS_OBJECT) {
  1102. ce = Z_OBJCE_P(klass);
  1103. } else if (Z_TYPE_P(klass) == IS_STRING) {
  1104. ce = zend_lookup_class(Z_STR_P(klass));
  1105. }
  1106. if (!ce) {
  1107. RETURN_NULL();
  1108. }
  1109. array_init(return_value);
  1110. scope = zend_get_executed_scope();
  1111. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
  1112. if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
  1113. || (scope &&
  1114. (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
  1115. zend_check_protected(mptr->common.scope, scope))
  1116. || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
  1117. scope == mptr->common.scope)))) {
  1118. size_t len = ZSTR_LEN(mptr->common.function_name);
  1119. /* Do not display old-style inherited constructors */
  1120. if (!key) {
  1121. ZVAL_STR_COPY(&method_name, mptr->common.function_name);
  1122. zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
  1123. } else if (mptr->common.scope->constructor != mptr ||
  1124. mptr->common.scope == ce ||
  1125. zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) {
  1126. if (mptr->type == ZEND_USER_FUNCTION &&
  1127. (!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
  1128. !same_name(key, mptr->common.function_name)) {
  1129. ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
  1130. zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
  1131. } else {
  1132. ZVAL_STR_COPY(&method_name, mptr->common.function_name);
  1133. zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
  1134. }
  1135. }
  1136. }
  1137. } ZEND_HASH_FOREACH_END();
  1138. }
  1139. /* }}} */
  1140. /* {{{ proto bool method_exists(object object, string method)
  1141. Checks if the class method exists */
  1142. ZEND_FUNCTION(method_exists)
  1143. {
  1144. zval *klass;
  1145. zend_string *method_name;
  1146. zend_string *lcname;
  1147. zend_class_entry * ce;
  1148. ZEND_PARSE_PARAMETERS_START(2, 2)
  1149. Z_PARAM_ZVAL(klass)
  1150. Z_PARAM_STR(method_name)
  1151. ZEND_PARSE_PARAMETERS_END();
  1152. if (Z_TYPE_P(klass) == IS_OBJECT) {
  1153. ce = Z_OBJCE_P(klass);
  1154. } else if (Z_TYPE_P(klass) == IS_STRING) {
  1155. if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
  1156. RETURN_FALSE;
  1157. }
  1158. } else {
  1159. RETURN_FALSE;
  1160. }
  1161. lcname = zend_string_tolower(method_name);
  1162. if (zend_hash_exists(&ce->function_table, lcname)) {
  1163. zend_string_release_ex(lcname, 0);
  1164. RETURN_TRUE;
  1165. } else if (Z_TYPE_P(klass) == IS_OBJECT) {
  1166. zend_object *obj = Z_OBJ_P(klass);
  1167. zend_function *func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
  1168. if (func != NULL) {
  1169. if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
  1170. /* Returns true to the fake Closure's __invoke */
  1171. RETVAL_BOOL(func->common.scope == zend_ce_closure
  1172. && zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
  1173. zend_string_release_ex(lcname, 0);
  1174. zend_string_release_ex(func->common.function_name, 0);
  1175. zend_free_trampoline(func);
  1176. return;
  1177. }
  1178. zend_string_release_ex(lcname, 0);
  1179. RETURN_TRUE;
  1180. }
  1181. }
  1182. zend_string_release_ex(lcname, 0);
  1183. RETURN_FALSE;
  1184. }
  1185. /* }}} */
  1186. /* {{{ proto bool property_exists(mixed object_or_class, string property_name)
  1187. Checks if the object or class has a property */
  1188. ZEND_FUNCTION(property_exists)
  1189. {
  1190. zval *object;
  1191. zend_string *property;
  1192. zend_class_entry *ce;
  1193. zend_property_info *property_info;
  1194. zval property_z;
  1195. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
  1196. return;
  1197. }
  1198. if (property == NULL) {
  1199. RETURN_FALSE;
  1200. }
  1201. if (Z_TYPE_P(object) == IS_STRING) {
  1202. ce = zend_lookup_class(Z_STR_P(object));
  1203. if (!ce) {
  1204. RETURN_FALSE;
  1205. }
  1206. } else if (Z_TYPE_P(object) == IS_OBJECT) {
  1207. ce = Z_OBJCE_P(object);
  1208. } else {
  1209. zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
  1210. RETURN_NULL();
  1211. }
  1212. property_info = zend_hash_find_ptr(&ce->properties_info, property);
  1213. if (property_info != NULL
  1214. && (!(property_info->flags & ZEND_ACC_PRIVATE)
  1215. || property_info->ce == ce)) {
  1216. RETURN_TRUE;
  1217. }
  1218. ZVAL_STR(&property_z, property);
  1219. if (Z_TYPE_P(object) == IS_OBJECT &&
  1220. Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) {
  1221. RETURN_TRUE;
  1222. }
  1223. RETURN_FALSE;
  1224. }
  1225. /* }}} */
  1226. /* {{{ proto bool class_exists(string classname [, bool autoload])
  1227. Checks if the class exists */
  1228. ZEND_FUNCTION(class_exists)
  1229. {
  1230. zend_string *class_name;
  1231. zend_string *lc_name;
  1232. zend_class_entry *ce;
  1233. zend_bool autoload = 1;
  1234. ZEND_PARSE_PARAMETERS_START(1, 2)
  1235. Z_PARAM_STR(class_name)
  1236. Z_PARAM_OPTIONAL
  1237. Z_PARAM_BOOL(autoload)
  1238. ZEND_PARSE_PARAMETERS_END();
  1239. if (!autoload) {
  1240. if (ZSTR_VAL(class_name)[0] == '\\') {
  1241. /* Ignore leading "\" */
  1242. lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
  1243. zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
  1244. } else {
  1245. lc_name = zend_string_tolower(class_name);
  1246. }
  1247. ce = zend_hash_find_ptr(EG(class_table), lc_name);
  1248. zend_string_release_ex(lc_name, 0);
  1249. } else {
  1250. ce = zend_lookup_class(class_name);
  1251. }
  1252. if (ce) {
  1253. RETURN_BOOL((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) == 0);
  1254. } else {
  1255. RETURN_FALSE;
  1256. }
  1257. }
  1258. /* }}} */
  1259. /* {{{ proto bool interface_exists(string classname [, bool autoload])
  1260. Checks if the class exists */
  1261. ZEND_FUNCTION(interface_exists)
  1262. {
  1263. zend_string *iface_name, *lc_name;
  1264. zend_class_entry *ce;
  1265. zend_bool autoload = 1;
  1266. ZEND_PARSE_PARAMETERS_START(1, 2)
  1267. Z_PARAM_STR(iface_name)
  1268. Z_PARAM_OPTIONAL
  1269. Z_PARAM_BOOL(autoload)
  1270. ZEND_PARSE_PARAMETERS_END();
  1271. if (!autoload) {
  1272. if (ZSTR_VAL(iface_name)[0] == '\\') {
  1273. /* Ignore leading "\" */
  1274. lc_name = zend_string_alloc(ZSTR_LEN(iface_name) - 1, 0);
  1275. zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(iface_name) + 1, ZSTR_LEN(iface_name) - 1);
  1276. } else {
  1277. lc_name = zend_string_tolower(iface_name);
  1278. }
  1279. ce = zend_hash_find_ptr(EG(class_table), lc_name);
  1280. zend_string_release_ex(lc_name, 0);
  1281. RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE);
  1282. }
  1283. ce = zend_lookup_class(iface_name);
  1284. if (ce) {
  1285. RETURN_BOOL((ce->ce_flags & ZEND_ACC_INTERFACE) > 0);
  1286. } else {
  1287. RETURN_FALSE;
  1288. }
  1289. }
  1290. /* }}} */
  1291. /* {{{ proto bool trait_exists(string traitname [, bool autoload])
  1292. Checks if the trait exists */
  1293. ZEND_FUNCTION(trait_exists)
  1294. {
  1295. zend_string *trait_name, *lc_name;
  1296. zend_class_entry *ce;
  1297. zend_bool autoload = 1;
  1298. ZEND_PARSE_PARAMETERS_START(1, 2)
  1299. Z_PARAM_STR(trait_name)
  1300. Z_PARAM_OPTIONAL
  1301. Z_PARAM_BOOL(autoload)
  1302. ZEND_PARSE_PARAMETERS_END();
  1303. if (!autoload) {
  1304. if (ZSTR_VAL(trait_name)[0] == '\\') {
  1305. /* Ignore leading "\" */
  1306. lc_name = zend_string_alloc(ZSTR_LEN(trait_name) - 1, 0);
  1307. zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(trait_name) + 1, ZSTR_LEN(trait_name) - 1);
  1308. } else {
  1309. lc_name = zend_string_tolower(trait_name);
  1310. }
  1311. ce = zend_hash_find_ptr(EG(class_table), lc_name);
  1312. zend_string_release_ex(lc_name, 0);
  1313. } else {
  1314. ce = zend_lookup_class(trait_name);
  1315. }
  1316. if (ce) {
  1317. RETURN_BOOL((ce->ce_flags & ZEND_ACC_TRAIT) != 0);
  1318. } else {
  1319. RETURN_FALSE;
  1320. }
  1321. }
  1322. /* }}} */
  1323. /* {{{ proto bool function_exists(string function_name)
  1324. Checks if the function exists */
  1325. ZEND_FUNCTION(function_exists)
  1326. {
  1327. zend_string *name;
  1328. zend_function *func;
  1329. zend_string *lcname;
  1330. ZEND_PARSE_PARAMETERS_START(1, 1)
  1331. Z_PARAM_STR(name)
  1332. ZEND_PARSE_PARAMETERS_END();
  1333. if (ZSTR_VAL(name)[0] == '\\') {
  1334. /* Ignore leading "\" */
  1335. lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
  1336. zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
  1337. } else {
  1338. lcname = zend_string_tolower(name);
  1339. }
  1340. func = zend_hash_find_ptr(EG(function_table), lcname);
  1341. zend_string_release_ex(lcname, 0);
  1342. /*
  1343. * A bit of a hack, but not a bad one: we see if the handler of the function
  1344. * is actually one that displays "function is disabled" message.
  1345. */
  1346. RETURN_BOOL(func && (func->type != ZEND_INTERNAL_FUNCTION ||
  1347. func->internal_function.handler != zif_display_disabled_function));
  1348. }
  1349. /* }}} */
  1350. /* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload])
  1351. Creates an alias for user defined class */
  1352. ZEND_FUNCTION(class_alias)
  1353. {
  1354. zend_string *class_name;
  1355. char *alias_name;
  1356. zend_class_entry *ce;
  1357. size_t alias_name_len;
  1358. zend_bool autoload = 1;
  1359. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) {
  1360. return;
  1361. }
  1362. ce = zend_lookup_class_ex(class_name, NULL, autoload);
  1363. if (ce) {
  1364. if (ce->type == ZEND_USER_CLASS) {
  1365. if (zend_register_class_alias_ex(alias_name, alias_name_len, ce, 0) == SUCCESS) {
  1366. RETURN_TRUE;
  1367. } else {
  1368. zend_error(E_WARNING, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), alias_name);
  1369. RETURN_FALSE;
  1370. }
  1371. } else {
  1372. zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class");
  1373. RETURN_FALSE;
  1374. }
  1375. } else {
  1376. zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name));
  1377. RETURN_FALSE;
  1378. }
  1379. }
  1380. /* }}} */
  1381. /* {{{ proto array get_included_files(void)
  1382. Returns an array with the file names that were include_once()'d */
  1383. ZEND_FUNCTION(get_included_files)
  1384. {
  1385. zend_string *entry;
  1386. if (zend_parse_parameters_none() == FAILURE) {
  1387. return;
  1388. }
  1389. array_init(return_value);
  1390. ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) {
  1391. if (entry) {
  1392. add_next_index_str(return_value, zend_string_copy(entry));
  1393. }
  1394. } ZEND_HASH_FOREACH_END();
  1395. }
  1396. /* }}} */
  1397. /* {{{ proto void trigger_error(string message [, int error_type])
  1398. Generates a user-level error/warning/notice message */
  1399. ZEND_FUNCTION(trigger_error)
  1400. {
  1401. zend_long error_type = E_USER_NOTICE;
  1402. char *message;
  1403. size_t message_len;
  1404. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) {
  1405. return;
  1406. }
  1407. switch (error_type) {
  1408. case E_USER_ERROR:
  1409. case E_USER_WARNING:
  1410. case E_USER_NOTICE:
  1411. case E_USER_DEPRECATED:
  1412. break;
  1413. default:
  1414. zend_error(E_WARNING, "Invalid error type specified");
  1415. RETURN_FALSE;
  1416. break;
  1417. }
  1418. zend_error((int)error_type, "%s", message);
  1419. RETURN_TRUE;
  1420. }
  1421. /* }}} */
  1422. /* {{{ proto string set_error_handler(callable error_handler [, int error_types])
  1423. Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */
  1424. ZEND_FUNCTION(set_error_handler)
  1425. {
  1426. zval *error_handler;
  1427. zend_long error_type = E_ALL;
  1428. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &error_handler, &error_type) == FAILURE) {
  1429. return;
  1430. }
  1431. if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */
  1432. if (!zend_is_callable(error_handler, 0, NULL)) {
  1433. zend_string *error_handler_name = zend_get_callable_name(error_handler);
  1434. zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
  1435. get_active_function_name(), error_handler_name?ZSTR_VAL(error_handler_name):"unknown");
  1436. zend_string_release_ex(error_handler_name, 0);
  1437. return;
  1438. }
  1439. }
  1440. if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
  1441. ZVAL_COPY(return_value, &EG(user_error_handler));
  1442. zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting));
  1443. zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler));
  1444. }
  1445. if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */
  1446. ZVAL_UNDEF(&EG(user_error_handler));
  1447. return;
  1448. }
  1449. ZVAL_COPY(&EG(user_error_handler), error_handler);
  1450. EG(user_error_handler_error_reporting) = (int)error_type;
  1451. }
  1452. /* }}} */
  1453. /* {{{ proto void restore_error_handler(void)
  1454. Restores the previously defined error handler function */
  1455. ZEND_FUNCTION(restore_error_handler)
  1456. {
  1457. if (zend_parse_parameters_none() == FAILURE) {
  1458. return;
  1459. }
  1460. if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
  1461. zval zeh;
  1462. ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
  1463. ZVAL_UNDEF(&EG(user_error_handler));
  1464. zval_ptr_dtor(&zeh);
  1465. }
  1466. if (zend_stack_is_empty(&EG(user_error_handlers))) {
  1467. ZVAL_UNDEF(&EG(user_error_handler));
  1468. } else {
  1469. zval *tmp;
  1470. EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
  1471. zend_stack_del_top(&EG(user_error_handlers_error_reporting));
  1472. tmp = zend_stack_top(&EG(user_error_handlers));
  1473. ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
  1474. zend_stack_del_top(&EG(user_error_handlers));
  1475. }
  1476. RETURN_TRUE;
  1477. }
  1478. /* }}} */
  1479. /* {{{ proto mixed set_exception_handler(callable exception_handler)
  1480. Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
  1481. ZEND_FUNCTION(set_exception_handler)
  1482. {
  1483. zval *exception_handler;
  1484. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &exception_handler) == FAILURE) {
  1485. return;
  1486. }
  1487. if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
  1488. if (!zend_is_callable(exception_handler, 0, NULL)) {
  1489. zend_string *exception_handler_name = zend_get_callable_name(exception_handler);
  1490. zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
  1491. get_active_function_name(), exception_handler_name?ZSTR_VAL(exception_handler_name):"unknown");
  1492. zend_string_release_ex(exception_handler_name, 0);
  1493. return;
  1494. }
  1495. }
  1496. if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
  1497. ZVAL_COPY(return_value, &EG(user_exception_handler));
  1498. zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
  1499. }
  1500. if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */
  1501. ZVAL_UNDEF(&EG(user_exception_handler));
  1502. return;
  1503. }
  1504. ZVAL_COPY(&EG(user_exception_handler), exception_handler);
  1505. }
  1506. /* }}} */
  1507. /* {{{ proto void restore_exception_handler(void)
  1508. Restores the previously defined exception handler function */
  1509. ZEND_FUNCTION(restore_exception_handler)
  1510. {
  1511. if (zend_parse_parameters_none() == FAILURE) {
  1512. return;
  1513. }
  1514. if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
  1515. zval_ptr_dtor(&EG(user_exception_handler));
  1516. }
  1517. if (zend_stack_is_empty(&EG(user_exception_handlers))) {
  1518. ZVAL_UNDEF(&EG(user_exception_handler));
  1519. } else {
  1520. zval *tmp = zend_stack_top(&EG(user_exception_handlers));
  1521. ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
  1522. zend_stack_del_top(&EG(user_exception_handlers));
  1523. }
  1524. RETURN_TRUE;
  1525. }
  1526. /* }}} */
  1527. static int copy_class_or_interface_name(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
  1528. {
  1529. zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
  1530. zval *array = va_arg(args, zval *);
  1531. uint32_t mask = va_arg(args, uint32_t);
  1532. uint32_t comply = va_arg(args, uint32_t);
  1533. uint32_t comply_mask = (comply)? mask:0;
  1534. if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0)
  1535. && (comply_mask == (ce->ce_flags & mask))) {
  1536. if ((ce->refcount > 1 || (ce->ce_flags & ZEND_ACC_IMMUTABLE)) &&
  1537. !same_name(hash_key->key, ce->name)) {
  1538. add_next_index_str(array, zend_string_copy(hash_key->key));
  1539. } else {
  1540. add_next_index_str(array, zend_string_copy(ce->name));
  1541. }
  1542. }
  1543. return ZEND_HASH_APPLY_KEEP;
  1544. }
  1545. /* }}} */
  1546. /* {{{ proto array get_declared_traits()
  1547. Returns an array of all declared traits. */
  1548. ZEND_FUNCTION(get_declared_traits)
  1549. {
  1550. uint32_t mask = ZEND_ACC_TRAIT;
  1551. uint32_t comply = 1;
  1552. if (zend_parse_parameters_none() == FAILURE) {
  1553. return;
  1554. }
  1555. array_init(return_value);
  1556. zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
  1557. }
  1558. /* }}} */
  1559. /* {{{ proto array get_declared_classes()
  1560. Returns an array of all declared classes. */
  1561. ZEND_FUNCTION(get_declared_classes)
  1562. {
  1563. uint32_t mask = ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
  1564. uint32_t comply = 0;
  1565. if (zend_parse_parameters_none() == FAILURE) {
  1566. return;
  1567. }
  1568. array_init(return_value);
  1569. zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
  1570. }
  1571. /* }}} */
  1572. /* {{{ proto array get_declared_interfaces()
  1573. Returns an array of all declared interfaces. */
  1574. ZEND_FUNCTION(get_declared_interfaces)
  1575. {
  1576. uint32_t mask = ZEND_ACC_INTERFACE;
  1577. uint32_t comply = 1;
  1578. if (zend_parse_parameters_none() == FAILURE) {
  1579. return;
  1580. }
  1581. array_init(return_value);
  1582. zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
  1583. }
  1584. /* }}} */
  1585. static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
  1586. {
  1587. zend_function *func = Z_PTR_P(zv);
  1588. zval *internal_ar = va_arg(args, zval *),
  1589. *user_ar = va_arg(args, zval *);
  1590. zend_bool *exclude_disabled = va_arg(args, zend_bool *);
  1591. if (hash_key->key == NULL || ZSTR_VAL(hash_key->key)[0] == 0) {
  1592. return 0;
  1593. }
  1594. if (func->type == ZEND_INTERNAL_FUNCTION) {
  1595. char *disable_functions = INI_STR("disable_functions");
  1596. if ((*exclude_disabled == 1) && (disable_functions != NULL)) {
  1597. if (strstr(disable_functions, func->common.function_name->val) == NULL) {
  1598. add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
  1599. }
  1600. } else {
  1601. add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
  1602. }
  1603. } else if (func->type == ZEND_USER_FUNCTION) {
  1604. add_next_index_str(user_ar, zend_string_copy(hash_key->key));
  1605. }
  1606. return 0;
  1607. }
  1608. /* }}} */
  1609. /* {{{ proto array get_defined_functions(void)
  1610. Returns an array of all defined functions */
  1611. ZEND_FUNCTION(get_defined_functions)
  1612. {
  1613. zval internal, user;
  1614. zend_bool exclude_disabled = 0;
  1615. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
  1616. return;
  1617. }
  1618. array_init(&internal);
  1619. array_init(&user);
  1620. array_init(return_value);
  1621. zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 3, &internal, &user, &exclude_disabled);
  1622. zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
  1623. zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user);
  1624. }
  1625. /* }}} */
  1626. /* {{{ proto array get_defined_vars(void)
  1627. Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
  1628. ZEND_FUNCTION(get_defined_vars)
  1629. {
  1630. zend_array *symbol_table;
  1631. if (zend_forbid_dynamic_call("get_defined_vars()") == FAILURE) {
  1632. return;
  1633. }
  1634. symbol_table = zend_rebuild_symbol_table();
  1635. if (UNEXPECTED(symbol_table == NULL)) {
  1636. return;
  1637. }
  1638. RETURN_ARR(zend_array_dup(symbol_table));
  1639. }
  1640. /* }}} */
  1641. #define LAMBDA_TEMP_FUNCNAME "__lambda_func"
  1642. /* {{{ proto string create_function(string args, string code)
  1643. Creates an anonymous function, and returns its name (funny, eh?) */
  1644. ZEND_FUNCTION(create_function)
  1645. {
  1646. zend_string *function_name;
  1647. char *eval_code, *function_args, *function_code;
  1648. size_t eval_code_length, function_args_len, function_code_len;
  1649. int retval;
  1650. char *eval_name;
  1651. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) {
  1652. return;
  1653. }
  1654. eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME)
  1655. +function_args_len
  1656. +2 /* for the args parentheses */
  1657. +2 /* for the curly braces */
  1658. +function_code_len);
  1659. eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1;
  1660. memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length);
  1661. memcpy(eval_code + eval_code_length, function_args, function_args_len);
  1662. eval_code_length += function_args_len;
  1663. eval_code[eval_code_length++] = ')';
  1664. eval_code[eval_code_length++] = '{';
  1665. memcpy(eval_code + eval_code_length, function_code, function_code_len);
  1666. eval_code_length += function_code_len;
  1667. eval_code[eval_code_length++] = '}';
  1668. eval_code[eval_code_length] = '\0';
  1669. eval_name = zend_make_compiled_string_description("runtime-created function");
  1670. retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name);
  1671. efree(eval_code);
  1672. efree(eval_name);
  1673. if (retval==SUCCESS) {
  1674. zend_op_array *func;
  1675. HashTable *static_variables;
  1676. func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
  1677. if (!func) {
  1678. zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()");
  1679. RETURN_FALSE;
  1680. }
  1681. if (func->refcount) {
  1682. (*func->refcount)++;
  1683. }
  1684. static_variables = func->static_variables;
  1685. func->static_variables = NULL;
  1686. zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
  1687. func->static_variables = static_variables;
  1688. function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
  1689. ZSTR_VAL(function_name)[0] = '\0';
  1690. do {
  1691. ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1;
  1692. } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL);
  1693. RETURN_NEW_STR(function_name);
  1694. } else {
  1695. zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
  1696. RETURN_FALSE;
  1697. }
  1698. }
  1699. /* }}} */
  1700. #if ZEND_DEBUG && defined(ZTS)
  1701. ZEND_FUNCTION(zend_thread_id)
  1702. {
  1703. RETURN_LONG((zend_long)tsrm_thread_id());
  1704. }
  1705. #endif
  1706. /* {{{ proto string get_resource_type(resource res)
  1707. Get the resource type name for a given resource */
  1708. ZEND_FUNCTION(get_resource_type)
  1709. {
  1710. const char *resource_type;
  1711. zval *z_resource_type;
  1712. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
  1713. return;
  1714. }
  1715. resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
  1716. if (resource_type) {
  1717. RETURN_STRING(resource_type);
  1718. } else {
  1719. RETURN_STRING("Unknown");
  1720. }
  1721. }
  1722. /* }}} */
  1723. /* {{{ proto array get_resources([string resouce_type])
  1724. Get an array with all active resources */
  1725. ZEND_FUNCTION(get_resources)
  1726. {
  1727. zend_string *type = NULL;
  1728. zend_string *key;
  1729. zend_ulong index;
  1730. zval *val;
  1731. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &type) == FAILURE) {
  1732. return;
  1733. }
  1734. if (!type) {
  1735. array_init(return_value);
  1736. ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
  1737. if (!key) {
  1738. Z_ADDREF_P(val);
  1739. zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
  1740. }
  1741. } ZEND_HASH_FOREACH_END();
  1742. } else if (zend_string_equals_literal(type, "Unknown")) {
  1743. array_init(return_value);
  1744. ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
  1745. if (!key && Z_RES_TYPE_P(val) <= 0) {
  1746. Z_ADDREF_P(val);
  1747. zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
  1748. }
  1749. } ZEND_HASH_FOREACH_END();
  1750. } else {
  1751. int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
  1752. if (id <= 0) {
  1753. zend_error(E_WARNING, "get_resources(): Unknown resource type '%s'", ZSTR_VAL(type));
  1754. RETURN_FALSE;
  1755. }
  1756. array_init(return_value);
  1757. ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
  1758. if (!key && Z_RES_TYPE_P(val) == id) {
  1759. Z_ADDREF_P(val);
  1760. zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
  1761. }
  1762. } ZEND_HASH_FOREACH_END();
  1763. }
  1764. }
  1765. /* }}} */
  1766. static int add_extension_info(zval *item, void *arg) /* {{{ */
  1767. {
  1768. zval *name_array = (zval *)arg;
  1769. zend_module_entry *module = (zend_module_entry*)Z_PTR_P(item);
  1770. add_next_index_string(name_array, module->name);
  1771. return 0;
  1772. }
  1773. /* }}} */
  1774. static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
  1775. {
  1776. zval *name_array = (zval *)arg;
  1777. add_next_index_string(name_array, ext->name);
  1778. return 0;
  1779. }
  1780. /* }}} */
  1781. static int add_constant_info(zval *item, void *arg) /* {{{ */
  1782. {
  1783. zval *name_array = (zval *)arg;
  1784. zend_constant *constant = (zend_constant*)Z_PTR_P(item);
  1785. zval const_val;
  1786. if (!constant->name) {
  1787. /* skip special constants */
  1788. return 0;
  1789. }
  1790. ZVAL_COPY_OR_DUP(&const_val, &constant->value);
  1791. zend_hash_add_new(Z_ARRVAL_P(name_array), constant->name, &const_val);
  1792. return 0;
  1793. }
  1794. /* }}} */
  1795. /* {{{ proto array get_loaded_extensions([bool zend_extensions])
  1796. Return an array containing names of loaded extensions */
  1797. ZEND_FUNCTION(get_loaded_extensions)
  1798. {
  1799. zend_bool zendext = 0;
  1800. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
  1801. return;
  1802. }
  1803. array_init(return_value);
  1804. if (zendext) {
  1805. zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t)add_zendext_info, return_value);
  1806. } else {
  1807. zend_hash_apply_with_argument(&module_registry, add_extension_info, return_value);
  1808. }
  1809. }
  1810. /* }}} */
  1811. /* {{{ proto array get_defined_constants([bool categorize])
  1812. Return an array containing the names and values of all defined constants */
  1813. ZEND_FUNCTION(get_defined_constants)
  1814. {
  1815. zend_bool categorize = 0;
  1816. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
  1817. return;
  1818. }
  1819. array_init(return_value);
  1820. if (categorize) {
  1821. zend_constant *val;
  1822. int module_number;
  1823. zval *modules, const_val;
  1824. char **module_names;
  1825. zend_module_entry *module;
  1826. int i = 1;
  1827. modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
  1828. module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
  1829. module_names[0] = "internal";
  1830. ZEND_HASH_FOREACH_PTR(&module_registry, module) {
  1831. module_names[module->module_number] = (char *)module->name;
  1832. i++;
  1833. } ZEND_HASH_FOREACH_END();
  1834. module_names[i] = "user";
  1835. ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) {
  1836. if (!val->name) {
  1837. /* skip special constants */
  1838. continue;
  1839. }
  1840. if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
  1841. module_number = i;
  1842. } else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
  1843. /* should not happen */
  1844. continue;
  1845. } else {
  1846. module_number = ZEND_CONSTANT_MODULE_NUMBER(val);
  1847. }
  1848. if (Z_TYPE(modules[module_number]) == IS_UNDEF) {
  1849. array_init(&modules[module_number]);
  1850. add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
  1851. }
  1852. ZVAL_COPY_OR_DUP(&const_val, &val->value);
  1853. zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
  1854. } ZEND_HASH_FOREACH_END();
  1855. efree(module_names);
  1856. efree(modules);
  1857. } else {
  1858. zend_hash_apply_with_argument(EG(zend_constants), add_constant_info, return_value);
  1859. }
  1860. }
  1861. /* }}} */
  1862. static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
  1863. {
  1864. uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
  1865. if (num_args) {
  1866. uint32_t i = 0;
  1867. zval *p = ZEND_CALL_ARG(call, 1);
  1868. array_init_size(arg_array, num_args);
  1869. zend_hash_real_init_packed(Z_ARRVAL_P(arg_array));
  1870. ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
  1871. if (call->func->type == ZEND_USER_FUNCTION) {
  1872. uint32_t first_extra_arg = MIN(num_args, call->func->op_array.num_args);
  1873. if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
  1874. /* In case of attached symbol_table, values on stack may be invalid
  1875. * and we have to access them through symbol_table
  1876. * See: https://bugs.php.net/bug.php?id=73156
  1877. */
  1878. zend_string *arg_name;
  1879. zval *arg;
  1880. while (i < first_extra_arg) {
  1881. arg_name = call->func->op_array.vars[i];
  1882. arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1);
  1883. if (arg) {
  1884. if (Z_OPT_REFCOUNTED_P(arg)) {
  1885. Z_ADDREF_P(arg);
  1886. }
  1887. ZEND_HASH_FILL_ADD(arg);
  1888. } else {
  1889. ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
  1890. }
  1891. i++;
  1892. }
  1893. } else {
  1894. while (i < first_extra_arg) {
  1895. if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
  1896. if (Z_OPT_REFCOUNTED_P(p)) {
  1897. Z_ADDREF_P(p);
  1898. }
  1899. ZEND_HASH_FILL_ADD(p);
  1900. } else {
  1901. ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
  1902. }
  1903. p++;
  1904. i++;
  1905. }
  1906. }
  1907. p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
  1908. }
  1909. while (i < num_args) {
  1910. if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
  1911. if (Z_OPT_REFCOUNTED_P(p)) {
  1912. Z_ADDREF_P(p);
  1913. }
  1914. ZEND_HASH_FILL_ADD(p);
  1915. } else {
  1916. ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
  1917. }
  1918. p++;
  1919. i++;
  1920. }
  1921. } ZEND_HASH_FILL_END();
  1922. Z_ARRVAL_P(arg_array)->nNumOfElements = num_args;
  1923. } else {
  1924. ZVAL_EMPTY_ARRAY(arg_array);
  1925. }
  1926. }
  1927. /* }}} */
  1928. void debug_print_backtrace_args(zval *arg_array) /* {{{ */
  1929. {
  1930. zval *tmp;
  1931. int i = 0;
  1932. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arg_array), tmp) {
  1933. if (i++) {
  1934. ZEND_PUTS(", ");
  1935. }
  1936. zend_print_flat_zval_r(tmp);
  1937. } ZEND_HASH_FOREACH_END();
  1938. }
  1939. /* }}} */
  1940. /* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
  1941. ZEND_FUNCTION(debug_print_backtrace)
  1942. {
  1943. zend_execute_data *call, *ptr, *skip;
  1944. zend_object *object;
  1945. int lineno, frameno = 0;
  1946. zend_function *func;
  1947. const char *function_name;
  1948. const char *filename;
  1949. zend_string *class_name = NULL;
  1950. char *call_type;
  1951. const char *include_filename = NULL;
  1952. zval arg_array;
  1953. int indent = 0;
  1954. zend_long options = 0;
  1955. zend_long limit = 0;
  1956. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
  1957. return;
  1958. }
  1959. ZVAL_UNDEF(&arg_array);
  1960. ptr = EX(prev_execute_data);
  1961. /* skip debug_backtrace() */
  1962. call = ptr;
  1963. ptr = ptr->prev_execute_data;
  1964. while (ptr && (limit == 0 || frameno < limit)) {
  1965. frameno++;
  1966. class_name = NULL;
  1967. call_type = NULL;
  1968. ZVAL_UNDEF(&arg_array);
  1969. ptr = zend_generator_check_placeholder_frame(ptr);
  1970. skip = ptr;
  1971. /* skip internal handler */
  1972. if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
  1973. skip->prev_execute_data &&
  1974. skip->prev_execute_data->func &&
  1975. ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
  1976. skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
  1977. skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
  1978. skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
  1979. skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
  1980. skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
  1981. skip = skip->prev_execute_data;
  1982. }
  1983. if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
  1984. filename = ZSTR_VAL(skip->func->op_array.filename);
  1985. if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
  1986. if (EG(opline_before_exception)) {
  1987. lineno = EG(opline_before_exception)->lineno;
  1988. } else {
  1989. lineno = skip->func->op_array.line_end;
  1990. }
  1991. } else {
  1992. lineno = skip->opline->lineno;
  1993. }
  1994. } else {
  1995. filename = NULL;
  1996. lineno = 0;
  1997. }
  1998. /* $this may be passed into regular internal functions */
  1999. object = (Z_TYPE(call->This) == IS_OBJECT) ? Z_OBJ(call->This) : NULL;
  2000. if (call->func) {
  2001. zend_string *zend_function_name;
  2002. func = call->func;
  2003. if (func->common.scope && func->common.scope->trait_aliases) {
  2004. zend_function_name = zend_resolve_method_name(object ? object->ce : func->common.scope, func);
  2005. } else {
  2006. zend_function_name = func->common.function_name;
  2007. }
  2008. if (zend_function_name != NULL) {
  2009. function_name = ZSTR_VAL(zend_function_name);
  2010. } else {
  2011. function_name = NULL;
  2012. }
  2013. } else {
  2014. func = NULL;
  2015. function_name = NULL;
  2016. }
  2017. if (function_name) {
  2018. if (object) {
  2019. if (func->common.scope) {
  2020. class_name = func->common.scope->name;
  2021. } else if (object->handlers->get_class_name == zend_std_get_class_name) {
  2022. class_name = object->ce->name;
  2023. } else {
  2024. class_name = object->handlers->get_class_name(object);
  2025. }
  2026. call_type = "->";
  2027. } else if (func->common.scope) {
  2028. class_name = func->common.scope->name;
  2029. call_type = "::";
  2030. } else {
  2031. class_name = NULL;
  2032. call_type = NULL;
  2033. }
  2034. if (func->type != ZEND_EVAL_CODE) {
  2035. if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
  2036. debug_backtrace_get_args(call, &arg_array);
  2037. }
  2038. }
  2039. } else {
  2040. /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
  2041. zend_bool build_filename_arg = 1;
  2042. if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
  2043. /* can happen when calling eval from a custom sapi */
  2044. function_name = "unknown";
  2045. build_filename_arg = 0;
  2046. } else
  2047. switch (ptr->opline->extended_value) {
  2048. case ZEND_EVAL:
  2049. function_name = "eval";
  2050. build_filename_arg = 0;
  2051. break;
  2052. case ZEND_INCLUDE:
  2053. function_name = "include";
  2054. break;
  2055. case ZEND_REQUIRE:
  2056. function_name = "require";
  2057. break;
  2058. case ZEND_INCLUDE_ONCE:
  2059. function_name = "include_once";
  2060. break;
  2061. case ZEND_REQUIRE_ONCE:
  2062. function_name = "require_once";
  2063. break;
  2064. default:
  2065. /* this can actually happen if you use debug_backtrace() in your error_handler and
  2066. * you're in the top-scope */
  2067. function_name = "unknown";
  2068. build_filename_arg = 0;
  2069. break;
  2070. }
  2071. if (build_filename_arg && include_filename) {
  2072. array_init(&arg_array);
  2073. add_next_index_string(&arg_array, (char*)include_filename);
  2074. }
  2075. call_type = NULL;
  2076. }
  2077. zend_printf("#%-2d ", indent);
  2078. if (class_name) {
  2079. ZEND_PUTS(ZSTR_VAL(class_name));
  2080. ZEND_PUTS(call_type);
  2081. if (object
  2082. && !func->common.scope
  2083. && object->handlers->get_class_name != zend_std_get_class_name) {
  2084. zend_string_release_ex(class_name, 0);
  2085. }
  2086. }
  2087. zend_printf("%s(", function_name);
  2088. if (Z_TYPE(arg_array) != IS_UNDEF) {
  2089. debug_print_backtrace_args(&arg_array);
  2090. zval_ptr_dtor(&arg_array);
  2091. }
  2092. if (filename) {
  2093. zend_printf(") called at [%s:%d]\n", filename, lineno);
  2094. } else {
  2095. zend_execute_data *prev_call = skip;
  2096. zend_execute_data *prev = skip->prev_execute_data;
  2097. while (prev) {
  2098. if (prev_call &&
  2099. prev_call->func &&
  2100. !ZEND_USER_CODE(prev_call->func->common.type)) {
  2101. prev = NULL;
  2102. break;
  2103. }
  2104. if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
  2105. zend_printf(") called at [%s:%d]\n", ZSTR_VAL(prev->func->op_array.filename), prev->opline->lineno);
  2106. break;
  2107. }
  2108. prev_call = prev;
  2109. prev = prev->prev_execute_data;
  2110. }
  2111. if (!prev) {
  2112. ZEND_PUTS(")\n");
  2113. }
  2114. }
  2115. include_filename = filename;
  2116. call = skip;
  2117. ptr = skip->prev_execute_data;
  2118. ++indent;
  2119. }
  2120. }
  2121. /* }}} */
  2122. ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
  2123. {
  2124. zend_execute_data *ptr, *skip, *call = NULL;
  2125. zend_object *object;
  2126. int lineno, frameno = 0;
  2127. zend_function *func;
  2128. zend_string *function_name;
  2129. zend_string *filename;
  2130. zend_string *include_filename = NULL;
  2131. zval stack_frame, tmp;
  2132. array_init(return_value);
  2133. if (!(ptr = EG(current_execute_data))) {
  2134. return;
  2135. }
  2136. if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
  2137. call = ptr;
  2138. ptr = ptr->prev_execute_data;
  2139. }
  2140. if (ptr) {
  2141. if (skip_last) {
  2142. /* skip debug_backtrace() */
  2143. call = ptr;
  2144. ptr = ptr->prev_execute_data;
  2145. } else {
  2146. /* skip "new Exception()" */
  2147. if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
  2148. call = ptr;
  2149. ptr = ptr->prev_execute_data;
  2150. }
  2151. }
  2152. if (!call) {
  2153. call = ptr;
  2154. ptr = ptr->prev_execute_data;
  2155. }
  2156. }
  2157. while (ptr && (limit == 0 || frameno < limit)) {
  2158. frameno++;
  2159. array_init(&stack_frame);
  2160. ptr = zend_generator_check_placeholder_frame(ptr);
  2161. skip = ptr;
  2162. /* skip internal handler */
  2163. if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
  2164. skip->prev_execute_data &&
  2165. skip->prev_execute_data->func &&
  2166. ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
  2167. skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
  2168. skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
  2169. skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
  2170. skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
  2171. skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
  2172. skip = skip->prev_execute_data;
  2173. }
  2174. if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
  2175. filename = skip->func->op_array.filename;
  2176. if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
  2177. if (EG(opline_before_exception)) {
  2178. lineno = EG(opline_before_exception)->lineno;
  2179. } else {
  2180. lineno = skip->func->op_array.line_end;
  2181. }
  2182. } else {
  2183. lineno = skip->opline->lineno;
  2184. }
  2185. ZVAL_STR_COPY(&tmp, filename);
  2186. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
  2187. ZVAL_LONG(&tmp, lineno);
  2188. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
  2189. /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
  2190. * and debug_baktrace() might have been called by the error_handler. in this case we don't
  2191. * want to pop anything of the argument-stack */
  2192. } else {
  2193. zend_execute_data *prev_call = skip;
  2194. zend_execute_data *prev = skip->prev_execute_data;
  2195. while (prev) {
  2196. if (prev_call &&
  2197. prev_call->func &&
  2198. !ZEND_USER_CODE(prev_call->func->common.type) &&
  2199. !(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
  2200. break;
  2201. }
  2202. if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
  2203. ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
  2204. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
  2205. ZVAL_LONG(&tmp, prev->opline->lineno);
  2206. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
  2207. break;
  2208. }
  2209. prev_call = prev;
  2210. prev = prev->prev_execute_data;
  2211. }
  2212. filename = NULL;
  2213. }
  2214. /* $this may be passed into regular internal functions */
  2215. object = (call && (Z_TYPE(call->This) == IS_OBJECT)) ? Z_OBJ(call->This) : NULL;
  2216. if (call && call->func) {
  2217. func = call->func;
  2218. function_name = (func->common.scope &&
  2219. func->common.scope->trait_aliases) ?
  2220. zend_resolve_method_name(
  2221. (object ? object->ce : func->common.scope), func) :
  2222. func->common.function_name;
  2223. } else {
  2224. func = NULL;
  2225. function_name = NULL;
  2226. }
  2227. if (function_name) {
  2228. ZVAL_STR_COPY(&tmp, function_name);
  2229. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
  2230. if (object) {
  2231. if (func->common.scope) {
  2232. ZVAL_STR_COPY(&tmp, func->common.scope->name);
  2233. } else if (object->handlers->get_class_name == zend_std_get_class_name) {
  2234. ZVAL_STR_COPY(&tmp, object->ce->name);
  2235. } else {
  2236. ZVAL_STR(&tmp, object->handlers->get_class_name(object));
  2237. }
  2238. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
  2239. if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
  2240. ZVAL_OBJ(&tmp, object);
  2241. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp);
  2242. Z_ADDREF(tmp);
  2243. }
  2244. ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR));
  2245. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
  2246. } else if (func->common.scope) {
  2247. ZVAL_STR_COPY(&tmp, func->common.scope->name);
  2248. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
  2249. ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM));
  2250. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
  2251. }
  2252. if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
  2253. func->type != ZEND_EVAL_CODE) {
  2254. debug_backtrace_get_args(call, &tmp);
  2255. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &tmp);
  2256. }
  2257. } else {
  2258. /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
  2259. zend_bool build_filename_arg = 1;
  2260. zend_string *pseudo_function_name;
  2261. if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
  2262. /* can happen when calling eval from a custom sapi */
  2263. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
  2264. build_filename_arg = 0;
  2265. } else
  2266. switch (ptr->opline->extended_value) {
  2267. case ZEND_EVAL:
  2268. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL);
  2269. build_filename_arg = 0;
  2270. break;
  2271. case ZEND_INCLUDE:
  2272. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE);
  2273. break;
  2274. case ZEND_REQUIRE:
  2275. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE);
  2276. break;
  2277. case ZEND_INCLUDE_ONCE:
  2278. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE_ONCE);
  2279. break;
  2280. case ZEND_REQUIRE_ONCE:
  2281. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE);
  2282. break;
  2283. default:
  2284. /* this can actually happen if you use debug_backtrace() in your error_handler and
  2285. * you're in the top-scope */
  2286. pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
  2287. build_filename_arg = 0;
  2288. break;
  2289. }
  2290. if (build_filename_arg && include_filename) {
  2291. zval arg_array;
  2292. array_init(&arg_array);
  2293. /* include_filename always points to the last filename of the last last called-function.
  2294. if we have called include in the frame above - this is the file we have included.
  2295. */
  2296. ZVAL_STR_COPY(&tmp, include_filename);
  2297. zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
  2298. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &arg_array);
  2299. }
  2300. ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
  2301. zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
  2302. }
  2303. zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
  2304. include_filename = filename;
  2305. call = skip;
  2306. ptr = skip->prev_execute_data;
  2307. }
  2308. }
  2309. /* }}} */
  2310. /* {{{ proto array debug_backtrace([int options[, int limit]])
  2311. Return backtrace as array */
  2312. ZEND_FUNCTION(debug_backtrace)
  2313. {
  2314. zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
  2315. zend_long limit = 0;
  2316. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
  2317. return;
  2318. }
  2319. zend_fetch_debug_backtrace(return_value, 1, options, limit);
  2320. }
  2321. /* }}} */
  2322. /* {{{ proto bool extension_loaded(string extension_name)
  2323. Returns true if the named extension is loaded */
  2324. ZEND_FUNCTION(extension_loaded)
  2325. {
  2326. zend_string *extension_name;
  2327. zend_string *lcname;
  2328. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
  2329. return;
  2330. }
  2331. lcname = zend_string_tolower(extension_name);
  2332. if (zend_hash_exists(&module_registry, lcname)) {
  2333. RETVAL_TRUE;
  2334. } else {
  2335. RETVAL_FALSE;
  2336. }
  2337. zend_string_release_ex(lcname, 0);
  2338. }
  2339. /* }}} */
  2340. /* {{{ proto array get_extension_funcs(string extension_name)
  2341. Returns an array with the names of functions belonging to the named extension */
  2342. ZEND_FUNCTION(get_extension_funcs)
  2343. {
  2344. zend_string *extension_name;
  2345. zend_string *lcname;
  2346. int array;
  2347. zend_module_entry *module;
  2348. zend_function *zif;
  2349. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
  2350. return;
  2351. }
  2352. if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
  2353. lcname = zend_string_tolower(extension_name);
  2354. module = zend_hash_find_ptr(&module_registry, lcname);
  2355. zend_string_release_ex(lcname, 0);
  2356. } else {
  2357. module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
  2358. }
  2359. if (!module) {
  2360. RETURN_FALSE;
  2361. }
  2362. if (module->functions) {
  2363. /* avoid BC break, if functions list is empty, will return an empty array */
  2364. array_init(return_value);
  2365. array = 1;
  2366. } else {
  2367. array = 0;
  2368. }
  2369. ZEND_HASH_FOREACH_PTR(CG(function_table), zif) {
  2370. if (zif->common.type == ZEND_INTERNAL_FUNCTION
  2371. && zif->internal_function.module == module) {
  2372. if (!array) {
  2373. array_init(return_value);
  2374. array = 1;
  2375. }
  2376. add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
  2377. }
  2378. } ZEND_HASH_FOREACH_END();
  2379. if (!array) {
  2380. RETURN_FALSE;
  2381. }
  2382. }
  2383. /* }}} */
  2384. /*
  2385. * Local variables:
  2386. * tab-width: 4
  2387. * c-basic-offset: 4
  2388. * indent-tabs-mode: t
  2389. * End:
  2390. * vim600: sw=4 ts=4 fdm=marker
  2391. * vim<600: sw=4 ts=4
  2392. */