test.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/info.h"
  22. #include "php_test.h"
  23. #include "observer.h"
  24. #include "fiber.h"
  25. #include "zend_attributes.h"
  26. #include "zend_enum.h"
  27. #include "zend_interfaces.h"
  28. #include "zend_weakrefs.h"
  29. #include "Zend/Optimizer/zend_optimizer.h"
  30. #include "test_arginfo.h"
  31. ZEND_DECLARE_MODULE_GLOBALS(zend_test)
  32. static zend_class_entry *zend_test_interface;
  33. static zend_class_entry *zend_test_class;
  34. static zend_class_entry *zend_test_child_class;
  35. static zend_class_entry *zend_test_trait;
  36. static zend_class_entry *zend_test_attribute;
  37. static zend_class_entry *zend_test_parameter_attribute;
  38. static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
  39. static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
  40. static zend_class_entry *zend_test_ns_foo_class;
  41. static zend_class_entry *zend_test_ns2_foo_class;
  42. static zend_class_entry *zend_test_ns2_ns_foo_class;
  43. static zend_class_entry *zend_test_unit_enum;
  44. static zend_class_entry *zend_test_string_enum;
  45. static zend_object_handlers zend_test_class_handlers;
  46. static ZEND_FUNCTION(zend_test_func)
  47. {
  48. RETVAL_STR_COPY(EX(func)->common.function_name);
  49. /* Cleanup trampoline */
  50. ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
  51. zend_string_release(EX(func)->common.function_name);
  52. zend_free_trampoline(EX(func));
  53. EX(func) = NULL;
  54. }
  55. static ZEND_FUNCTION(zend_test_array_return)
  56. {
  57. ZEND_PARSE_PARAMETERS_NONE();
  58. }
  59. static ZEND_FUNCTION(zend_test_nullable_array_return)
  60. {
  61. ZEND_PARSE_PARAMETERS_NONE();
  62. }
  63. static ZEND_FUNCTION(zend_test_void_return)
  64. {
  65. /* dummy */
  66. ZEND_PARSE_PARAMETERS_NONE();
  67. }
  68. static void pass1(zend_script *script, void *context)
  69. {
  70. php_printf("pass1\n");
  71. }
  72. static void pass2(zend_script *script, void *context)
  73. {
  74. php_printf("pass2\n");
  75. }
  76. static ZEND_FUNCTION(zend_test_deprecated)
  77. {
  78. zval *arg1;
  79. zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg1);
  80. }
  81. /* Create a string without terminating null byte. Must be terminated with
  82. * zend_terminate_string() before destruction, otherwise a warning is issued
  83. * in debug builds. */
  84. static ZEND_FUNCTION(zend_create_unterminated_string)
  85. {
  86. zend_string *str, *res;
  87. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
  88. RETURN_THROWS();
  89. }
  90. res = zend_string_alloc(ZSTR_LEN(str), 0);
  91. memcpy(ZSTR_VAL(res), ZSTR_VAL(str), ZSTR_LEN(str));
  92. /* No trailing null byte */
  93. RETURN_STR(res);
  94. }
  95. /* Enforce terminate null byte on string. This avoids a warning in debug builds. */
  96. static ZEND_FUNCTION(zend_terminate_string)
  97. {
  98. zend_string *str;
  99. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
  100. RETURN_THROWS();
  101. }
  102. ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
  103. }
  104. /* Cause an intentional memory leak, for testing/debugging purposes */
  105. static ZEND_FUNCTION(zend_leak_bytes)
  106. {
  107. zend_long leakbytes = 3;
  108. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
  109. RETURN_THROWS();
  110. }
  111. emalloc(leakbytes);
  112. }
  113. /* Leak a refcounted variable */
  114. static ZEND_FUNCTION(zend_leak_variable)
  115. {
  116. zval *zv;
  117. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
  118. RETURN_THROWS();
  119. }
  120. if (!Z_REFCOUNTED_P(zv)) {
  121. zend_error(E_WARNING, "Cannot leak variable that is not refcounted");
  122. return;
  123. }
  124. Z_ADDREF_P(zv);
  125. }
  126. /* Tests Z_PARAM_OBJ_OR_STR */
  127. static ZEND_FUNCTION(zend_string_or_object)
  128. {
  129. zend_string *str;
  130. zend_object *object;
  131. ZEND_PARSE_PARAMETERS_START(1, 1)
  132. Z_PARAM_OBJ_OR_STR(object, str)
  133. ZEND_PARSE_PARAMETERS_END();
  134. if (str) {
  135. RETURN_STR_COPY(str);
  136. } else {
  137. RETURN_OBJ_COPY(object);
  138. }
  139. }
  140. /* Tests Z_PARAM_OBJ_OR_STR_OR_NULL */
  141. static ZEND_FUNCTION(zend_string_or_object_or_null)
  142. {
  143. zend_string *str;
  144. zend_object *object;
  145. ZEND_PARSE_PARAMETERS_START(1, 1)
  146. Z_PARAM_OBJ_OR_STR_OR_NULL(object, str)
  147. ZEND_PARSE_PARAMETERS_END();
  148. if (str) {
  149. RETURN_STR_COPY(str);
  150. } else if (object) {
  151. RETURN_OBJ_COPY(object);
  152. } else {
  153. RETURN_NULL();
  154. }
  155. }
  156. /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR */
  157. static ZEND_FUNCTION(zend_string_or_stdclass)
  158. {
  159. zend_string *str;
  160. zend_object *object;
  161. ZEND_PARSE_PARAMETERS_START(1, 1)
  162. Z_PARAM_OBJ_OF_CLASS_OR_STR(object, zend_standard_class_def, str)
  163. ZEND_PARSE_PARAMETERS_END();
  164. if (str) {
  165. RETURN_STR_COPY(str);
  166. } else {
  167. RETURN_OBJ_COPY(object);
  168. }
  169. }
  170. /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
  171. static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
  172. {
  173. zend_string *str;
  174. zend_object *object;
  175. ZEND_PARSE_PARAMETERS_START(1, 1)
  176. Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(object, zend_standard_class_def, str)
  177. ZEND_PARSE_PARAMETERS_END();
  178. if (str) {
  179. RETURN_STR_COPY(str);
  180. } else if (object) {
  181. RETURN_OBJ_COPY(object);
  182. } else {
  183. RETURN_NULL();
  184. }
  185. }
  186. static ZEND_FUNCTION(zend_weakmap_attach)
  187. {
  188. zval *value;
  189. zend_object *obj;
  190. ZEND_PARSE_PARAMETERS_START(2, 2)
  191. Z_PARAM_OBJ(obj)
  192. Z_PARAM_ZVAL(value)
  193. ZEND_PARSE_PARAMETERS_END();
  194. if (zend_weakrefs_hash_add(&ZT_G(global_weakmap), obj, value)) {
  195. Z_TRY_ADDREF_P(value);
  196. RETURN_TRUE;
  197. }
  198. RETURN_FALSE;
  199. }
  200. static ZEND_FUNCTION(zend_weakmap_remove)
  201. {
  202. zend_object *obj;
  203. ZEND_PARSE_PARAMETERS_START(1, 1)
  204. Z_PARAM_OBJ(obj)
  205. ZEND_PARSE_PARAMETERS_END();
  206. RETURN_BOOL(zend_weakrefs_hash_del(&ZT_G(global_weakmap), obj) == SUCCESS);
  207. }
  208. static ZEND_FUNCTION(zend_weakmap_dump)
  209. {
  210. ZEND_PARSE_PARAMETERS_NONE();
  211. RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap)));
  212. }
  213. static ZEND_FUNCTION(zend_get_current_func_name)
  214. {
  215. ZEND_PARSE_PARAMETERS_NONE();
  216. zend_string *function_name = get_function_or_method_name(EG(current_execute_data)->prev_execute_data->func);
  217. RETURN_STR(function_name);
  218. }
  219. /* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */
  220. static ZEND_FUNCTION(zend_iterable)
  221. {
  222. zval *arg1, *arg2;
  223. ZEND_PARSE_PARAMETERS_START(1, 2)
  224. Z_PARAM_ITERABLE(arg1)
  225. Z_PARAM_OPTIONAL
  226. Z_PARAM_ITERABLE_OR_NULL(arg2)
  227. ZEND_PARSE_PARAMETERS_END();
  228. }
  229. /* Call a method on a class or object using zend_call_method() */
  230. static ZEND_FUNCTION(zend_call_method)
  231. {
  232. zend_class_entry *ce = NULL;
  233. zend_string *method_name = NULL;
  234. zval *arg1 = NULL, *arg2 = NULL;
  235. int argc = ZEND_NUM_ARGS();
  236. ZEND_PARSE_PARAMETERS_START(2, 4)
  237. Z_PARAM_CLASS(ce)
  238. Z_PARAM_STR(method_name)
  239. Z_PARAM_OPTIONAL
  240. Z_PARAM_ZVAL(arg1)
  241. Z_PARAM_ZVAL(arg2)
  242. ZEND_PARSE_PARAMETERS_END();
  243. zend_call_method(NULL, ce, NULL, ZSTR_VAL(method_name), ZSTR_LEN(method_name), return_value, argc - 2, arg1, arg2);
  244. }
  245. static ZEND_FUNCTION(zend_get_unit_enum)
  246. {
  247. ZEND_PARSE_PARAMETERS_NONE();
  248. RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo"));
  249. }
  250. static ZEND_FUNCTION(namespaced_func)
  251. {
  252. ZEND_PARSE_PARAMETERS_NONE();
  253. RETURN_TRUE;
  254. }
  255. static ZEND_FUNCTION(zend_test_parameter_with_attribute)
  256. {
  257. zend_string *parameter;
  258. ZEND_PARSE_PARAMETERS_START(1, 1)
  259. Z_PARAM_STR(parameter)
  260. ZEND_PARSE_PARAMETERS_END();
  261. RETURN_LONG(1);
  262. }
  263. static zend_object *zend_test_class_new(zend_class_entry *class_type)
  264. {
  265. zend_object *obj = zend_objects_new(class_type);
  266. object_properties_init(obj, class_type);
  267. obj->handlers = &zend_test_class_handlers;
  268. return obj;
  269. }
  270. static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key)
  271. {
  272. if (zend_string_equals_literal_ci(name, "test")) {
  273. zend_internal_function *fptr;
  274. if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
  275. fptr = (zend_internal_function *) &EG(trampoline);
  276. } else {
  277. fptr = emalloc(sizeof(zend_internal_function));
  278. }
  279. memset(fptr, 0, sizeof(zend_internal_function));
  280. fptr->type = ZEND_INTERNAL_FUNCTION;
  281. fptr->num_args = 1;
  282. fptr->scope = (*object)->ce;
  283. fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
  284. fptr->function_name = zend_string_copy(name);
  285. fptr->handler = ZEND_FN(zend_test_func);
  286. return (zend_function*)fptr;
  287. }
  288. return zend_std_get_method(object, name, key);
  289. }
  290. static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name)
  291. {
  292. if (zend_string_equals_literal_ci(name, "test")) {
  293. zend_internal_function *fptr;
  294. if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
  295. fptr = (zend_internal_function *) &EG(trampoline);
  296. } else {
  297. fptr = emalloc(sizeof(zend_internal_function));
  298. }
  299. memset(fptr, 0, sizeof(zend_internal_function));
  300. fptr->type = ZEND_INTERNAL_FUNCTION;
  301. fptr->num_args = 1;
  302. fptr->scope = ce;
  303. fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
  304. fptr->function_name = zend_string_copy(name);
  305. fptr->handler = ZEND_FN(zend_test_func);
  306. return (zend_function*)fptr;
  307. }
  308. return zend_std_get_static_method(ce, name, NULL);
  309. }
  310. void zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope)
  311. {
  312. if (target != ZEND_ATTRIBUTE_TARGET_CLASS) {
  313. zend_error(E_COMPILE_ERROR, "Only classes can be marked with #[ZendTestAttribute]");
  314. }
  315. }
  316. static ZEND_METHOD(_ZendTestClass, __toString)
  317. {
  318. ZEND_PARSE_PARAMETERS_NONE();
  319. RETURN_EMPTY_STRING();
  320. }
  321. /* Internal function returns bool, we return int. */
  322. static ZEND_METHOD(_ZendTestClass, is_object)
  323. {
  324. ZEND_PARSE_PARAMETERS_NONE();
  325. RETURN_LONG(42);
  326. }
  327. static ZEND_METHOD(_ZendTestClass, returnsStatic) {
  328. ZEND_PARSE_PARAMETERS_NONE();
  329. object_init_ex(return_value, zend_get_called_scope(execute_data));
  330. }
  331. static ZEND_METHOD(_ZendTestClass, returnsThrowable)
  332. {
  333. ZEND_PARSE_PARAMETERS_NONE();
  334. zend_throw_error(NULL, "Dummy");
  335. }
  336. static ZEND_METHOD(_ZendTestChildClass, returnsThrowable)
  337. {
  338. ZEND_PARSE_PARAMETERS_NONE();
  339. zend_throw_error(NULL, "Dummy");
  340. }
  341. static ZEND_METHOD(_ZendTestTrait, testMethod)
  342. {
  343. ZEND_PARSE_PARAMETERS_NONE();
  344. RETURN_TRUE;
  345. }
  346. static ZEND_METHOD(ZendTestNS_Foo, method)
  347. {
  348. ZEND_PARSE_PARAMETERS_NONE();
  349. }
  350. static ZEND_METHOD(ZendTestNS2_Foo, method)
  351. {
  352. ZEND_PARSE_PARAMETERS_NONE();
  353. }
  354. static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method)
  355. {
  356. ZEND_PARSE_PARAMETERS_NONE();
  357. }
  358. static ZEND_METHOD(ZendTestParameterAttribute, __construct)
  359. {
  360. zend_string *parameter;
  361. ZEND_PARSE_PARAMETERS_START(1, 1)
  362. Z_PARAM_STR(parameter)
  363. ZEND_PARSE_PARAMETERS_END();
  364. ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
  365. }
  366. static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override)
  367. {
  368. zend_string *parameter;
  369. ZEND_PARSE_PARAMETERS_START(1, 1)
  370. Z_PARAM_STR(parameter)
  371. ZEND_PARSE_PARAMETERS_END();
  372. RETURN_LONG(2);
  373. }
  374. static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, override)
  375. {
  376. zend_string *parameter;
  377. ZEND_PARSE_PARAMETERS_START(1, 1)
  378. Z_PARAM_STR(parameter)
  379. ZEND_PARSE_PARAMETERS_END();
  380. RETURN_LONG(3);
  381. }
  382. static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override)
  383. {
  384. zend_string *parameter;
  385. ZEND_PARSE_PARAMETERS_START(1, 1)
  386. Z_PARAM_STR(parameter)
  387. ZEND_PARSE_PARAMETERS_END();
  388. RETURN_LONG(4);
  389. }
  390. PHP_INI_BEGIN()
  391. STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
  392. STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
  393. PHP_INI_END()
  394. void (*old_zend_execute_ex)(zend_execute_data *execute_data);
  395. static void custom_zend_execute_ex(zend_execute_data *execute_data)
  396. {
  397. old_zend_execute_ex(execute_data);
  398. }
  399. PHP_MINIT_FUNCTION(zend_test)
  400. {
  401. zend_test_interface = register_class__ZendTestInterface();
  402. zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
  403. zend_test_class = register_class__ZendTestClass(zend_test_interface);
  404. zend_test_class->create_object = zend_test_class_new;
  405. zend_test_class->get_static_method = zend_test_class_static_method_get;
  406. zend_test_child_class = register_class__ZendTestChildClass(zend_test_class);
  407. memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  408. zend_test_class_handlers.get_method = zend_test_class_method_get;
  409. zend_test_trait = register_class__ZendTestTrait();
  410. REGISTER_LONG_CONSTANT("ZEND_TEST_DEPRECATED", 42, CONST_PERSISTENT | CONST_DEPRECATED);
  411. zend_test_attribute = register_class_ZendTestAttribute();
  412. {
  413. zend_internal_attribute *attr = zend_internal_attribute_register(zend_test_attribute, ZEND_ATTRIBUTE_TARGET_ALL);
  414. attr->validator = zend_attribute_validate_zendtestattribute;
  415. }
  416. zend_test_parameter_attribute = register_class_ZendTestParameterAttribute();
  417. zend_internal_attribute_register(zend_test_parameter_attribute, ZEND_ATTRIBUTE_TARGET_PARAMETER);
  418. {
  419. zend_attribute *attr;
  420. attr = zend_add_parameter_attribute(
  421. zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1),
  422. 0,
  423. zend_test_parameter_attribute->name,
  424. 1
  425. );
  426. ZVAL_PSTRING(&attr->args[0].value, "value1");
  427. }
  428. zend_test_class_with_method_with_parameter_attribute = register_class_ZendTestClassWithMethodWithParameterAttribute();
  429. {
  430. zend_attribute *attr;
  431. attr = zend_add_parameter_attribute(
  432. zend_hash_str_find_ptr(&zend_test_class_with_method_with_parameter_attribute->function_table, "no_override", sizeof("no_override") - 1),
  433. 0,
  434. zend_test_parameter_attribute->name,
  435. 1
  436. );
  437. ZVAL_PSTRING(&attr->args[0].value, "value2");
  438. attr = zend_add_parameter_attribute(
  439. zend_hash_str_find_ptr(&zend_test_class_with_method_with_parameter_attribute->function_table, "override", sizeof("override") - 1),
  440. 0,
  441. zend_test_parameter_attribute->name,
  442. 1
  443. );
  444. ZVAL_PSTRING(&attr->args[0].value, "value3");
  445. }
  446. zend_test_child_class_with_method_with_parameter_attribute = register_class_ZendTestChildClassWithMethodWithParameterAttribute(zend_test_class_with_method_with_parameter_attribute);
  447. {
  448. zend_attribute *attr;
  449. attr = zend_add_parameter_attribute(
  450. zend_hash_str_find_ptr(&zend_test_child_class_with_method_with_parameter_attribute->function_table, "override", sizeof("override") - 1),
  451. 0,
  452. zend_test_parameter_attribute->name,
  453. 1
  454. );
  455. ZVAL_PSTRING(&attr->args[0].value, "value4");
  456. }
  457. zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
  458. zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
  459. zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();
  460. zend_test_unit_enum = register_class_ZendTestUnitEnum();
  461. zend_test_string_enum = register_class_ZendTestStringEnum();
  462. // Loading via dl() not supported with the observer API
  463. if (type != MODULE_TEMPORARY) {
  464. REGISTER_INI_ENTRIES();
  465. } else {
  466. (void)ini_entries;
  467. }
  468. if (ZT_G(replace_zend_execute_ex)) {
  469. old_zend_execute_ex = zend_execute_ex;
  470. zend_execute_ex = custom_zend_execute_ex;
  471. }
  472. if (ZT_G(register_passes)) {
  473. zend_optimizer_register_pass(pass1);
  474. zend_optimizer_register_pass(pass2);
  475. }
  476. zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU);
  477. zend_test_fiber_init();
  478. return SUCCESS;
  479. }
  480. PHP_MSHUTDOWN_FUNCTION(zend_test)
  481. {
  482. if (type != MODULE_TEMPORARY) {
  483. UNREGISTER_INI_ENTRIES();
  484. }
  485. zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
  486. return SUCCESS;
  487. }
  488. PHP_RINIT_FUNCTION(zend_test)
  489. {
  490. zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
  491. return SUCCESS;
  492. }
  493. PHP_RSHUTDOWN_FUNCTION(zend_test)
  494. {
  495. zend_ulong objptr;
  496. ZEND_HASH_FOREACH_NUM_KEY(&ZT_G(global_weakmap), objptr) {
  497. zend_weakrefs_hash_del(&ZT_G(global_weakmap), (zend_object *)(uintptr_t)objptr);
  498. } ZEND_HASH_FOREACH_END();
  499. zend_hash_destroy(&ZT_G(global_weakmap));
  500. return SUCCESS;
  501. }
  502. static PHP_GINIT_FUNCTION(zend_test)
  503. {
  504. #if defined(COMPILE_DL_ZEND_TEST) && defined(ZTS)
  505. ZEND_TSRMLS_CACHE_UPDATE();
  506. #endif
  507. memset(zend_test_globals, 0, sizeof(*zend_test_globals));
  508. }
  509. PHP_MINFO_FUNCTION(zend_test)
  510. {
  511. php_info_print_table_start();
  512. php_info_print_table_header(2, "zend_test extension", "enabled");
  513. php_info_print_table_end();
  514. DISPLAY_INI_ENTRIES();
  515. }
  516. zend_module_entry zend_test_module_entry = {
  517. STANDARD_MODULE_HEADER,
  518. "zend_test",
  519. ext_functions,
  520. PHP_MINIT(zend_test),
  521. PHP_MSHUTDOWN(zend_test),
  522. PHP_RINIT(zend_test),
  523. PHP_RSHUTDOWN(zend_test),
  524. PHP_MINFO(zend_test),
  525. PHP_ZEND_TEST_VERSION,
  526. PHP_MODULE_GLOBALS(zend_test),
  527. PHP_GINIT(zend_test),
  528. NULL,
  529. NULL,
  530. STANDARD_MODULE_PROPERTIES_EX
  531. };
  532. #ifdef COMPILE_DL_ZEND_TEST
  533. # ifdef ZTS
  534. ZEND_TSRMLS_CACHE_DEFINE()
  535. # endif
  536. ZEND_GET_MODULE(zend_test)
  537. #endif
  538. /* The important part here is the ZEND_FASTCALL. */
  539. PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len)
  540. {
  541. return (int) zend_atol(str, str_len);
  542. }
  543. PHP_ZEND_TEST_API struct bug79096 bug79096(void)
  544. {
  545. struct bug79096 b;
  546. b.a = 1;
  547. b.b = 1;
  548. return b;
  549. }
  550. PHP_ZEND_TEST_API void bug79532(off_t *array, size_t elems)
  551. {
  552. int i;
  553. for (i = 0; i < elems; i++) {
  554. array[i] = i;
  555. }
  556. }
  557. PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
  558. void bug79177(void)
  559. {
  560. bug79177_cb();
  561. }
  562. typedef struct bug80847_01 {
  563. uint64_t b;
  564. double c;
  565. } bug80847_01;
  566. typedef struct bug80847_02 {
  567. bug80847_01 a;
  568. } bug80847_02;
  569. PHP_ZEND_TEST_API bug80847_02 ffi_bug80847(bug80847_02 s) {
  570. s.a.b += 10;
  571. s.a.c -= 10.0;
  572. return s;
  573. }