Skip to content

Commit 9c514b5

Browse files
committed
PHPC-741: Consistent exceptions for Timestamp init methods
1 parent 160c65d commit 9c514b5

9 files changed

+211
-23
lines changed

src/BSON/Timestamp.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,34 +46,48 @@ PHONGO_API zend_class_entry *php_phongo_timestamp_ce;
4646

4747
zend_object_handlers php_phongo_handler_timestamp;
4848

49-
/* Initialize the object from a string and return whether it was successful. */
50-
static bool php_phongo_timestamp_init(php_phongo_timestamp_t *intern, phongo_long increment, phongo_long timestamp)
49+
/* Initialize the object and return whether it was successful. An exception will
50+
* be thrown on error. */
51+
static bool php_phongo_timestamp_init(php_phongo_timestamp_t *intern, phongo_long increment, phongo_long timestamp TSRMLS_DC)
5152
{
53+
if (increment < 0 || increment > UINT32_MAX) {
54+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected increment to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", increment);
55+
return false;
56+
}
57+
58+
if (timestamp < 0 || timestamp > UINT32_MAX) {
59+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected timestamp to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", timestamp);
60+
return false;
61+
}
62+
5263
intern->increment = increment;
5364
intern->timestamp = timestamp;
5465
intern->initialized = true;
5566

5667
return true;
5768
}
5869

59-
/* Initialize the object from a HashTable and return whether it was successful. */
60-
static bool php_phongo_timestamp_init_from_hash(php_phongo_timestamp_t *intern, HashTable *props)
70+
/* Initialize the object from a HashTable and return whether it was successful.
71+
* An exception will be thrown on error. */
72+
static bool php_phongo_timestamp_init_from_hash(php_phongo_timestamp_t *intern, HashTable *props TSRMLS_DC)
6173
{
6274
#if PHP_VERSION_ID >= 70000
6375
zval *increment, *timestamp;
6476

6577
if ((increment = zend_hash_str_find(props, "increment", sizeof("increment")-1)) && Z_TYPE_P(increment) == IS_LONG &&
6678
(timestamp = zend_hash_str_find(props, "timestamp", sizeof("timestamp")-1)) && Z_TYPE_P(timestamp) == IS_LONG) {
67-
return php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp));
79+
return php_phongo_timestamp_init(intern, Z_LVAL_P(increment), Z_LVAL_P(timestamp) TSRMLS_CC);
6880
}
6981
#else
7082
zval **increment, **timestamp;
7183

7284
if (zend_hash_find(props, "increment", sizeof("increment"), (void**) &increment) == SUCCESS && Z_TYPE_PP(increment) == IS_LONG &&
7385
zend_hash_find(props, "timestamp", sizeof("timestamp"), (void**) &timestamp) == SUCCESS && Z_TYPE_PP(timestamp) == IS_LONG) {
74-
return php_phongo_timestamp_init(intern, Z_LVAL_PP(increment), Z_LVAL_PP(timestamp));
86+
return php_phongo_timestamp_init(intern, Z_LVAL_PP(increment), Z_LVAL_PP(timestamp) TSRMLS_CC);
7587
}
7688
#endif
89+
90+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"increment\" and \"timestamp\" integer fields", ZSTR_VAL(php_phongo_timestamp_ce->name));
7791
return false;
7892
}
7993

@@ -96,17 +110,7 @@ PHP_METHOD(Timestamp, __construct)
96110
}
97111
zend_restore_error_handling(&error_handling TSRMLS_CC);
98112

99-
if (increment < 0 || increment > UINT32_MAX) {
100-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected increment to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", increment);
101-
return;
102-
}
103-
104-
if (timestamp < 0 || timestamp > UINT32_MAX) {
105-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected timestamp to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", timestamp);
106-
return;
107-
}
108-
109-
php_phongo_timestamp_init(intern, increment, timestamp);
113+
php_phongo_timestamp_init(intern, increment, timestamp TSRMLS_CC);
110114
}
111115
/* }}} */
112116

@@ -127,9 +131,7 @@ PHP_METHOD(Timestamp, __set_state)
127131
intern = Z_TIMESTAMP_OBJ_P(return_value);
128132
props = Z_ARRVAL_P(array);
129133

130-
if (!php_phongo_timestamp_init_from_hash(intern, props)) {
131-
php_error(E_ERROR, "Invalid serialization data for Timestamp object");
132-
}
134+
php_phongo_timestamp_init_from_hash(intern, props TSRMLS_CC);
133135
}
134136
/* }}} */
135137

@@ -168,9 +170,7 @@ PHP_METHOD(Timestamp, __wakeup)
168170
intern = Z_TIMESTAMP_OBJ_P(getThis());
169171
props = zend_std_get_properties(getThis() TSRMLS_CC);
170172

