Skip to content

PHPC-593, PHPC-594, PHPC-595: Range checks for WriteConcern, Binary, and Timestamp #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions phongo_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@
# define phongo_char_pdup(str) pestrdup(filename->val, 1)
# define phongo_char_free(str) zend_string_release(str)
# define phongo_long zend_long
#if SIZEOF_ZEND_LONG == 8
# define PHONGO_LONG_FORMAT PRId64
#elif SIZEOF_ZEND_LONG == 4
# define PHONGO_LONG_FORMAT PRId32
#else
# error Unsupported architecture (integers are neither 32-bit nor 64-bit)
#endif
# define SIZEOF_PHONGO_LONG SIZEOF_ZEND_LONG
# define phongo_str(str) str->val
# define phongo_create_object_retval zend_object*
Expand Down Expand Up @@ -153,6 +160,7 @@
# define phongo_char_pdup(str) pestrdup(filename, 1)
# define phongo_char_free(str) _efree(str ZEND_FILE_LINE_CC ZEND_FILE_LINE_CC)
# define phongo_long long
# define PHONGO_LONG_FORMAT "ld"
# define SIZEOF_PHONGO_LONG SIZEOF_LONG
# define phongo_str(str) str
# define phongo_create_object_retval zend_object_value
Expand Down
4 changes: 2 additions & 2 deletions php_phongo.c
Original file line number Diff line number Diff line change
Expand Up @@ -2044,7 +2044,7 @@ void php_phongo_new_datetime_from_utcdatetime(zval *object, int64_t milliseconds
efree(sec);
datetime_obj->time->f = milliseconds % 1000;
} /* }}} */
void php_phongo_new_timestamp_from_increment_and_timestamp(zval *object, int32_t increment, int32_t timestamp TSRMLS_DC) /* {{{ */
void php_phongo_new_timestamp_from_increment_and_timestamp(zval *object, uint32_t increment, uint32_t timestamp TSRMLS_DC) /* {{{ */
{
php_phongo_timestamp_t *intern;

Expand Down Expand Up @@ -2080,7 +2080,7 @@ void php_phongo_new_binary_from_binary_and_type(zval *object, const char *data,
intern = Z_BINARY_OBJ_P(object);
intern->data = estrndup(data, data_len);
intern->data_len = data_len;
intern->type = type;
intern->type = (uint8_t) type;
} /* }}} */
void php_phongo_new_regex_from_regex_and_options(zval *object, const char *pattern, const char *flags TSRMLS_DC) /* {{{ */
{
Expand Down
2 changes: 1 addition & 1 deletion php_phongo.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void php_phongo_objectid_new_from_oid(zval *object, const bson_oid_t *oid TSRMLS
void php_phongo_cursor_id_new_from_id(zval *object, int64_t cursorid TSRMLS_DC);
void php_phongo_new_utcdatetime_from_epoch(zval *object, int64_t msec_since_epoch TSRMLS_DC);
void php_phongo_new_datetime_from_utcdatetime(zval *object, int64_t milliseconds TSRMLS_DC);
void php_phongo_new_timestamp_from_increment_and_timestamp(zval *object, int32_t increment, int32_t timestamp TSRMLS_DC);
void php_phongo_new_timestamp_from_increment_and_timestamp(zval *object, uint32_t increment, uint32_t timestamp TSRMLS_DC);
void php_phongo_new_javascript_from_javascript(int init, zval *object, const char *code, size_t code_len TSRMLS_DC);
void php_phongo_new_javascript_from_javascript_and_scope(int init, zval *object, const char *code, size_t code_len, const bson_t *scope TSRMLS_DC);
void php_phongo_new_binary_from_binary_and_type(zval *object, const char *data, size_t data_len, bson_subtype_t type TSRMLS_DC);
Expand Down
6 changes: 3 additions & 3 deletions php_phongo_structs-5.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ typedef struct {
zend_object std;
char *data;
int data_len;
int type;
uint8_t type;
} php_phongo_binary_t;
typedef struct {
zend_object std;
Expand Down Expand Up @@ -156,8 +156,8 @@ typedef struct {
} php_phongo_regex_t;
typedef struct {
zend_object std;
int32_t increment;
int32_t timestamp;
uint32_t increment;
uint32_t timestamp;
} php_phongo_timestamp_t;
typedef struct {
zend_object std;
Expand Down
4 changes: 2 additions & 2 deletions php_phongo_structs-7.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ typedef struct {
zend_object std;
} php_phongo_regex_t;
typedef struct {
int32_t increment;
int32_t timestamp;
uint32_t increment;
uint32_t timestamp;
zend_object std;
} php_phongo_timestamp_t;
typedef struct {
Expand Down
9 changes: 7 additions & 2 deletions src/BSON/Binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ PHP_METHOD(Binary, __construct)
zend_error_handling error_handling;
char *data;
phongo_zpp_char_len data_len;
long type;
phongo_long type;


zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
Expand All @@ -66,9 +66,14 @@ PHP_METHOD(Binary, __construct)
}
zend_restore_error_handling(&error_handling TSRMLS_CC);

if (type < 0 || type > UINT8_MAX) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected type to be an unsigned 8-bit integer, %" PHONGO_LONG_FORMAT " given", type);
return;
}

intern->data = estrndup(data, data_len);
intern->data_len = data_len;
intern->type = type;
intern->type = (uint8_t) type;
}
/* }}} */
/* {{{ proto string Binary::getData()
Expand Down
16 changes: 13 additions & 3 deletions src/BSON/Timestamp.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ PHP_METHOD(Timestamp, __construct)
{
php_phongo_timestamp_t *intern;
zend_error_handling error_handling;
long increment;
long timestamp;
phongo_long increment;
phongo_long timestamp;


zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
Expand All @@ -65,6 +65,16 @@ PHP_METHOD(Timestamp, __construct)
}
zend_restore_error_handling(&error_handling TSRMLS_CC);

if (increment < 0 || increment > UINT32_MAX) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected increment to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", increment);
return;
}

if (timestamp < 0 || timestamp > UINT32_MAX) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected timestamp to be an unsigned 32-bit integer, %" PHONGO_LONG_FORMAT " given", timestamp);
return;
}

intern->increment = increment;
intern->timestamp = timestamp;
}
Expand All @@ -84,7 +94,7 @@ PHP_METHOD(Timestamp, __toString)
return;
}

retval_len = spprintf(&retval, 0, "[%d:%d]", intern->increment, intern->timestamp);
retval_len = spprintf(&retval, 0, "[%" PRIu32 ":%" PRIu32 "]", intern->increment, intern->timestamp);
PHONGO_RETVAL_STRINGL(retval, retval_len);
efree(retval);
}
Expand Down
9 changes: 7 additions & 2 deletions src/MongoDB/WriteConcern.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ PHP_METHOD(WriteConcern, __construct)
php_phongo_writeconcern_t *intern;
zend_error_handling error_handling;
zval *w, *journal;
long wtimeout = 0;
phongo_long wtimeout = 0;
SUPPRESS_UNUSED_WARNING(return_value) SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used)


Expand Down Expand Up @@ -99,7 +99,12 @@ PHP_METHOD(WriteConcern, __construct)
/* fallthrough */
case 2:
if (wtimeout < 0) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected wtimeout to be >= 0, %ld given", wtimeout);
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected wtimeout to be >= 0, %" PHONGO_LONG_FORMAT " given", wtimeout);
return;
}

if (wtimeout > INT32_MAX) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected wtimeout to be <= %" PRId32 ", %" PHONGO_LONG_FORMAT " given", INT32_MAX, wtimeout);
return;
}

Expand Down
6 changes: 3 additions & 3 deletions src/bson.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ int64_t php_phongo_utcdatetime_get_milliseconds(zval *object TSRMLS_DC)

return intern->milliseconds;
}
int32_t php_phongo_timestamp_get_increment(zval *object TSRMLS_DC)
uint32_t php_phongo_timestamp_get_increment(zval *object TSRMLS_DC)
{
php_phongo_timestamp_t *intern;

intern = Z_TIMESTAMP_OBJ_P(object);

return intern->increment;
}
int32_t php_phongo_timestamp_get_timestamp(zval *object TSRMLS_DC)
uint32_t php_phongo_timestamp_get_timestamp(zval *object TSRMLS_DC)
{
php_phongo_timestamp_t *intern;

Expand Down Expand Up @@ -142,7 +142,7 @@ int php_phongo_binary_get_data(zval *object, char **data TSRMLS_DC)
*data = intern->data;
return intern->data_len;
}
int php_phongo_binary_get_type(zval *object TSRMLS_DC)
uint8_t php_phongo_binary_get_type(zval *object TSRMLS_DC)
{
php_phongo_binary_t *intern;

Expand Down
27 changes: 27 additions & 0 deletions tests/bson/bson-binary_error-004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
BSON BSON\Binary constructor requires unsigned 8-bit integer for type
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

use MongoDB\BSON as BSON;

echo throws(function() {
new BSON\Binary('foo', -1);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

echo throws(function() {
new BSON\Binary('foo', 256);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected type to be an unsigned 8-bit integer, -1 given
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected type to be an unsigned 8-bit integer, 256 given
===DONE===
42 changes: 42 additions & 0 deletions tests/bson/bson-timestamp-003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
BSON BSON\Timestamp constructor requires positive unsigned 32-bit integers
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

use MongoDB\BSON as BSON;

$tests = [
new BSON\Timestamp(2147483647, 0),
new BSON\Timestamp(0, 2147483647),
];

foreach ($tests as $test) {
printf("Test %s\n", $test);
var_dump($test);
echo "\n";
}

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
Test [2147483647:0]
object(%SBSON\Timestamp)#%d (%d) {
["increment"]=>
int(2147483647)
["timestamp"]=>
int(0)
}

Test [0:2147483647]
object(%SBSON\Timestamp)#%d (%d) {
["increment"]=>
int(0)
["timestamp"]=>
int(2147483647)
}

===DONE===
43 changes: 43 additions & 0 deletions tests/bson/bson-timestamp-004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--TEST--
BSON BSON\Timestamp constructor requires 64-bit integers to be positive unsigned 32-bit integers
--SKIPIF--
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

use MongoDB\BSON as BSON;

$tests = [
new BSON\Timestamp(4294967295, 0),
new BSON\Timestamp(0, 4294967295),
];

foreach ($tests as $test) {
printf("Test %s\n", $test);
var_dump($test);
echo "\n";
}

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
Test [4294967295:0]
object(%SBSON\Timestamp)#%d (%d) {
["increment"]=>
int(4294967295)
["timestamp"]=>
int(0)
}

Test [0:4294967295]
object(%SBSON\Timestamp)#%d (%d) {
["increment"]=>
int(0)
["timestamp"]=>
int(4294967295)
}

===DONE===
39 changes: 39 additions & 0 deletions tests/bson/bson-timestamp_error-004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--TEST--
BSON BSON\Timestamp constructor requires positive unsigned 32-bit integers
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

use MongoDB\BSON as BSON;

echo throws(function() {
new BSON\Timestamp(-1, 0);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

echo throws(function() {
new BSON\Timestamp(-2147483648, 0);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

echo throws(function() {
new BSON\Timestamp(0, -1);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

echo throws(function() {
new BSON\Timestamp(0, -2147483648);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected increment to be an unsigned 32-bit integer, -1 given
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected increment to be an unsigned 32-bit integer, -2147483648 given
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected timestamp to be an unsigned 32-bit integer, -1 given
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected timestamp to be an unsigned 32-bit integer, -2147483648 given
===DONE===
28 changes: 28 additions & 0 deletions tests/bson/bson-timestamp_error-005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
BSON BSON\Timestamp constructor requires 64-bit integers to be positive unsigned 32-bit integers
--SKIPIF--
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

use MongoDB\BSON as BSON;

echo throws(function() {
new BSON\Timestamp(4294967296, 0);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

echo throws(function() {
new BSON\Timestamp(0, 4294967296);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected increment to be an unsigned 32-bit integer, 4294967296 given
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected timestamp to be an unsigned 32-bit integer, 4294967296 given
===DONE===
20 changes: 20 additions & 0 deletions tests/writeConcern/writeconcern-ctor_error-005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
MongoDB\Driver\WriteConcern construction (invalid wtimeout range)
--SKIPIF--
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

echo throws(function() {
new MongoDB\Driver\WriteConcern(1, 2147483648);
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
Expected wtimeout to be <= 2147483647, 2147483648 given
===DONE===