]> granicus.if.org Git - php/commitdiff
zend-test extension to house code that is required for testing internal APIs, but...
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 10 Mar 2017 23:33:32 +0000 (00:33 +0100)
committerJoe Watkins <krakjoe@php.net>
Sun, 12 Mar 2017 18:58:50 +0000 (18:58 +0000)
14 files changed:
Zend/tests/return_types/internal_functions001.phpt
Zend/tests/return_types/internal_functions002.phpt
Zend/zend_builtin_functions.c
appveyor/build_task.bat
ext/sockets/tests/socket_export_stream-5.phpt
ext/sockets/tests/socket_import_stream-5.phpt
ext/standard/tests/file/bug52820.phpt
ext/standard/tests/file/stream_enclosed.phpt
ext/standard/tests/url/parse_url_unterminated.phpt [new file with mode: 0644]
ext/zend_test/config.m4 [new file with mode: 0644]
ext/zend_test/config.w32 [new file with mode: 0644]
ext/zend_test/php_test.h [new file with mode: 0644]
ext/zend_test/test.c [new file with mode: 0644]
travis/compile.sh

index fffaf54574535eaefc3489d5c58ee5bdaf9abc00..5dfd2784da02326c34ae43eaf397821828bf16fa 100644 (file)
@@ -1,15 +1,14 @@
 --TEST--
 Return type for internal functions
-
 --SKIPIF--
 <?php
-if (!function_exists('zend_test_func')) {
-    print 'skip';
-}
-
+if (!function_exists('zend_test_array_return')) die('skip');
+// Internal function return types are only checked in debug builds
+if (!PHP_DEBUG) die('skip requires debug build');
+?>
 --FILE--
 <?php
-zend_test_func();
+zend_test_array_return();
 ?>
 --EXPECTF--
-Fatal error: Return value of zend_test_func() must be of the type array, null returned in %s on line %d
+Fatal error: Return value of zend_test_array_return() must be of the type array, null returned in %s on line %d
index 7cdb2b884a5d40547ec7106f647ae389910566ba..0daf3481c8e66974f73c9476ed5aab820f1c4d11 100644 (file)
@@ -1,16 +1,12 @@
 --TEST--
 Return type for internal functions 2
-
 --SKIPIF--
 <?php
-if (!function_exists('zend_test_func2')) {
-    print 'skip';
-}
-
+if (!function_exists('zend_test_nullable_array_return')) die('skip');
 --FILE--
 <?php
-zend_test_func2();
-echo "==DONE==\n"
+zend_test_nullable_array_return();
 ?>
---EXPECTF--
+==DONE==
+--EXPECT--
 ==DONE==
index 55d1209ae0e8d5850d0d3d05ed32323a864b66cb..7f6e46b73675ba7f93256c6f97138e798eda1524 100644 (file)
 #include "zend_closures.h"
 #include "zend_generators.h"
 
-#undef ZEND_TEST_EXCEPTIONS
-
-#if ZEND_DEBUG
-static zend_class_entry *zend_test_interface;
-static zend_class_entry *zend_test_class;
-static zend_class_entry *zend_test_trait;
-static zend_object_handlers zend_test_class_handlers;
-#endif
-
 static ZEND_FUNCTION(zend_version);
 static ZEND_FUNCTION(func_num_args);
 static ZEND_FUNCTION(func_get_arg);
@@ -61,13 +52,6 @@ static ZEND_FUNCTION(interface_exists);
 static ZEND_FUNCTION(trait_exists);
 static ZEND_FUNCTION(function_exists);
 static ZEND_FUNCTION(class_alias);
-#if ZEND_DEBUG
-static ZEND_FUNCTION(leak);
-static ZEND_FUNCTION(leak_variable);
-#ifdef ZEND_TEST_EXCEPTIONS
-static ZEND_FUNCTION(crash);
-#endif
-#endif
 static ZEND_FUNCTION(get_included_files);
 static ZEND_FUNCTION(is_subclass_of);
 static ZEND_FUNCTION(is_a);
@@ -93,13 +77,9 @@ static ZEND_FUNCTION(get_extension_funcs);
 static ZEND_FUNCTION(get_defined_constants);
 static ZEND_FUNCTION(debug_backtrace);
 static ZEND_FUNCTION(debug_print_backtrace);
-#if ZEND_DEBUG
-static ZEND_FUNCTION(zend_test_func);
-static ZEND_FUNCTION(zend_test_func2);
-#ifdef ZTS
+#if ZEND_DEBUG && defined(ZTS)
 static ZEND_FUNCTION(zend_thread_id);
 #endif
-#endif
 static ZEND_FUNCTION(gc_mem_caches);
 static ZEND_FUNCTION(gc_collect_cycles);
 static ZEND_FUNCTION(gc_enabled);
