1 /*
2 +----------------------------------------------------------------------+
3 | Compatibility macros for different PHP versions |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2016 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Adam Harvey <aharvey@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifndef _COMPAT_ZEND_RESOURCE_H
20 #define _COMPAT_ZEND_RESOURCE_H
21
22 /*
23 * The PHP 5 and PHP 7 resource APIs use the same function names for mutually
24 * incompatible functions, which is unfortunate. A simple version of the PHP 5
25 * macro API can be implemented on top of the PHP 7 API, but not vice versa
26 * (since, for example, zend_register_resource() in PHP 5 also sets the zval,
27 * which is a separate action in PHP 7).
28 *
29 * Instead of using preprocessor trickery to try to mangle things into a sane
30 * API, I've implemented a minimal API that supports basic resource handling
31 * and delegates appropriately on both versions.
32 *
33 * Destructors should be registered using the normal
34 * zend_register_list_destructors() or zend_register_list_destructors_ex()
35 * functions. The destructor function should take a "zend_resource *" (there is
36 * an appropriate typedef in the PHP 5 section to make this work); as only a
37 * subset of fields are available across PHP versions, this should be treated
38 * as this struct in effect:
39 *
40 * typedef struct {
41 * void *ptr;
42 * int type;
43 * } zend_resource;
44 *
45 * Accessing other fields will likely result in compilation errors and/or
46 * segfaults.
47 */
48
49 /**
50 * Deletes the resource.
51 *
52 * On PHP 5, this is equivalent to zend_list_delete(Z_LVAL_P(zv)).
53 * On PHP 7, this is equivalent to zend_list_close(Z_RES_P(zv)).
54 *
55 * @param zv The IS_RESOURCE zval to delete.
56 */
57 static void compat_zend_delete_resource(const zval *zv);
58
59 /**
60 * Fetches the resource.
61 *
62 * This API does not support the default ID that's possible with the PHP 5
63 * zend_fetch_resource() API, and will always set that value to -1.
64 *
65 * @param zv The IS_RESOURCE zval to fetch.
66 * @param rsrc_type_name The type name to use in error messages.
67 * @param rsrc_type The resource type ID.
68 * @return A void pointer to the resource, which needs to be typecast, or NULL
69 * on error.
70 */
71 static void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type);
72
73 /**
74 * Registers a new resource.
75 *
76 * @param zv The zval to set to IS_RESOURCE with the new resource value.
77 * @param ptr A void pointer to the resource.
78 * @param rsrc_type The resource type ID.
79 */
80 static void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type);
81
82 #ifdef PHP_7
83 /*============================================================================*/
84
compat_zend_delete_resource(const zval * zv)85 static void compat_zend_delete_resource(const zval *zv)
86 {
87 if (IS_RESOURCE != Z_TYPE_P(zv)) {
88 return;
89 }
90
91 zend_list_close(Z_RES_P(zv));
92 }
93
compat_zend_fetch_resource(zval * zv,const char * rsrc_type_name,int rsrc_type)94 static void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type)
95 {
96 if (IS_RESOURCE != Z_TYPE_P(zv)) {
97 return NULL;
98 }
99
100 return zend_fetch_resource(Z_RES_P(zv), rsrc_type_name, rsrc_type);
101 }
102
compat_zend_register_resource(zval * zv,void * ptr,int rsrc_type)103 static void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type)
104 {
105 ZVAL_RES(zv, zend_register_resource(ptr, rsrc_type));
106 }
107
108 #else
109 /*== PHP 5 ===================================================================*/
110
111 /* Used for destructors. */
112 typedef zend_rsrc_list_entry zend_resource;
113
compat_zend_delete_resource(const zval * zv)114 static void compat_zend_delete_resource(const zval *zv)
115 {
116 if (IS_RESOURCE != Z_TYPE_P(zv)) {
117 return;
118 }
119
120 zend_list_delete(Z_LVAL_P(zv));
121 }
122
compat_zend_fetch_resource(zval * zv,const char * rsrc_type_name,int rsrc_type)123 static void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type)
124 {
125 #if ZEND_MODULE_API_NO >= 20100412
126 return zend_fetch_resource(&zv, -1, rsrc_type_name, NULL, 1, rsrc_type);
127 #else
128 return zend_fetch_resource(&zv, -1, (char *)rsrc_type_name, NULL, 1, rsrc_type);
129 #endif
130 }
131
compat_zend_register_resource(zval * zv,void * ptr,int rsrc_type)132 static void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type)
133 {
134 ZEND_REGISTER_RESOURCE(zv, ptr, rsrc_type);
135 }
136
137 #endif /* PHP_7 */
138 /*============================================================================*/
139
140 #endif /* _COMPAT_ZEND_RESOURCE_H */
141