Skip to content

Commit cb7a784

Browse files
committed
Make HashContexts serializable.
* Modify php_hash_ops to contain the algorithm name and serialize and unserialize methods. * Implement __serialize and __unserialize magic methods on HashContext. Note that serialized HashContexts are not necessarily portable between PHP versions or from architecture to architecture. (Most are, but fast SHA3s are not necessarily.) A ValueError is thrown when an unsupported serialization is attempted. Because of security concerns, HASH_HMAC contexts are not currently serializable; attempting to serialize one throws an error. Serialization exposes the state of HashContext memory, so ensure that memory is zeroed before use by allocating it with a new php_hash_alloc_context function. Performance impact is negligible.
1 parent 15d2b65 commit cb7a784

36 files changed

+1294
-51
lines changed

ext/hash/hash.c

+356-9
Large diffs are not rendered by default.

ext/hash/hash.stub.php

+4
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,8 @@ function mhash(int $hash, string $data, string $key = UNKNOWN): string|false {}
5353
final class HashContext
5454
{
5555
private function __construct() {}
56+
57+
public function __serialize(): array {}
58+
59+
public function __unserialize(array $serialized): void {}
5660
}

ext/hash/hash_adler32.c

+4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ PHP_HASH_API int PHP_ADLER32Copy(const php_hash_ops *ops, PHP_ADLER32_CTX *orig_
5959
}
6060

6161
const php_hash_ops php_hash_adler32_ops = {
62+
"adler32",
6263
(php_hash_init_func_t) PHP_ADLER32Init,
6364
(php_hash_update_func_t) PHP_ADLER32Update,
6465
(php_hash_final_func_t) PHP_ADLER32Final,
6566
(php_hash_copy_func_t) PHP_ADLER32Copy,
67+
php_hash_serialize,
68+
php_hash_unserialize,
69+
PHP_ADLER32_SPEC,
6670
4, /* what to say here? */
6771
4,
6872
sizeof(PHP_ADLER32_CTX),

ext/hash/hash_arginfo.h

+10
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ ZEND_END_ARG_INFO()
117117
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_HashContext___construct, 0, 0, 0)
118118
ZEND_END_ARG_INFO()
119119

120+
#define arginfo_class_HashContext___serialize arginfo_hash_algos
121+
122+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_HashContext___unserialize, 0, 1, IS_VOID, 0)
123+
ZEND_ARG_TYPE_INFO(0, serialized, IS_ARRAY, 0)
124+
ZEND_END_ARG_INFO()
125+
120126

121127
ZEND_FUNCTION(hash);
122128
ZEND_FUNCTION(hash_file);
@@ -149,6 +155,8 @@ ZEND_FUNCTION(mhash_count);
149155
ZEND_FUNCTION(mhash);
150156
#endif
151157
ZEND_METHOD(HashContext, __construct);
158+
ZEND_METHOD(HashContext, __serialize);
159+
ZEND_METHOD(HashContext, __unserialize);
152160

153161