@@ -199,13 +179,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
        ZEND_ARG_INFO(0, autoload)
 ZEND_END_ARG_INFO()
 
-#if ZEND_DEBUG
-ZEND_BEGIN_ARG_INFO_EX(arginfo_leak_variable, 0, 0, 1)
-       ZEND_ARG_INFO(0, variable)
-       ZEND_ARG_INFO(0, leak_data)
-ZEND_END_ARG_INFO()
-#endif
-
 ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
        ZEND_ARG_INFO(0, message)
        ZEND_ARG_INFO(0, error_type)
@@ -255,70 +228,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
        ZEND_ARG_INFO(0, extension_name)
 ZEND_END_ARG_INFO()
 
-#if ZEND_DEBUG
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func, IS_ARRAY, 0)
-ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func2, IS_ARRAY, 1)
-ZEND_END_ARG_INFO()
-#endif
-
-/* }}} */
-
-#if ZEND_DEBUG
-static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
-       zend_object *obj = zend_objects_new(class_type);
-       obj->handlers = &zend_test_class_handlers;
-       return obj;
-}
-/* }}} */
-
-static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
-       zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
-       fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
-       fptr->num_args = 1;
-       fptr->arg_info = NULL;
-       fptr->scope = (*object)->ce;
-       fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
-       fptr->function_name = zend_string_copy(name);
-       fptr->handler = ZEND_FN(zend_test_func);
-       zend_set_function_arg_flags((zend_function*)fptr);
-
-       return (zend_function*)fptr;
-}
-/* }}} */
-
-static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
-       zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
-       fptr->type = ZEND_OVERLOADED_FUNCTION;
-       fptr->num_args = 1;
-       fptr->arg_info = NULL;
-       fptr->scope = ce;
-       fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
-       fptr->function_name = name;
-       fptr->handler = ZEND_FN(zend_test_func);
-       zend_set_function_arg_flags((zend_function*)fptr);
-
-       return (zend_function*)fptr;
-}
-/* }}} */
-
-static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ {
-       RETVAL_STR(zend_string_copy(method));
-       return 0;
-}
-/* }}} */
-
-static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
-       RETURN_TRUE;
-}
 /* }}} */
 
-static zend_function_entry zend_test_trait_methods[] = {
-    ZEND_ME(_ZendTestTrait, testMethod, arginfo_zend__void, ZEND_ACC_PUBLIC)
-    ZEND_FE_END
-};
-#endif
-
 static const zend_function_entry builtin_functions[] = { /* {{{ */
        ZEND_FE(zend_version,           arginfo_zend__void)
        ZEND_FE(func_num_args,          arginfo_zend__void)
@@ -343,13 +254,6 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
        ZEND_FE(trait_exists,           arginfo_trait_exists)
        ZEND_FE(function_exists,        arginfo_function_exists)
        ZEND_FE(class_alias,            arginfo_class_alias)
-#if ZEND_DEBUG
-       ZEND_FE(leak,                           NULL)
-       ZEND_FE(leak_variable,          arginfo_leak_variable)
-#ifdef ZEND_TEST_EXCEPTIONS
-       ZEND_FE(crash,                          NULL)
-#endif
-#endif
        ZEND_FE(get_included_files,     arginfo_zend__void)
        ZEND_FALIAS(get_required_files, get_included_files,             arginfo_zend__void)
        ZEND_FE(is_subclass_of,         arginfo_is_subclass_of)
@@ -377,12 +281,8 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
        ZEND_FE(get_defined_constants,          arginfo_get_defined_constants)
        ZEND_FE(debug_backtrace,                arginfo_debug_backtrace)
        ZEND_FE(debug_print_backtrace,          arginfo_debug_print_backtrace)
-#if ZEND_DEBUG
-       ZEND_FE(zend_test_func,         arginfo_zend_test_func)
-       ZEND_FE(zend_test_func2,        arginfo_zend_test_func2)
-#ifdef ZTS
+#if ZEND_DEBUG && defined(ZTS)
        ZEND_FE(zend_thread_id,         NULL)
-#endif
 #endif
        ZEND_FE(gc_mem_caches,      arginfo_zend__void)
        ZEND_FE(gc_collect_cycles,      arginfo_zend__void)
@@ -401,26 +301,6 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */
 
        zend_register_default_classes();
 
-#if ZEND_DEBUG
-       INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL);
-       zend_test_interface = zend_register_internal_interface(&class_entry);
-       zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
-       INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", NULL);
-       zend_test_class = zend_register_internal_class_ex(&class_entry, NULL);
-       zend_class_implements(zend_test_class, 1, zend_test_interface);
-       zend_test_class->create_object = zend_test_class_new;
-       zend_test_class->get_static_method = zend_test_class_static_method_get;
-
-       memcpy(&zend_test_class_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
-       zend_test_class_handlers.get_method = zend_test_class_method_get;
-       zend_test_class_handlers.call_method = zend_test_class_call_method;
-
-       INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
-       zend_test_trait = zend_register_internal_class(&class_entry);
-       zend_test_trait->ce_flags |= ZEND_ACC_TRAIT;
-       zend_declare_property_null(zend_test_trait, "testProp", sizeof("testProp")-1, ZEND_ACC_PUBLIC);
-#endif
-
        return SUCCESS;
 }
 /* }}} */
