Skip to content

Commit d6b095a

Browse files
committed
PHPC-779: Switch Timestamp from O to C type serialization
1 parent 41a1175 commit d6b095a

6 files changed

+125
-15
lines changed

src/BSON/Timestamp.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
#include <ext/standard/info.h>
3535
#include <Zend/zend_interfaces.h>
3636
#include <ext/spl/spl_iterators.h>
37+
#include <ext/standard/php_var.h>
38+
#if PHP_VERSION_ID >= 70000
39+
# include <zend_smart_str.h>
40+
#else
41+
# include <ext/standard/php_smart_str.h>
42+
#endif
3743
/* Our Compatability header */
3844
#include "phongo_compat.h"
3945

@@ -226,6 +232,102 @@ PHP_METHOD(Timestamp, __wakeup)
226232
}
227233
/* }}} */
228234

235+
/* {{{ proto string Timestamp::serialize()
236+
*/
237+
PHP_METHOD(Timestamp, serialize)
238+
{
239+
php_phongo_timestamp_t *intern;
240+
#if PHP_VERSION_ID >= 70000
241+
zval retval;
242+
#else
243+
zval *retval;
244+
#endif
245+
php_serialize_data_t var_hash;
246+
smart_str buf = { 0 };
247+
char s_increment[12];
248+
char s_timestamp[12];
249+
int s_increment_len;
250+
int s_timestamp_len;
251+
252+
intern = Z_TIMESTAMP_OBJ_P(getThis());
253+
254+
if (zend_parse_parameters_none() == FAILURE) {
255+
return;
256+
}
257+
258+
s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment);
259+
s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp);
260+
261+
#if PHP_VERSION_ID >= 70000
262+
array_init_size(&retval, 2);
263+
ADD_ASSOC_STRINGL(&retval, "increment", s_increment, s_increment_len);
264+
ADD_ASSOC_STRINGL(&retval, "timestamp", s_timestamp, s_timestamp_len);
265+
#else
266+
ALLOC_INIT_ZVAL(retval);
267+
array_init_size(retval, 2);
268+
ADD_ASSOC_STRINGL(retval, "increment", s_increment, s_increment_len);
269+
ADD_ASSOC_STRINGL(retval, "timestamp", s_timestamp, s_timestamp_len);
270+
#endif
271+
272+
PHP_VAR_SERIALIZE_INIT(var_hash);
273+
php_var_serialize(&buf, &retval, &var_hash TSRMLS_CC);
274+
smart_str_0(&buf);
275+
PHP_VAR_SERIALIZE_DESTROY(var_hash);
276+
277+
PHONGO_RETVAL_SMART_STR(buf);
278+
279+
smart_str_free(&buf);
280+
zval_ptr_dtor(&retval);
281+
}
282+
/* }}} */
283+
284+
/* {{{ proto string Timestamp::unserialize(string $serialized)
285+
*/
286+
PHP_METHOD(Timestamp, unserialize)
287+
{
288+
php_phongo_timestamp_t *intern;
289+
zend_error_handling error_handling;
290+
char *serialized;
291+
phongo_zpp_char_len serialized_len;
292+
#if PHP_VERSION_ID >= 70000
293+
zval props;
294+
#else
295+
zval *props;
296+
#endif
297+
php_unserialize_data_t var_hash;
298+
299+
intern = Z_TIMESTAMP_OBJ_P(getThis());
300+
301+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
302+
303+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &serialized_len) == FAILURE) {
304+
zend_restore_error_handling(&error_handling TSRMLS_CC);
305+
return;
306+
}
307+
zend_restore_error_handling(&error_handling TSRMLS_CC);
308+
309+
#if PHP_VERSION_ID < 70000
310+
ALLOC_INIT_ZVAL(props);
311+
#endif
312+
PHP_VAR_UNSERIALIZE_INIT(var_hash);
313+
if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char *) serialized + serialized_len, &var_hash TSRMLS_CC)) {
314+
zval_ptr_dtor(&props);
315+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "%s unserialization failed", ZSTR_VAL(php_phongo_timestamp_ce->name));
316+
317+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
318+
return;
319+
}
320+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
321+
322+
#if PHP_VERSION_ID >= 70000
323+
php_phongo_timestamp_init_from_hash(intern, HASH_OF(&props) TSRMLS_CC);
324+
#else
325+
php_phongo_timestamp_init_from_hash(intern, HASH_OF(props) TSRMLS_CC);
326+
#endif
327+
zval_ptr_dtor(&props);
328+
}
329+
/* }}} */
330+
229331
/* {{{ BSON\Timestamp */
230332