171-
if (!php_phongo_timestamp_init_from_hash(intern, props)) {
172-
php_error(E_ERROR, "Invalid serialization data for Timestamp object");
173-
}
173+
php_phongo_timestamp_init_from_hash(intern, props TSRMLS_CC);
174174
}
175175
/* }}} */
176176

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp unserialization requires "increment" and "timestamp" integer fields
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
echo throws(function() {
10+
unserialize('O:22:"MongoDB\BSON\Timestamp":1:{s:9:"increment";i:1234;}');
11+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
12+
13+
echo throws(function() {
14+
unserialize('O:22:"MongoDB\BSON\Timestamp":1:{s:9:"timestamp";i:5678;}');
15+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
16+
17+
echo throws(function() {
18+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";s:4:"1234";s:9:"timestamp";s:4:"5678";}');
19+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
20+
21+
?>
22+
===DONE===
23+
<?php exit(0); ?>
24+
--EXPECT--
25+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
26+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
27+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
28+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
29+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
30+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
31+
===DONE===
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp unserialization requires positive unsigned 32-bit integers
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
echo throws(function() {
10+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:-1;s:9:"timestamp";i:5678;}');
11+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
12+
13+
echo throws(function() {
14+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:-2147483648;s:9:"timestamp";i:5678;}');
15+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
16+
17+
echo throws(function() {
18+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:-1;}');
19+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
20+
21+
echo throws(function() {
22+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:-2147483648;}');
23+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
24+
25+
?>
26+
===DONE===
27+
<?php exit(0); ?>
28+
--EXPECT--
29+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
30+
Expected increment to be an unsigned 32-bit integer, -1 given
31+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
32+
Expected increment to be an unsigned 32-bit integer, -2147483648 given
33+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
34+
Expected timestamp to be an unsigned 32-bit integer, -1 given
35+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
36+
Expected timestamp to be an unsigned 32-bit integer, -2147483648 given
37+
===DONE===
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp unserialization requires 64-bit integers to be positive unsigned 32-bit integers
3+
--SKIPIF--
4+
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
5+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
echo throws(function() {
11+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:4294967296;s:9:"timestamp";i:5678;}');
12+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
13+
14+
echo throws(function() {
15+
unserialize('O:22:"MongoDB\BSON\Timestamp":2:{s:9:"increment";i:1234;s:9:"timestamp";i:4294967296;}');
16+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
17+
18+
?>
19+
===DONE===
20+
<?php exit(0); ?>
21+
--EXPECT--
22+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
23+
Expected increment to be an unsigned 32-bit integer, 4294967296 given
24+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
25+
Expected timestamp to be an unsigned 32-bit integer, 4294967296 given
26+
===DONE===
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp::__set_state() requires "increment" and "timestamp" integer fields
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
echo throws(function() {
10+
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234]);
11+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
12+
13+
echo throws(function() {
14+
MongoDB\BSON\Timestamp::__set_state(['timestamp' => 5678]);
15+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
16+
17+
echo throws(function() {
18+
MongoDB\BSON\Timestamp::__set_state(['increment' => '1234', 'timestamp' => '5678']);
19+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
20+
21+
?>
22+
===DONE===
23+
<?php exit(0); ?>
24+
--EXPECT--
25+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
26+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
27+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
28+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
29+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
30+
MongoDB\BSON\Timestamp initialization requires "increment" and "timestamp" integer fields
31+
===DONE===
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp::__set_state() requires positive unsigned 32-bit integers
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
echo throws(function() {
10+
MongoDB\BSON\Timestamp::__set_state(['increment' => -1, 'timestamp' => 5678]);
11+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
12+
13+
echo throws(function() {
14+
MongoDB\BSON\Timestamp::__set_state(['increment' => -2147483648, 'timestamp' => 5678]);
15+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
16+
17+
echo throws(function() {
18+
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => -1]);
19+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
20+
21+
echo throws(function() {
22+
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => -2147483648]);
23+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
24+
25+
?>
26+
===DONE===
27+
<?php exit(0); ?>
28+
--EXPECT--
29+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
30+
Expected increment to be an unsigned 32-bit integer, -1 given
31+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
32+
Expected increment to be an unsigned 32-bit integer, -2147483648 given
33+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
34+
Expected timestamp to be an unsigned 32-bit integer, -1 given
35+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
36+
Expected timestamp to be an unsigned 32-bit integer, -2147483648 given
37+
===DONE===
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
MongoDB\BSON\Timestamp::__set_state() requires 64-bit integers to be positive unsigned 32-bit integers
3+
--SKIPIF--
4+
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
5+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
echo throws(function() {
11+
MongoDB\BSON\Timestamp::__set_state(['increment' => 4294967296, 'timestamp' => 5678]);
12+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
13+
14+
echo throws(function() {
15+
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => 4294967296]);
16+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
17+
18+
?>
19+
===DONE===
20+
<?php exit(0); ?>
21+
--EXPECT--
22+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
23+
Expected increment to be an unsigned 32-bit integer, 4294967296 given
24+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
25+
Expected timestamp to be an unsigned 32-bit integer, 4294967296 given
26+
===DONE===

0 commit comments

Comments
 (0)