@@ -1653,63 +1533,6 @@ ZEND_FUNCTION(class_alias)
 }
 /* }}} */
 
-#if ZEND_DEBUG
-/* {{{ proto void leak([int num_bytes])
-   Cause an intentional memory leak, for testing/debugging purposes */
-ZEND_FUNCTION(leak)
-{
-       zend_long leakbytes = 3;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
-               return;
-       }
-
-       emalloc(leakbytes);
-}
-/* }}} */
-
-/* {{{ proto void leak_variable(mixed variable [, bool leak_data])
-   Leak a variable that is a resource or an object */
-ZEND_FUNCTION(leak_variable)
-{
-       zval *zv;
-       zend_bool leak_data = 0;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &zv, &leak_data) == FAILURE) {
-               return;
-       }
-
-       if (!leak_data) {
-               Z_ADDREF_P(zv);
-       } else if (Z_TYPE_P(zv) == IS_RESOURCE) {
-               Z_ADDREF_P(zv);
-       } else if (Z_TYPE_P(zv) == IS_OBJECT) {
-               Z_ADDREF_P(zv);
-       } else {
-               zend_error(E_WARNING, "Leaking non-zval data is only applicable to resources and objects");
-       }
-}
-/* }}} */
-
-
-#ifdef ZEND_TEST_EXCEPTIONS
-/* {{{ proto void crash(void)
-   Crash the script */
-ZEND_FUNCTION(crash)
-{
-       char *nowhere = NULL;
-
-       if (zend_parse_parameters_none() == FAILURE) {
-               return;
-       }
-
-       memcpy(nowhere, "something", sizeof("something"));
-}
-/* }}} */
-#endif
-
-#endif /* ZEND_DEBUG */
-
 /* {{{ proto array get_included_files(void)
    Returns an array with the file names that were include_once()'d */
 ZEND_FUNCTION(get_included_files)
@@ -2095,28 +1918,12 @@ ZEND_FUNCTION(create_function)
 }
 /* }}} */
 
-#if ZEND_DEBUG
-ZEND_FUNCTION(zend_test_func)
-{
-       zval *arg1, *arg2;
-
-       zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
-}
-
-ZEND_FUNCTION(zend_test_func2)
-{
-       zval *arg1, *arg2;
-
-       zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
-}
-
-#ifdef ZTS
+#if ZEND_DEBUG && defined(ZTS)
 ZEND_FUNCTION(zend_thread_id)
 {
        RETURN_LONG((zend_long)tsrm_thread_id());
 }
 #endif
-#endif
 
 /* {{{ proto string get_resource_type(resource res)
    Get the resource type name for a given resource */
index ad47854e0b1cea9cc1e34cfe1a4ede9ec72953d0..85a64e4fbd7003762b647f007c11b8077ecd19b8 100644 (file)
@@ -39,6 +39,7 @@ call configure.bat ^
        --enable-object-out-dir=%PHP_BUILD_OBJ_DIR% ^
        --with-php-build=%DEPS_DIR% ^
        %ADD_CONF% ^
+       --enable-zend-test ^
        --with-test-ini-ext-exclude=%EXT_EXCLUDE_FROM_TEST%
 if %errorlevel% neq 0 exit /b 3
 
index 732b2072d0b32ccca9e2876e51f7fb0b8297141a..db2d018d474d59d358b64635a1a5b09ed2cdd511 100644 (file)
@@ -5,7 +5,7 @@ socket_export_stream: effects of leaked handles
 if (!extension_loaded('sockets')) {
        die('SKIP sockets extension not available.');
 }
-if (!function_exists('leak_variable'))
+if (!function_exists('zend_leak_variable'))
        die('SKIP only for debug builds');
 --FILE--
 <?php
@@ -13,12 +13,12 @@ if (!function_exists('leak_variable'))
 $sock0 = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
 socket_bind($sock0, '0.0.0.0', 58380);
 $stream0 = socket_export_stream($sock0);
-leak_variable($stream0, true);
+zend_leak_variable($stream0);
 
 $sock1 = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
 socket_bind($sock1, '0.0.0.0', 58381);
 $stream1 = socket_export_stream($sock1);
-leak_variable($sock1, true);
+zend_leak_variable($sock1);
 
 echo "Done.\n";
 --EXPECT--
