summaryrefslogtreecommitdiff
path: root/src/sp_php_compat.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp_php_compat.h')
-rw-r--r--src/sp_php_compat.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/sp_php_compat.h b/src/sp_php_compat.h
new file mode 100644
index 0000000..04914b4
--- /dev/null
+++ b/src/sp_php_compat.h
@@ -0,0 +1,139 @@
1/* code in this file is licensed under its original license
2The PHP License, version 3.01 (https://www.php.net/license/3_01.txt)
3which is also included with these sources in the file `PHP_LICENSE` */
4
5#if PHP_VERSION_ID < 80000
6
7// copied from PHP 8.0.9 sources
8ZEND_API zend_string *zend_string_concat2(
9 const char *str1, size_t str1_len,
10 const char *str2, size_t str2_len);
11
12#define ZEND_HASH_REVERSE_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \
13 ZEND_HASH_REVERSE_FOREACH(ht, 0); \
14 _h = _p->h; \
15 _key = _p->key; \
16 _ptr = Z_PTR_P(_z);
17
18// zend_result was introduced to replace ZEND_RESULT_CODE with PHP8
19typedef ZEND_RESULT_CODE zend_result;
20
21#endif
22
23#if PHP_VERSION_ID < 70300
24
25// copied from PHP 7.4.22 sources
26
27static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
28 ZEND_ASSERT(p->refcount > 0);
29 // ZEND_RC_MOD_CHECK(p);
30 return --(p->refcount);
31}
32#define GC_DELREF(p) zend_gc_delref(&(p)->gc)
33
34static zend_always_inline void zend_string_release_ex(zend_string *s, int persistent)
35{
36 if (!ZSTR_IS_INTERNED(s)) {
37 if (GC_DELREF(s) == 0) {
38 if (persistent) {
39 ZEND_ASSERT(GC_FLAGS(s) & IS_STR_PERSISTENT);
40 free(s);
41 } else {
42 ZEND_ASSERT(!(GC_FLAGS(s) & IS_STR_PERSISTENT));
43 efree(s);
44 }
45 }
46 }
47}
48
49static zend_always_inline void zend_string_efree(zend_string *s)
50{
51 ZEND_ASSERT(!ZSTR_IS_INTERNED(s));
52 ZEND_ASSERT(GC_REFCOUNT(s) <= 1);
53 ZEND_ASSERT(!(GC_FLAGS(s) & IS_STR_PERSISTENT));
54 efree(s);
55}
56
57#endif
58
59#if PHP_VERSION_ID < 70200
60
61#undef ZEND_HASH_REVERSE_FOREACH
62
63// copied from PHP 7.4.22 sources
64
65#define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \
66 HashTable *__ht = (_ht); \
67 uint32_t _idx = __ht->nNumUsed; \
68 Bucket *_p = __ht->arData + _idx; \
69 zval *_z; \
70 for (_idx = __ht->nNumUsed; _idx > 0; _idx--) { \
71 _p--; \
72 _z = &_p->val; \
73 if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
74 _z = Z_INDIRECT_P(_z); \
75 } \
76 if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue;
77
78
79#define ZEND_HASH_FOREACH_END_DEL() \
80 __ht->nNumOfElements--; \
81 do { \
82 uint32_t j = HT_IDX_TO_HASH(_idx - 1); \
83 uint32_t nIndex = _p->h | __ht->nTableMask; \
84 uint32_t i = HT_HASH(__ht, nIndex); \
85 if (UNEXPECTED(j != i)) { \
86 Bucket *prev = HT_HASH_TO_BUCKET(__ht, i); \
87 while (Z_NEXT(prev->val) != j) { \
88 i = Z_NEXT(prev->val); \
89 prev = HT_HASH_TO_BUCKET(__ht, i); \
90 } \
91 Z_NEXT(prev->val) = Z_NEXT(_p->val); \
92 } else { \
93 HT_HASH(__ht, nIndex) = Z_NEXT(_p->val); \
94 } \
95 } while (0); \
96 } \
97 __ht->nNumUsed = _idx; \
98 } while (0)
99
100#endif
101
102// copied from PHP 8.0.11 sources, ext/hash/hash.c
103// slightly modified for PHP 8.1 compatibility
104
105static inline void php_hash_string_xor_char(unsigned char *out, const unsigned char *in, const unsigned char xor_with, const size_t length) {
106 size_t i;
107 for (i=0; i < length; i++) {
108 out[i] = in[i] ^ xor_with;
109 }
110}
111
112static inline void php_hash_hmac_prep_key(unsigned char *K, const php_hash_ops *ops, void *context, const unsigned char *key, const size_t key_len) {
113 memset(K, 0, ops->block_size);
114 if (key_len > ops->block_size) {
115 /* Reduce the key first */
116#if PHP_VERSION_ID < 80100
117 ops->hash_init(context);
118#else
119 ops->hash_init(context, NULL);
120#endif
121 ops->hash_update(context, key, key_len);
122 ops->hash_final(K, context);
123 } else {
124 memcpy(K, key, key_len);
125 }
126 /* XOR the key with 0x36 to get the ipad) */
127 php_hash_string_xor_char(K, K, 0x36, ops->block_size);
128}
129
130static inline void php_hash_hmac_round(unsigned char *final, const php_hash_ops *ops, void *context, const unsigned char *key, const unsigned char *data, const zend_long data_size) {
131#if PHP_VERSION_ID < 80100
132 ops->hash_init(context);
133#else
134 ops->hash_init(context, NULL);
135#endif
136 ops->hash_update(context, key, ops->block_size);
137 ops->hash_update(context, data, data_size);
138 ops->hash_final(final, context);
139}