Skip to content

Commit 1de9b24

Browse files
committed
PHPC-2420: Compare Int64 instances without casting
1 parent 5ac56a5 commit 1de9b24

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed

src/BSON/Int64.c

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,23 @@ static zend_object* php_phongo_int64_clone_object(phongo_compat_object_handler_t
265265
return new_object;
266266
}
267267

268-
static int php_phongo_int64_compare_objects(zval* o1, zval* o2)
268+
static bool php_phongo_int64_is_int64_object(zval* object)
269269
{
270-
php_phongo_int64_t *intern1, *intern2;
270+
if (Z_TYPE_P(object) != IS_OBJECT) {
271+
return false;
272+
}
271273

272-
ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
274+
return Z_OBJ_P(object)->ce == php_phongo_int64_ce;
275+
}
276+
277+
static bool php_phongo_int64_is_long_or_double(zval* value)
278+
{
279+
return Z_TYPE_P(value) == IS_LONG || Z_TYPE_P(value) == IS_DOUBLE;
280+
}
281+
282+
static int php_phongo_int64_compare_int64_objects(zval* o1, zval* o2)
283+
{
284+
php_phongo_int64_t *intern1, *intern2;
273285

274286
intern1 = Z_INT64_OBJ_P(o1);
275287
intern2 = Z_INT64_OBJ_P(o2);
@@ -281,6 +293,58 @@ static int php_phongo_int64_compare_objects(zval* o1, zval* o2)
281293
return 0;
282294
}
283295

296+
static int php_phongo_int64_compare_with_long_or_float(zval* object, zval* value)
297+
{
298+
php_phongo_int64_t* intern;
299+
int64_t long_value;
300+
double double_value;
301+
302+
intern = Z_INT64_OBJ_P(object);
303+
304+
assert(php_phongo_int64_is_long_or_double(value));
305+
306+
switch (Z_TYPE_P(value)) {
307+
case IS_LONG:
308+
long_value = Z_LVAL_P(value);
309+
if (intern->integer != long_value) {
310+
return intern->integer < long_value ? -1 : 1;
311+
}
312+
break;
313+
314+
case IS_DOUBLE:
315+
double_value = Z_DVAL_P(value);
316+
if (intern->integer != double_value) {
317+
return intern->integer < double_value ? -1 : 1;
318+
}
319+
break;
320+
321+
default:
322+
return 0;
323+
}
324+
325+
return 0;
326+
}
327+
328+
static int php_phongo_int64_compare_objects(zval* o1, zval* o2)
329+
{
330+
if (php_phongo_int64_is_int64_object(o1) && php_phongo_int64_is_int64_object(o2)) {
331+
return php_phongo_int64_compare_int64_objects(o1, o2);
332+
}
333+
334+
if (php_phongo_int64_is_int64_object(o1) && php_phongo_int64_is_long_or_double(o2)) {
335+
return php_phongo_int64_compare_with_long_or_float(o1, o2);
336+
}
337+
338+
if (php_phongo_int64_is_long_or_double(o1) && php_phongo_int64_is_int64_object(o2)) {
339+
// Invert the result as we're flipping the values used for comparison
340+
return -1 * php_phongo_int64_compare_with_long_or_float(o2, o1);
341+
}
342+
343+
ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
344+
345+
return 0;
346+
}
347+
284348
static zend_result php_phongo_int64_cast_object(phongo_compat_object_handler_type* readobj, zval* retval, int type)
285349
{
286350
php_phongo_int64_t* intern;
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
--TEST--
2-
MongoDB\BSON\Int64 comparisons with scalars (64-bit values, 64-bit platforms only)
3-
--SKIPIF--
4-
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
2+
MongoDB\BSON\Int64 comparisons with scalars (64-bit values, all platforms)
53
--FILE--
64
<?php
75

86
// Use 2**33 to ensure it still fits in a float
97
$int64 = new MongoDB\BSON\Int64('8589934592');
108

119
$tests = [
12-
'matching int' => 8589934592,
13-
'wrong int' => 8589934593,
10+
'matching float' => (float) 2**33,
11+
'wrong int' => 0,
1412
];
1513

1614
foreach ($tests as $name => $value) {
1715
printf('Testing %s: %s' . PHP_EOL, $name, var_export($int64 == $value, true));
1816
}
1917

18+
var_dump($int64 > 123);
19+
2020
?>
2121
===DONE===
2222
<?php exit(0); ?>
2323
--EXPECT--
24-
Testing matching int: true
24+
Testing matching float: true
2525
Testing wrong int: false
26+
bool(true)
2627
===DONE===
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
MongoDB\BSON\Int64 comparisons with scalars (64-bit values, 64-bit platforms only)
3+
--SKIPIF--
4+
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
5+
--FILE--
6+
<?php
7+
8+
// Use 2**33 to ensure it still fits in a float
9+
$int64 = new MongoDB\BSON\Int64('8589934592');
10+
11+
$tests = [
12+
'matching int' => 8589934592,
13+
'wrong int' => 8589934593,
14+
];
15+
16+
foreach ($tests as $name => $value) {
17+
printf('Testing %s: %s' . PHP_EOL, $name, var_export($int64 == $value, true));
18+
}
19+
20+
?>
21+
===DONE===
22+
<?php exit(0); ?>
23+
--EXPECT--
24+
Testing matching int: true
25+
Testing wrong int: false
26+
===DONE===

0 commit comments

Comments
 (0)