index d48531e4108bdadff1c85dd0252a6deda48cf6ff..0583f2e4c203670df321b54434ec00a28ffe3511 100644 (file)
@@ -5,18 +5,18 @@ socket_import_stream: effects of leaked handles
 if (!extension_loaded('sockets')) {
        die('SKIP sockets extension not available.');
 }
-if (!function_exists('leak_variable'))
+if (!function_exists('zend_leak_variable'))
        die('SKIP only for debug builds');
 --FILE--
 <?php
 
 $stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND);
 $sock0 = socket_import_stream($stream0);
-leak_variable($stream0, true);
+zend_leak_variable($stream0);
 
 $stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND);
 $sock1 = socket_import_stream($stream1);
-leak_variable($sock1, true);
+zend_leak_variable($sock1);
 
 echo "Done.\n";
 --EXPECT--
index a00ebf50b633c25a5116a105f9603945c8a7bce4..e51c27e457218313b9e5cf7070bb8ae9c73c42a0 100644 (file)
@@ -2,7 +2,7 @@
 Bug #52820 (writes to fopencookie FILE* not committed when seeking the stream)
 --SKIPIF--
 <?php
-if (!function_exists('leak_variable'))
+if (!function_exists('zend_leak_variable'))
    die("skip only for debug builds");
 /* unfortunately no standard function does a cast to FILE*, so we need
  * curl to test this */
@@ -33,10 +33,10 @@ echo "\nmemory stream (close after):\n";
 fclose(do_stuff("php://memory"));
 
 echo "\ntemp stream (leak):\n";
-leak_variable(do_stuff("php://temp"), true);
+zend_leak_variable(do_stuff("php://temp"));
 
 echo "\nmemory stream (leak):\n";
-leak_variable(do_stuff("php://memory"), true);
+zend_leak_variable(do_stuff("php://memory"));
 
 echo "\nDone.\n";
 --EXPECTF--
index f487ed07442e32e94e1a9b9a7038161a54b16902..ff764c8f81721975dc1315541fcac95b96f559fd 100644 (file)
@@ -2,7 +2,7 @@
 Unexposed/leaked stream encloses another stream
 --SKIPIF--
 <?php
-if (!function_exists('leak_variable')) die("skip only debug builds");
+if (!function_exists('zend_leak_variable')) die("skip only debug builds");
 --FILE--
 <?php
 $s = fopen('php://temp/maxmemory=1024','wb+');
@@ -15,6 +15,6 @@ while ($i++ < 5000) {
     fwrite($t, str_repeat('a',1024));
 }
 
-leak_variable($s, true);
-leak_variable($t, true);
+zend_leak_variable($s);
+zend_leak_variable($t);
 --EXPECT--