231333
ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___construct, 0, 0, 2)
@@ -237,6 +339,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp___set_state, 0, 0, 1)
237339
ZEND_ARG_ARRAY_INFO(0, properties, 0)
238340
ZEND_END_ARG_INFO()
239341

342+
ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_unserialize, 0, 0, 1)
343+
ZEND_ARG_INFO(0, serialized)
344+
ZEND_END_ARG_INFO()
345+
240346
ZEND_BEGIN_ARG_INFO_EX(ai_Timestamp_void, 0, 0, 0)
241347
ZEND_END_ARG_INFO()
242348

@@ -245,6 +351,8 @@ static zend_function_entry php_phongo_timestamp_me[] = {
245351
PHP_ME(Timestamp, __set_state, ai_Timestamp___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
246352
PHP_ME(Timestamp, __toString, ai_Timestamp_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
247353
PHP_ME(Timestamp, __wakeup, ai_Timestamp_void, ZEND_ACC_PUBLIC)
354+
PHP_ME(Timestamp, serialize, ai_Timestamp_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
355+
PHP_ME(Timestamp, unserialize, ai_Timestamp_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
248356
PHP_FE_END
249357
};
250358

@@ -367,6 +475,8 @@ PHP_MINIT_FUNCTION(Timestamp)
367475
PHONGO_CE_FINAL(php_phongo_timestamp_ce);
368476

369477
zend_class_implements(php_phongo_timestamp_ce TSRMLS_CC, 1, php_phongo_type_ce);
478+
zend_class_implements(php_phongo_timestamp_ce TSRMLS_CC, 1, zend_ce_serializable);
479+
370480
memcpy(&php_phongo_handler_timestamp, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
371481
php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties;
372482
#if PHP_VERSION_ID >= 70000

tests/bson/bson-timestamp-serialization-001.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object(MongoDB\BSON\Timestamp)#%d (%d) {
2828
["timestamp"]=>
2929
string(4) "5678"
3030
}
31-
string(88) "O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:4:"1234";s:9:"timestamp";s:4:"5678";}"
31+
string(95) "C:22:"MongoDB\BSON\Timestamp":60:{a:2:{s:9:"increment";s:4:"1234";s:9:"timestamp";s:4:"5678";}}"
3232
object(MongoDB\BSON\Timestamp)#%d (%d) {
3333
["increment"]=>
3434
string(4) "1234"
@@ -42,7 +42,7 @@ object(MongoDB\BSON\Timestamp)#%d (%d) {
4242
["timestamp"]=>
4343
string(1) "0"
4444
}
45-
string(92) "O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:10:"2147483647";s:9:"timestamp";s:1:"0";}"
45+
string(99) "C:22:"MongoDB\BSON\Timestamp":64:{a:2:{s:9:"increment";s:10:"2147483647";s:9:"timestamp";s:1:"0";}}"
4646
object(MongoDB\BSON\Timestamp)#%d (%d) {
4747
["increment"]=>
4848
string(10) "2147483647"
@@ -56,7 +56,7 @@ object(MongoDB\BSON\Timestamp)#%d (%d) {
5656
["timestamp"]=>
5757
string(10) "2147483647"
5858
}
59-
string(92) "O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:1:"0";s:9:"timestamp";s:10:"2147483647";}"
59+
string(99) "C:22:"MongoDB\BSON\Timestamp":64:{a:2:{s:9:"increment";s:1:"0";s:9:"timestamp";s:10:"2147483647";}}"
6060
object(MongoDB\BSON\Timestamp)#%d (%d) {
6161
["increment"]=>
6262
string(1) "0"

tests/bson/bson-timestamp-serialization-002.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object(MongoDB\BSON\Timestamp)#%d (%d) {
2929
["timestamp"]=>
3030
string(1) "0"
3131
}
32-
string(92) "O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:10:"4294967295";s:9:"timestamp";s:1:"0";}"
32+
string(99) "C:22:"MongoDB\BSON\Timestamp":64:{a:2:{s:9:"increment";s:10:"4294967295";s:9:"timestamp";s:1:"0";}}"
3333
object(MongoDB\BSON\Timestamp)#%d (%d) {
3434
["increment"]=>
3535
string(10) "4294967295"
@@ -43,7 +43,7 @@ object(MongoDB\BSON\Timestamp)#%d (%d) {
4343
["timestamp"]=>
4444
string(10) "4294967295"
4545
}
46-
string(92) "O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:1:"0";s:9:"timestamp";s:10:"4294967295";}"
46+
string(99) "C:22:"MongoDB\BSON\Timestamp":64:{a:2:{s:9:"increment";s:1:"0";s:9:"timestamp";s:10:"4294967295";}}"
4747
object(MongoDB\BSON\Timestamp)#%d (%d) {
4848
["increment"]=>
4949
string(1) "0"

