-
Notifications
You must be signed in to change notification settings - Fork 208
PHPC-788: Timestamp on 32-bit platforms breaks #435
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,7 @@ zend_object_handlers php_phongo_handler_timestamp; | |
|
||
/* Initialize the object and return whether it was successful. An exception will | ||
* be thrown on error. */ | ||
static bool php_phongo_timestamp_init(php_phongo_timestamp_t *intern, phongo_long increment, phongo_long timestamp TSRMLS_DC) | ||
static bool php_phongo_timestamp_init(php_phongo_timestamp_t *intern, int64_t increment, int64_t timestamp TSRMLS_DC) | ||
{ | ||
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); | ||
|
@@ -66,8 +66,8 @@ static bool php_phongo_timestamp_init(php_phongo_timestamp_t *intern, phongo_lon | |
return false; | ||
} | ||
|
||
intern->increment = increment; | ||
intern->timestamp = timestamp; | ||
intern->increment = (uint32_t) increment; | ||
intern->timestamp = (uint32_t) timestamp; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have to worry about endianness here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. |
||
intern->initialized = true; | ||
|
||
return true; | ||
|
@@ -413,8 +413,8 @@ HashTable *php_phongo_timestamp_get_properties(zval *object TSRMLS_DC) /* {{{ */ | |
return props; | ||
} | ||
|
||
s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRId64, intern->increment); | ||
s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRId64, intern->timestamp); | ||
s_increment_len = snprintf(s_increment, sizeof(s_increment), "%" PRIu32, intern->increment); | ||
s_timestamp_len = snprintf(s_timestamp, sizeof(s_timestamp), "%" PRIu32, intern->timestamp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The value in "increment" and "timestamp" is 32bit unsigned, so using a 64bit formatting would add a random 32bit value to the start of each formatted string, resulting in test failures. |
||
|
||
#if PHP_VERSION_ID >= 70000 | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,15 +10,15 @@ echo throws(function() { | |
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n"; | ||
|
||
echo throws(function() { | ||
MongoDB\BSON\Timestamp::__set_state(['increment' => -2147483648, 'timestamp' => 5678]); | ||
MongoDB\BSON\Timestamp::__set_state(['increment' => -2147483647, 'timestamp' => 5678]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP's parser parses "-" and "2147483648" separately. And as "2147483648" is over the int-32 limit, it gets converted to a double. -2147483647 is therefore the highest 32bit number PHP itself can represent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, this isn't really testing a boundary condition, is it? I was testing I'd be OK with remove these test cases unless you really want to keep them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's still a boundary check. Just one for PHP. I'll just keep it. |
||
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n"; | ||
|
||
echo throws(function() { | ||
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => -1]); | ||
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n"; | ||
|
||
echo throws(function() { | ||
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => -2147483648]); | ||
MongoDB\BSON\Timestamp::__set_state(['increment' => 1234, 'timestamp' => -2147483647]); | ||
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n"; | ||
|
||
?> | ||
|
@@ -28,9 +28,9 @@ echo throws(function() { | |
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 | ||
Expected increment to be an unsigned 32-bit integer, -2147483647 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 | ||
Expected timestamp to be an unsigned 32-bit integer, -2147483647 given | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ foreach ($tests as $json) { | |
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECTF-- | ||
%a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is being printed before the first test case? It may make more sense to simply enable and disable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reading of /etc/issue and something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll make the debug=stderr changes, but the other PR will just remove them again... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're going to clean this up in the other PR, don't worry about duplicating that work here. |
||
Test { "x": { "$numberLong": "-2147483648" }} | ||
object(stdClass)#%d (%d) { | ||
["x"]=> | ||
|
@@ -44,15 +45,22 @@ object(stdClass)#%d (%d) { | |
int(2147483647) | ||
} | ||
|
||
Test { "x": { "$numberLong": "4294967294" }} | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 4294967294 | ||
object(stdClass)#%d (%d) { | ||
["x"]=> | ||
string(10) "4294967294" | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test had missing output sections, and the warning formatting was wrong too. This test was always broken. |
||
Test { "x": { "$numberLong": "4294967295" }} | ||
[%s] PHONGO-BSON: WARNING > ENTRY: Integer overflow detected on your platform: 4294967295 | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 4294967295 | ||
object(stdClass)#%d (%d) { | ||
["x"]=> | ||
string(10) "4294967295" | ||
} | ||
|
||
Test { "x": { "$numberLong": "9223372036854775807" }} | ||
[%s] PHONGO-BSON: WARNING > ENTRY: Integer overflow detected on your platform: 9223372036854775807 | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 9223372036854775807 | ||
object(stdClass)#%d (%d) { | ||
["x"]=> | ||
string(19) "9223372036854775807" | ||
|
@@ -71,20 +79,21 @@ object(stdClass)#%d (%d) { | |
} | ||
|
||
Test { "longFieldName": { "$numberLong": "4294967294" }} | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 4294967294 | ||
object(stdClass)#%d (%d) { | ||
["longFieldName"]=> | ||
string(10) "4294967294" | ||
} | ||
|
||
Test { "longFieldName": { "$numberLong": "4294967295" }} | ||
[%s] PHONGO-BSON: WARNING > ENTRY: Integer overflow detected on your platform: 4294967295 | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 4294967295 | ||
object(stdClass)#%d (%d) { | ||
["longFieldName"]=> | ||
string(10) "4294967295" | ||
} | ||
|
||
Test { "longFieldName": { "$numberLong": "9223372036854775807" }} | ||
[%s] PHONGO-BSON: WARNING > ENTRY: Integer overflow detected on your platform: 9223372036854775807 | ||
[%s] PHONGO-BSON: WARNING > Integer overflow detected on your platform: 9223372036854775807 | ||
object(stdClass)#%d (%d) { | ||
["longFieldName"]=> | ||
string(19) "9223372036854775807" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be int64_t, as that's what the original arguments that were passed in here are as well. phongo_long is also not 64-bit on 32-bit platforms, and hence the comparison with UINT32_MIN would fail for some values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you mean the
< 0
comparisons would fail?Since
php_phongo_timestamp_init_from_string()
was always parsing the strings intoint64_t
values, I suppose there was possible degredation there. The other code path isphp_phongo_timestamp_init_from_hash()
picking upIS_LONG
values. In that case, would a negativeint32_t
value expand to a negativeint64_t
value (essentially the sign bit relocates) and still yield an exception?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the
< 0
would fail. And a sign bit doesn't change when you cast.