diff --git a/ext/standard/tests/url/parse_url_unterminated.phpt b/ext/standard/tests/url/parse_url_unterminated.phpt
new file mode 100644 (file)
index 0000000..bb0e096
--- /dev/null
@@ -0,0 +1,887 @@
+--TEST--
+Test parse_url() function: Parse unterminated string
+--SKIPIF--
+<?php
+if (!function_exists('zend_create_unterminated_string')) die('skip ext/test required');
+?>
+--FILE--
+<?php
+
+/*
+ * This is the same as the basic001 test, but with unterminated strings.
+ */
+
+include_once(dirname(__FILE__) . '/urls.inc');
+
+foreach ($urls as $url) {
+       echo "\n--> $url: ";
+       $str = zend_create_unterminated_string($url);
+       var_dump(parse_url($str));
+    zend_terminate_string($str);
+}
+
+echo "Done";
+?>
+--EXPECTF--
+
+--> 64.246.30.37: array(1) {
+  ["path"]=>
+  string(12) "64.246.30.37"
+}
+
+--> http://64.246.30.37: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(12) "64.246.30.37"
+}
+
+--> http://64.246.30.37/: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(12) "64.246.30.37"
+  ["path"]=>
+  string(1) "/"
+}
+
+--> 64.246.30.37/: array(1) {
+  ["path"]=>
+  string(13) "64.246.30.37/"
+}
+
+--> 64.246.30.37:80/: array(3) {
+  ["host"]=>
+  string(12) "64.246.30.37"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+}
+
+--> php.net: array(1) {
+  ["path"]=>
+  string(7) "php.net"
+}
+
+--> php.net/: array(1) {
+  ["path"]=>
+  string(8) "php.net/"
+}
+
+--> http://php.net: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(7) "php.net"
+}
+
+--> http://php.net/: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(7) "php.net"
+  ["path"]=>
+  string(1) "/"
+}
+
+--> www.php.net: array(1) {
+  ["path"]=>
+  string(11) "www.php.net"
+}
+
+--> www.php.net/: array(1) {
+  ["path"]=>
+  string(12) "www.php.net/"
+}
+
+--> http://www.php.net: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+}
+
+--> http://www.php.net/: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(1) "/"
+}
+
+--> www.php.net:80: array(2) {
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+}
+
+--> http://www.php.net:80: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+}
+
+--> http://www.php.net:80/: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+}
+
+--> http://www.php.net/index.php: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(10) "/index.php"
+}
+
+--> www.php.net/?: array(1) {
+  ["path"]=>
+  string(12) "www.php.net/"
+}
+
+--> www.php.net:80/?: array(3) {
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+}
+
+--> http://www.php.net/?: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(1) "/"
+}
+
+--> http://www.php.net:80/?: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+}
+
+--> http://www.php.net:80/index.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+}
+
+--> http://www.php.net:80/foo/bar/index.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(18) "/foo/bar/index.php"
+}
+
+--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(53) "/this/is/a/very/deep/directory/structure/and/file.php"
+}
+
+--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php?lots=1&of=2&parameters=3&too=4&here=5: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(53) "/this/is/a/very/deep/directory/structure/and/file.php"
+  ["query"]=>
+  string(37) "lots=1&of=2&parameters=3&too=4&here=5"
+}
+
+--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(45) "/this/is/a/very/deep/directory/structure/and/"
+}
+
+--> http://www.php.net:80/this/is/a/very/deep/directory/structure/and/file.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(53) "/this/is/a/very/deep/directory/structure/and/file.php"
+}
+
+--> http://www.php.net:80/this/../a/../deep/directory: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(28) "/this/../a/../deep/directory"
+}
+
+--> http://www.php.net:80/this/../a/../deep/directory/: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(29) "/this/../a/../deep/directory/"
+}
+
+--> http://www.php.net:80/this/is/a/very/deep/directory/../file.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(42) "/this/is/a/very/deep/directory/../file.php"
+}
+
+--> http://www.php.net:80/index.php: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+}
+
+--> http://www.php.net:80/index.php?: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+}
+
+--> http://www.php.net:80/#foo: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+  ["fragment"]=>
+  string(3) "foo"
+}
+
+--> http://www.php.net:80/?#: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+}
+
+--> http://www.php.net:80/?test=1: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+  ["query"]=>
+  string(6) "test=1"
+}
+
+--> http://www.php.net/?test=1&: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(1) "/"
+  ["query"]=>
+  string(7) "test=1&"
+}
+
+--> http://www.php.net:80/?&: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(1) "/"
+  ["query"]=>
+  string(1) "&"
+}
+
+--> http://www.php.net:80/index.php?test=1&: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(7) "test=1&"
+}
+
+--> http://www.php.net/index.php?&: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(1) "&"
+}
+
+--> http://www.php.net:80/index.php?foo&: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(4) "foo&"
+}
+
+--> http://www.php.net/index.php?&foo: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(4) "&foo"
+}
+
+--> http://www.php.net:80/index.php?test=1&test2=char&test3=mixesCI: array(5) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+}
+
+--> www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(5) {
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://secret@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["user"]=>
+  string(6) "secret"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["user"]=>
+  string(6) "secret"
+  ["pass"]=>
+  string(0) ""
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(8) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["user"]=>
+  string(0) ""
+  ["pass"]=>
+  string(7) "hideout"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["user"]=>
+  string(6) "secret"
+  ["pass"]=>
+  string(7) "hideout"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["user"]=>
+  string(14) "secret@hideout"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(8) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "www.php.net"
+  ["port"]=>
+  int(80)
+  ["user"]=>
+  string(6) "secret"
+  ["pass"]=>
+  string(7) "hid:out"
+  ["path"]=>
+  string(10) "/index.php"
+  ["query"]=>
+  string(31) "test=1&test2=char&test3=mixesCI"
+  ["fragment"]=>
+  string(16) "some_page_ref123"
+}
+
+--> nntp://news.php.net: array(2) {
+  ["scheme"]=>
+  string(4) "nntp"
+  ["host"]=>
+  string(12) "news.php.net"
+}
+
+--> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz: array(3) {
+  ["scheme"]=>
+  string(3) "ftp"
+  ["host"]=>
+  string(11) "ftp.gnu.org"
+  ["path"]=>
+  string(22) "/gnu/glic/glibc.tar.gz"
+}
+
+--> zlib:http://foo@bar: array(2) {
+  ["scheme"]=>
+  string(4) "zlib"
+  ["path"]=>
+  string(14) "http://foo@bar"
+}
+
+--> zlib:filename.txt: array(2) {
+  ["scheme"]=>
+  string(4) "zlib"
+  ["path"]=>
+  string(12) "filename.txt"
+}
+
+--> zlib:/path/to/my/file/file.txt: array(2) {
+  ["scheme"]=>
+  string(4) "zlib"
+  ["path"]=>
+  string(25) "/path/to/my/file/file.txt"
+}
+
+--> foo://foo@bar: array(3) {
+  ["scheme"]=>
+  string(3) "foo"
+  ["host"]=>
+  string(3) "bar"
+  ["user"]=>
+  string(3) "foo"
+}
+
+--> mailto:me@mydomain.com: array(2) {
+  ["scheme"]=>
+  string(6) "mailto"
+  ["path"]=>
+  string(15) "me@mydomain.com"
+}
+
+--> /foo.php?a=b&c=d: array(2) {
+  ["path"]=>
+  string(8) "/foo.php"
+  ["query"]=>
+  string(7) "a=b&c=d"
+}
+
+--> foo.php?a=b&c=d: array(2) {
+  ["path"]=>
+  string(7) "foo.php"
+  ["query"]=>
+  string(7) "a=b&c=d"
+}
+
+--> http://user:passwd@www.example.com:8080?bar=1&boom=0: array(6) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(15) "www.example.com"
+  ["port"]=>
+  int(8080)
+  ["user"]=>
+  string(4) "user"
+  ["pass"]=>
+  string(6) "passwd"
+  ["query"]=>
+  string(12) "bar=1&boom=0"
+}
+
+--> http://user_me-you:my_pas-word@www.example.com:8080?bar=1&boom=0: array(6) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(15) "www.example.com"
+  ["port"]=>
+  int(8080)
+  ["user"]=>
+  string(11) "user_me-you"
+  ["pass"]=>
+  string(11) "my_pas-word"
+  ["query"]=>
+  string(12) "bar=1&boom=0"
+}
+
+--> file:///path/to/file: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(13) "/path/to/file"
+}
+
+--> file://path/to/file: array(3) {
+  ["scheme"]=>
+  string(4) "file"
+  ["host"]=>
+  string(4) "path"
+  ["path"]=>
+  string(8) "/to/file"
+}
+
+--> file:/path/to/file: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(13) "/path/to/file"
+}
+
+--> http://1.2.3.4:/abc.asp?a=1&b=2: array(4) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(7) "1.2.3.4"
+  ["path"]=>
+  string(8) "/abc.asp"
+  ["query"]=>
+  string(7) "a=1&b=2"
+}
+
+--> http://foo.com#bar: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(7) "foo.com"
+  ["fragment"]=>
+  string(3) "bar"
+}
+
+--> scheme:: array(1) {
+  ["scheme"]=>
+  string(6) "scheme"
+}
+
+--> foo+bar://baz@bang/bla: array(4) {
+  ["scheme"]=>
+  string(7) "foo+bar"
+  ["host"]=>
+  string(4) "bang"
+  ["user"]=>
+  string(3) "baz"
+  ["path"]=>
+  string(4) "/bla"
+}
+
+--> gg:9130731: array(2) {
+  ["scheme"]=>
+  string(2) "gg"
+  ["path"]=>
+  string(7) "9130731"
+}
+
+--> http://user:@pass@host/path?argument?value#etc: array(7) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(4) "host"
+  ["user"]=>
+  string(4) "user"
+  ["pass"]=>
+  string(5) "@pass"
+  ["path"]=>
+  string(5) "/path"
+  ["query"]=>
+  string(14) "argument?value"
+  ["fragment"]=>
+  string(3) "etc"
+}
+
+--> http://10.10.10.10/:80: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(11) "10.10.10.10"
+  ["path"]=>
+  string(4) "/:80"
+}
+
+--> http://x:?: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(1) "x"
+}
+
+--> x:blah.com: array(2) {
+  ["scheme"]=>
+  string(1) "x"
+  ["path"]=>
+  string(8) "blah.com"
+}
+
+--> x:/blah.com: array(2) {
+  ["scheme"]=>
+  string(1) "x"
+  ["path"]=>
+  string(9) "/blah.com"
+}
+
+--> x://::abc/?: bool(false)
+
+--> http://::?: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(1) ":"
+}
+
+--> http://::#: array(2) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(1) ":"
+}
+
+--> x://::6.5: array(3) {
+  ["scheme"]=>
+  string(1) "x"
+  ["host"]=>
+  string(1) ":"
+  ["port"]=>
+  int(6)
+}
+
+--> http://?:/: bool(false)
+
+--> http://@?:/: bool(false)
+
+--> file:///:: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(2) "/:"
+}
+
+--> file:///a:/: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(3) "a:/"
+}
+
+--> file:///ab:/: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(5) "/ab:/"
+}
+
+--> file:///a:/: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(3) "a:/"
+}
+
+--> file:///@:/: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(3) "@:/"
+}
+
+--> file:///:80/: array(2) {
+  ["scheme"]=>
+  string(4) "file"
+  ["path"]=>
+  string(5) "/:80/"
+}
+
+--> []: array(1) {
+  ["path"]=>
+  string(2) "[]"
+}
+
+--> http://[x:80]/: array(3) {
+  ["scheme"]=>
+  string(4) "http"
+  ["host"]=>
+  string(6) "[x:80]"
+  ["path"]=>
+  string(1) "/"
+}
+
+--> : array(1) {
+  ["path"]=>
+  string(0) ""
+}
+
+--> /: array(1) {
+  ["path"]=>
+  string(1) "/"
+}
+
+--> /rest/Users?filter={"id":"123"}: array(2) {
+  ["path"]=>
+  string(11) "/rest/Users"
+  ["query"]=>
+  string(19) "filter={"id":"123"}"
+}
+
+--> http:///blah.com: bool(false)
+
+--> http://:80: bool(false)
+
+--> http://user@:80: bool(false)
+
+--> http://user:pass@:80: bool(false)
+
+--> http://:: bool(false)
+
+--> http://@/: bool(false)
+
+--> http://@:/: bool(false)
+
+--> http://:/: bool(false)
+
+--> http://?: bool(false)
+
+--> http://#: bool(false)
+
+--> http://?:: bool(false)
+
+--> http://:?: bool(false)
+
+--> http://blah.com:123456: bool(false)
+
+--> http://blah.com:abcdef: bool(false)
+Done
diff --git a/ext/zend_test/config.m4 b/ext/zend_test/config.m4
new file mode 100644 (file)
index 0000000..becefcd
--- /dev/null
@@ -0,0 +1,6 @@
+PHP_ARG_ENABLE(zend-test, whether to enable zend-test extension,
+[  --enable-zend-test           Enable zend-test extension])
+
+if test "$PHP_ZEND_TEST" != "no"; then
+  PHP_NEW_EXTENSION(zend_test, test.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
+fi
diff --git a/ext/zend_test/config.w32 b/ext/zend_test/config.w32
new file mode 100644 (file)
index 0000000..9b1574e
--- /dev/null
@@ -0,0 +1,8 @@
+// vim:ft=javascript
+
+ARG_ENABLE("zend-test", "enable zend-test extension", "no");
+
+if (PHP_ZEND_TEST != "no") {
+       EXTENSION("zend_test", "test.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
+}
+
diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h
new file mode 100644 (file)
index 0000000..fe8c5e4
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 7                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2017 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author:                                                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_TEST_H
+#define PHP_TEST_H
+
+extern zend_module_entry zend_test_module_entry;
+#define phpext_zend_test_ptr &zend_test_module_entry
+
+#define PHP_ZEND_TEST_VERSION "0.1.0"
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#if defined(ZTS) && defined(COMPILE_DL_ZEND_TEST)
+ZEND_TSRMLS_CACHE_EXTERN()
+#endif
+
+#endif
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
new file mode 100644 (file)
index 0000000..f203af8
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 7                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2017 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author:                                                              |
+  +----------------------------------------------------------------------+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_test.h"
+
+static zend_class_entry *zend_test_interface;
+static zend_class_entry *zend_test_class;
+static zend_class_entry *zend_test_trait;
+static zend_object_handlers zend_test_class_handlers;
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_array_return, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_nullable_array_return, IS_ARRAY, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_terminate_string, 0, 0, 1)
+       ZEND_ARG_INFO(1, str)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_leak_variable, 0, 0, 1)
+       ZEND_ARG_INFO(0, variable)
+ZEND_END_ARG_INFO()
+
+ZEND_FUNCTION(zend_test_func)
+{
+       /* dummy */
+}
+
+ZEND_FUNCTION(zend_test_array_return)
+{
+       zval *arg1, *arg2;
+
+       zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
+}
+
+ZEND_FUNCTION(zend_test_nullable_array_return)
+{
+       zval *arg1, *arg2;
+
+       zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
+}
+
+/* Create a string without terminating null byte. Must be termined with
+ * zend_terminate_string() before destruction, otherwise a warning is issued
+ * in debug builds. */
+ZEND_FUNCTION(zend_create_unterminated_string)
+{
+       zend_string *str, *res;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
+               return;
+       }
+
+       res = zend_string_alloc(ZSTR_LEN(str), 0);
+       memcpy(ZSTR_VAL(res), ZSTR_VAL(str), ZSTR_LEN(str));
+       /* No trailing null byte */
+
+       RETURN_STR(res);
+}
+
+/* Enforce terminate null byte on string. This avoids a warning in debug builds. */
+ZEND_FUNCTION(zend_terminate_string)
+{
+       zend_string *str;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
+               return;
+       }
+
+       ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
+}
+
+/* {{{ proto void zend_leak_bytes([int num_bytes])
+   Cause an intentional memory leak, for testing/debugging purposes */
+ZEND_FUNCTION(zend_leak_bytes)
+{
+       zend_long leakbytes = 3;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
+               return;
+       }
+
+       emalloc(leakbytes);
+}
+/* }}} */
+
+/* {{{ proto void zend_leak_variable(mixed variable)
+   Leak a refcounted variable */
+ZEND_FUNCTION(zend_leak_variable)
+{
+       zval *zv;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
+               return;
+       }
+
+       if (!Z_REFCOUNTED_P(zv)) {
+               zend_error(E_WARNING, "Cannot leak variable that is not refcounted");
+               return;
+       }
+
+       Z_ADDREF_P(zv);
+}
+/* }}} */
+
+static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
+       zend_object *obj = zend_objects_new(class_type);
+       obj->handlers = &zend_test_class_handlers;
+       return obj;
+}
+/* }}} */
+
+static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
+       zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
+       fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
+       fptr->num_args = 1;
+       fptr->arg_info = NULL;
+       fptr->scope = (*object)->ce;
+       fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
+       fptr->function_name = zend_string_copy(name);
+       fptr->handler = ZEND_FN(zend_test_func);
+       zend_set_function_arg_flags((zend_function*)fptr);
+
+       return (zend_function*)fptr;
+}
+/* }}} */
+
+static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
+       zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
+       fptr->type = ZEND_OVERLOADED_FUNCTION;
+       fptr->num_args = 1;
+       fptr->arg_info = NULL;
+       fptr->scope = ce;
+       fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
+       fptr->function_name = name;
+       fptr->handler = ZEND_FN(zend_test_func);
+       zend_set_function_arg_flags((zend_function*)fptr);
+
+       return (zend_function*)fptr;
+}
+/* }}} */
+
+static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ {
+       RETVAL_STR(zend_string_copy(method));
+       return 0;
+}
+/* }}} */
+
+static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
+       RETURN_TRUE;
+}
+/* }}} */
+
+static zend_function_entry zend_test_trait_methods[] = {
+    ZEND_ME(_ZendTestTrait, testMethod, NULL, ZEND_ACC_PUBLIC)
+    ZEND_FE_END
+};
+
+PHP_MINIT_FUNCTION(zend_test)
+{
+       zend_class_entry class_entry;
+
+       INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL);
+       zend_test_interface = zend_register_internal_interface(&class_entry);
+       zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
+       INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", NULL);
+       zend_test_class = zend_register_internal_class_ex(&class_entry, NULL);
+       zend_class_implements(zend_test_class, 1, zend_test_interface);
+       zend_test_class->create_object = zend_test_class_new;
+       zend_test_class->get_static_method = zend_test_class_static_method_get;
+
+       memcpy(&zend_test_class_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       zend_test_class_handlers.get_method = zend_test_class_method_get;
+       zend_test_class_handlers.call_method = zend_test_class_call_method;
+
+       INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
+       zend_test_trait = zend_register_internal_class(&class_entry);
+       zend_test_trait->ce_flags |= ZEND_ACC_TRAIT;
+       zend_declare_property_null(zend_test_trait, "testProp", sizeof("testProp")-1, ZEND_ACC_PUBLIC);
+       return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(zend_test)
+{
+       return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(zend_test)
+{
+#if defined(COMPILE_DL_ZEND_TEST) && defined(ZTS)
+       ZEND_TSRMLS_CACHE_UPDATE();
+#endif
+       return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(zend_test)
+{
+       return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(zend_test)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, "zend-test extension", "enabled");
+       php_info_print_table_end();
+}
+
+const zend_function_entry zend_test_functions[] = {
+       ZEND_FE(zend_test_array_return, arginfo_zend_test_array_return)
+       ZEND_FE(zend_test_nullable_array_return, arginfo_zend_test_nullable_array_return)
+       ZEND_FE(zend_create_unterminated_string, NULL)
+       ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string)
+       ZEND_FE(zend_leak_bytes, NULL)
+       ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable)
+       ZEND_FE_END
+};
+
+zend_module_entry zend_test_module_entry = {
+       STANDARD_MODULE_HEADER,
+       "test",
+       zend_test_functions,
+       PHP_MINIT(zend_test),
+       PHP_MSHUTDOWN(zend_test),
+       PHP_RINIT(zend_test),
+       PHP_RSHUTDOWN(zend_test),
+       PHP_MINFO(zend_test),
+       PHP_ZEND_TEST_VERSION,
+       STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_ZEND_TEST
+#ifdef ZTS
+ZEND_TSRMLS_CACHE_DEFINE()
+#endif
+ZEND_GET_MODULE(test)
+#endif
+
index 090cedae693f8ba1c5141201689945965af76833..bd127e716d8f62dc74f45b260bf29cce2066f5d0 100755 (executable)
@@ -58,6 +58,7 @@ $TS \
 --with-freetype-dir=/usr \
 --with-xpm-dir=/usr \
 --with-kerberos \
---enable-sysvmsg 
+--enable-sysvmsg \
+--enable-zend-test
 make -j2 --quiet
 make install