tests/bson/bson-timestamp-serialization_error-001.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ MongoDB\BSON\Timestamp unserialization requires "increment" and "timestamp" inte
66
require_once __DIR__ . '/../utils/tools.php';
77

88
echo throws(function() {
9-
unserialize('O:22:"MongoDB\BSON\Timestamp":1:{s:9:"increment";i:1234;}');
9+
unserialize('C:22:"MongoDB\BSON\Timestamp":29:{a:1:{s:9:"increment";i:1234;}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
echo throws(function() {
13-
unserialize('O:22:"MongoDB\BSON\Timestamp":1:{s:9:"timestamp";i:5678;}');
13+
unserialize('C:22:"MongoDB\BSON\Timestamp":29:{a:1:{s:9:"timestamp";i:5678;}}');
1414
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1515

1616
echo throws(function() {
17-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";s:4:"5678";}');
17+
unserialize('C:22:"MongoDB\BSON\Timestamp":56:{a:2:{s:9:"increment";i:1234;s:9:"timestamp";s:4:"5678";}}');
1818
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1919

2020
echo throws(function() {
21-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:4:"1234";s:9:"timestamp";i:5678;}');
21+
unserialize('C:22:"MongoDB\BSON\Timestamp":56:{a:2:{s:9:"increment";s:4:"1234";s:9:"timestamp";i:5678;}}');
2222
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
2323

2424
?>

tests/bson/bson-timestamp-serialization_error-002.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ MongoDB\BSON\Timestamp unserialization requires positive unsigned 32-bit integer
66
require_once __DIR__ . '/../utils/tools.php';
77

88
echo throws(function() {
9-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:-1;s:9:"timestamp";i:5678;}');
9+
unserialize('C:22:"MongoDB\BSON\Timestamp":50:{a:2:{s:9:"increment";i:-1;s:9:"timestamp";i:5678;}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
echo throws(function() {
13-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:-2147483648;s:9:"timestamp";i:5678;}');
13+
unserialize('C:22:"MongoDB\BSON\Timestamp":59:{a:2:{s:9:"increment";i:-2147483648;s:9:"timestamp";i:5678;}}');
1414
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1515

1616
echo throws(function() {
17-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:-1;}');
17+
unserialize('C:22:"MongoDB\BSON\Timestamp":50:{a:2:{s:9:"increment";i:1234;s:9:"timestamp";i:-1;}}');
1818
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1919

2020
echo throws(function() {
21-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:-2147483648;}');
21+
unserialize('C:22:"MongoDB\BSON\Timestamp":59:{a:2:{s:9:"increment";i:1234;s:9:"timestamp";i:-2147483648;}}');
2222
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
2323

2424
?>

tests/bson/bson-timestamp-serialization_error-003.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ MongoDB\BSON\Timestamp unserialization requires 64-bit integers to be positive u
88
require_once __DIR__ . '/../utils/tools.php';
99

1010
echo throws(function() {
11-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:4294967296;s:9:"timestamp";i:5678;}');
11+
unserialize('C:22:"MongoDB\BSON\Timestamp":58:{a:2:{s:9:"increment";i:4294967296;s:9:"timestamp";i:5678;}}');
1212
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1313

1414
echo throws(function() {
15-
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:4294967296;}');
15+
unserialize('C:22:"MongoDB\BSON\Timestamp":58:{a:2:{s:9:"increment";i:1234;s:9:"timestamp";i:4294967296;}}');
1616
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1717

1818
?>

0 commit comments

Comments
 (0)