154162
static const zend_function_entry ext_functions[] = {
@@ -188,5 +196,7 @@ static const zend_function_entry ext_functions[] = {
188196

189197
static const zend_function_entry class_HashContext_methods[] = {
190198
ZEND_ME(HashContext, __construct, arginfo_class_HashContext___construct, ZEND_ACC_PRIVATE)
199+
ZEND_ME(HashContext, __serialize, arginfo_class_HashContext___serialize, ZEND_ACC_PUBLIC)
200+
ZEND_ME(HashContext, __unserialize, arginfo_class_HashContext___unserialize, ZEND_ACC_PUBLIC)
191201
ZEND_FE_END
192202
};

ext/hash/hash_crc32.c

+12
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,44 @@ PHP_HASH_API int PHP_CRC32Copy(const php_hash_ops *ops, PHP_CRC32_CTX *orig_cont
7878
}
7979

8080
const php_hash_ops php_hash_crc32_ops = {
81+
"crc32",
8182
(php_hash_init_func_t) PHP_CRC32Init,
8283
(php_hash_update_func_t) PHP_CRC32Update,
8384
(php_hash_final_func_t) PHP_CRC32LEFinal,
8485
(php_hash_copy_func_t) PHP_CRC32Copy,
86+
php_hash_serialize,
87+
php_hash_unserialize,
88+
PHP_CRC32_SPEC,
8589
4, /* what to say here? */
8690
4,
8791
sizeof(PHP_CRC32_CTX),
8892
0
8993
};
9094

9195
const php_hash_ops php_hash_crc32b_ops = {
96+
"crc32b",
9297
(php_hash_init_func_t) PHP_CRC32Init,
9398
(php_hash_update_func_t) PHP_CRC32BUpdate,
9499
(php_hash_final_func_t) PHP_CRC32BEFinal,
95100
(php_hash_copy_func_t) PHP_CRC32Copy,
101+
php_hash_serialize,
102+
php_hash_unserialize,
103+
PHP_CRC32_SPEC,
96104
4, /* what to say here? */
97105
4,
98106
sizeof(PHP_CRC32_CTX),
99107
0
100108
};
101109

102110
const php_hash_ops php_hash_crc32c_ops = {
111+
"crc32c",
103112
(php_hash_init_func_t) PHP_CRC32Init,
104113
(php_hash_update_func_t) PHP_CRC32CUpdate,
105114
(php_hash_final_func_t) PHP_CRC32BEFinal,
106115
(php_hash_copy_func_t) PHP_CRC32Copy,
116+
php_hash_serialize,
117+
php_hash_unserialize,
118+
PHP_CRC32_SPEC,
107119
4, /* what to say here? */
108120
4,
109121
sizeof(PHP_CRC32_CTX),

ext/hash/hash_fnv.c

+22-6
Original file line numberDiff line numberDiff line change
@@ -21,43 +21,59 @@
2121
#include "php_hash_fnv.h"
2222

2323
const php_hash_ops php_hash_fnv132_ops = {
24+
"fnv132",
2425
(php_hash_init_func_t) PHP_FNV132Init,
2526
(php_hash_update_func_t) PHP_FNV132Update,
2627
(php_hash_final_func_t) PHP_FNV132Final,
27-
(php_hash_copy_func_t) php_hash_copy,
28+
php_hash_copy,
29+
php_hash_serialize,
30+
php_hash_unserialize,
31+
PHP_FNV132_SPEC,
2832
4,
2933
4,
3034
sizeof(PHP_FNV132_CTX),
3135
0
3236
};
3337

3438
const php_hash_ops php_hash_fnv1a32_ops = {
39+
"fnv1a32",
3540
(php_hash_init_func_t) PHP_FNV132Init,
3641
(php_hash_update_func_t) PHP_FNV1a32Update,
37-
(php_hash_final_func_t) PHP_FNV132Final,
38-
(php_hash_copy_func_t) php_hash_copy,
42+
(php_hash_final_func_t) PHP_FNV132Final,
43+
php_hash_copy,
44+
php_hash_serialize,
45+
php_hash_unserialize,
46+
PHP_FNV132_SPEC,
3947
4,
4048
4,
4149
sizeof(PHP_FNV132_CTX),
4250
0
4351
};
4452

4553
const php_hash_ops php_hash_fnv164_ops = {
54+
"fnv164",
4655
(php_hash_init_func_t) PHP_FNV164Init,
4756
(php_hash_update_func_t) PHP_FNV164Update,
4857
(php_hash_final_func_t) PHP_FNV164Final,
49-
(php_hash_copy_func_t) php_hash_copy,
58+
php_hash_copy,
59+
php_hash_serialize,
60+
php_hash_unserialize,
61+
PHP_FNV164_SPEC,
5062
8,
5163
4,
5264
sizeof(PHP_FNV164_CTX),
5365
0
5466
};
5567

5668
const php_hash_ops php_hash_fnv1a64_ops = {
69+
"fnv1a64",
5770
(php_hash_init_func_t) PHP_FNV164Init,
5871
(php_hash_update_func_t) PHP_FNV1a64Update,
59-
(php_hash_final_func_t) PHP_FNV164Final,
60-
(php_hash_copy_func_t) php_hash_copy,
72+
(php_hash_final_func_t) PHP_FNV164Final,
73+
php_hash_copy,
74+
php_hash_serialize,
75+
php_hash_unserialize,
76+
PHP_FNV164_SPEC,
6177
8,
6278
4,
6379
sizeof(PHP_FNV164_CTX),

ext/hash/hash_gost.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -305,21 +305,29 @@ PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context)
305305
}
306306

307307
const php_hash_ops php_hash_gost_ops = {
308+
"gost",
308309
(php_hash_init_func_t) PHP_GOSTInit,
309310
(php_hash_update_func_t) PHP_GOSTUpdate,
310311
(php_hash_final_func_t) PHP_GOSTFinal,
311-
(php_hash_copy_func_t) php_hash_copy,
312+
php_hash_copy,
313+
php_hash_serialize,
314+
php_hash_unserialize,
315+
PHP_GOST_SPEC,
312316
32,
313317
32,
314318
sizeof(PHP_GOST_CTX),
315319
1
316320
};
317321

318322
const php_hash_ops php_hash_gost_crypto_ops = {
323+
"gost-crypto",
319324
(php_hash_init_func_t) PHP_GOSTInitCrypto,
320325
(php_hash_update_func_t) PHP_GOSTUpdate,
321326
(php_hash_final_func_t) PHP_GOSTFinal,
322-
(php_hash_copy_func_t) php_hash_copy,
327+
php_hash_copy,
328+
php_hash_serialize,
329+
php_hash_unserialize,
330+
PHP_GOST_SPEC,
323331
32,
324332
32,
325333
sizeof(PHP_GOST_CTX),

ext/hash/hash_haval.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,14 @@ static void PHP_5HAVALTransform(uint32_t state[8], const unsigned char block[128
247247

248248
#define PHP_HASH_HAVAL_INIT(p,b) \
249249
const php_hash_ops php_hash_##p##haval##b##_ops = { \
250+
"haval" #b "," #p, \
250251
(php_hash_init_func_t) PHP_##p##HAVAL##b##Init, \
251252
(php_hash_update_func_t) PHP_HAVALUpdate, \
252253
(php_hash_final_func_t) PHP_HAVAL##b##Final, \
253-
(php_hash_copy_func_t) php_hash_copy, \
254+
php_hash_copy, \
255+
php_hash_serialize, \
256+
php_hash_unserialize, \
257+
PHP_HAVAL_SPEC, \
254258
((b) / 8), 128, sizeof(PHP_HAVAL_CTX), 1 }; \
255259
PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *context) \
256260
{ int i; context->count[0] = context->count[1] = 0; \

ext/hash/hash_joaat.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@
2222
#include "php_hash_joaat.h"
2323

2424
const php_hash_ops php_hash_joaat_ops = {
25+
"joaat",
2526
(php_hash_init_func_t) PHP_JOAATInit,
2627
(php_hash_update_func_t) PHP_JOAATUpdate,
2728
(php_hash_final_func_t) PHP_JOAATFinal,
28-
(php_hash_copy_func_t) php_hash_copy,
29+
php_hash_copy,
30+
php_hash_serialize,
31+
php_hash_unserialize,
32+
PHP_JOAAT_SPEC,
2933
4,
3034
4,
3135
sizeof(PHP_JOAAT_CTX),

ext/hash/hash_md.c

+15-3
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,44 @@
1818
#include "php_hash_md.h"
1919

2020
const php_hash_ops php_hash_md5_ops = {
21+
"md5",
2122
(php_hash_init_func_t) PHP_MD5Init,
2223
(php_hash_update_func_t) PHP_MD5Update,
2324
(php_hash_final_func_t) PHP_MD5Final,
24-
(php_hash_copy_func_t) php_hash_copy,
25+
php_hash_copy,
26+
php_hash_serialize,
27+
php_hash_unserialize,
28+
PHP_MD5_SPEC,
2529
16,
2630
64,
2731
sizeof(PHP_MD5_CTX),
2832
1
2933
};
3034

3135
const php_hash_ops php_hash_md4_ops = {
36+
"md4",
3237
(php_hash_init_func_t) PHP_MD4Init,
3338
(php_hash_update_func_t) PHP_MD4Update,
3439
(php_hash_final_func_t) PHP_MD4Final,
35-
(php_hash_copy_func_t) php_hash_copy,
40+
php_hash_copy,
41+
php_hash_serialize,
42+
php_hash_unserialize,
43+
PHP_MD4_SPEC,
3644
16,
3745
64,
3846
sizeof(PHP_MD4_CTX),
3947
1
4048
};
4149

4250
const php_hash_ops php_hash_md2_ops = {
51+
"md2",
4352
(php_hash_init_func_t) PHP_MD2Init,
4453
(php_hash_update_func_t) PHP_MD2Update,
4554
(php_hash_final_func_t) PHP_MD2Final,
46-
(php_hash_copy_func_t) php_hash_copy,
55+
php_hash_copy,
56+
php_hash_serialize,
57+
php_hash_unserialize,
58+
PHP_MD2_SPEC,
4759
16,
4860
16,
4961
sizeof(PHP_MD2_CTX),

ext/hash/hash_ripemd.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,59 @@
2222
#include "php_hash_ripemd.h"
2323

2424
const php_hash_ops php_hash_ripemd128_ops = {
25+
"ripemd128",
2526
(php_hash_init_func_t) PHP_RIPEMD128Init,
2627
(php_hash_update_func_t) PHP_RIPEMD128Update,
2728
(php_hash_final_func_t) PHP_RIPEMD128Final,
28-
(php_hash_copy_func_t) php_hash_copy,
29+
php_hash_copy,
30+
php_hash_serialize,
31+
php_hash_unserialize,
32+
PHP_RIPEMD128_SPEC,
2933
16,
3034
64,
3135
sizeof(PHP_RIPEMD128_CTX),
3236
1
3337
};
3438

3539
const php_hash_ops php_hash_ripemd160_ops = {
40+
"ripemd160",
3641
(php_hash_init_func_t) PHP_RIPEMD160Init,
3742
(php_hash_update_func_t) PHP_RIPEMD160Update,
3843
(php_hash_final_func_t) PHP_RIPEMD160Final,
39-
(php_hash_copy_func_t) php_hash_copy,
44+
php_hash_copy,
45+
php_hash_serialize,
46+
php_hash_unserialize,
47+
PHP_RIPEMD160_SPEC,
4048
20,
4149
64,
4250
sizeof(PHP_RIPEMD160_CTX),
4351
1
4452
};
4553

4654
const php_hash_ops php_hash_ripemd256_ops = {
55+
"ripemd256",
4756
(php_hash_init_func_t) PHP_RIPEMD256Init,
4857
(php_hash_update_func_t) PHP_RIPEMD256Update,
4958
(php_hash_final_func_t) PHP_RIPEMD256Final,
50-
(php_hash_copy_func_t) php_hash_copy,
59+
php_hash_copy,
60+
php_hash_serialize,
61+
php_hash_unserialize,
62+
PHP_RIPEMD256_SPEC,
5163
32,
5264
64,
5365
sizeof(PHP_RIPEMD256_CTX),
5466
1
5567
};
5668

5769
const php_hash_ops php_hash_ripemd320_ops = {
70+
"ripemd320",
5871
(php_hash_init_func_t) PHP_RIPEMD320Init,
5972
(php_hash_update_func_t) PHP_RIPEMD320Update,
6073
(php_hash_final_func_t) PHP_RIPEMD320Final,
61-
(php_hash_copy_func_t) php_hash_copy,
74+
php_hash_copy,
75+
php_hash_serialize,
76+
php_hash_unserialize,
77+
PHP_RIPEMD320_SPEC,
6278
40,
6379
64,
6480
sizeof(PHP_RIPEMD320_CTX),

0 commit comments

Comments
 (0)