Skip to content

Commit 6bcba59

Browse files
committed
PHPC-544: Consult SIZEOF_ZEND_LONG for 64-bit integer support
Define phongo_long and SIZEOF_PHONGO_LONG in compatibility header. On PHP 7, this will ensure we use zend_long and SIZEOF_ZEND_LONG instead of relying on long and SIZEOF_LONG. Additionally, this adds an else condition to report a build error if the architecture is neither 32-bit nor 64-bit.
1 parent 915e089 commit 6bcba59

File tree

3 files changed

+135
-33
lines changed

3 files changed

+135
-33
lines changed

phongo_compat.h

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -92,34 +92,6 @@
9292
# define ARG_UNUSED
9393
#endif
9494

95-
#if SIZEOF_LONG == 4
96-
# define ADD_INDEX_INT64(zval, index, value) \
97-
if (value > LONG_MAX || value < LONG_MIN) { \
98-
char *tmp; \
99-
int tmp_len; \
100-
mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Integer overflow detected on your platform: %lld", value); \
101-
tmp_len = spprintf(&tmp, 0, "%lld", value); \
102-
ADD_INDEX_STRINGL(zval, index, tmp, tmp_len); \
103-
efree(tmp); \
104-
} else { \
105-
add_index_long(zval, index, val); \
106-
}
107-
# define ADD_ASSOC_INT64(zval, key, value) \
108-
if (value > LONG_MAX || value < LONG_MIN) { \
109-
char *tmp; \
110-
int tmp_len; \
111-
mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Integer overflow detected on your platform: %lld", value); \
112-
tmp_len = spprintf(&tmp, 0, "%lld", value); \
113-
ADD_ASSOC_STRING_EX(zval, key, strlen(key), tmp, tmp_len); \
114-
efree(tmp); \
115-
} else { \
116-
add_assoc_long(zval, key, value); \
117-
}
118-
#else
119-
# define ADD_INDEX_INT64(zval, index, value) add_index_long(zval, index, value)
120-
# define ADD_ASSOC_INT64(zval, key, value) add_assoc_long(zval, key, value);
121-
#endif
122-
12395
#ifdef HAVE_ATOLL
12496
# define STRTOLL(s) atoll(s)
12597
#else
@@ -151,6 +123,8 @@
151123
# define phongo_char zend_string
152124
# define phongo_char_pdup(str) pestrdup(filename->val, 1)
153125
# define phongo_char_free(str) zend_string_release(str)
126+
# define phongo_long zend_long
127+
# define SIZEOF_PHONGO_LONG SIZEOF_ZEND_LONG
154128
# define phongo_str(str) str->val
155129
# define phongo_create_object_retval zend_object*
156130
# define PHONGO_ALLOC_OBJECT_T(_obj_t, _class_type) (_obj_t *)ecalloc(1, sizeof(_obj_t)+zend_object_properties_size(_class_type))
@@ -178,6 +152,8 @@
178152
# define phongo_char char
179153
# define phongo_char_pdup(str) pestrdup(filename, 1)
180154
# define phongo_char_free(str) _efree(str ZEND_FILE_LINE_CC ZEND_FILE_LINE_CC)
155+
# define phongo_long long
156+
# define SIZEOF_PHONGO_LONG SIZEOF_LONG
181157
# define phongo_str(str) str
182158
# define phongo_create_object_retval zend_object_value
183159
# define PHONGO_ALLOC_OBJECT_T(_obj_t, _class_type) (_obj_t *)ecalloc(1, sizeof(_obj_t))
@@ -206,6 +182,35 @@
206182
# define PHP_STREAM_CONTEXT(stream) ((php_stream_context*) (stream)->context)
207183
#endif
208184

185+
#if SIZEOF_PHONGO_LONG == 8
186+
# define ADD_INDEX_INT64(zval, index, value) add_index_long(zval, index, value)
187+
# define ADD_ASSOC_INT64(zval, key, value) add_assoc_long(zval, key, value)
188+
#elif SIZEOF_PHONGO_LONG == 4
189+
# define ADD_INDEX_INT64(zval, index, value) \
190+
if (value > LONG_MAX || value < LONG_MIN) { \
191+
char *tmp; \
192+
int tmp_len; \
193+
mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Integer overflow detected on your platform: %lld", value); \
194+
tmp_len = spprintf(&tmp, 0, "%lld", value); \
195+
ADD_INDEX_STRINGL(zval, index, tmp, tmp_len); \
196+
efree(tmp); \
197+
} else { \
198+
add_index_long(zval, index, val); \
199+
}
200+
# define ADD_ASSOC_INT64(zval, key, value) \
201+
if (value > LONG_MAX || value < LONG_MIN) { \
202+
char *tmp; \
203+
int tmp_len; \
204+
mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Integer overflow detected on your platform: %lld", value); \
205+
tmp_len = spprintf(&tmp, 0, "%lld", value); \
206+
ADD_ASSOC_STRING_EX(zval, key, strlen(key), tmp, tmp_len); \
207+
efree(tmp); \
208+
} else { \
209+
add_assoc_long(zval, key, value); \
210+
}
211+
#else
212+
# error Unsupported architecture (integers are neither 32-bit nor 64-bit)
213+
#endif
209214

210215
void *x509_from_zval(zval *zval TSRMLS_DC);
211216
void phongo_add_exception_prop(const char *prop, int prop_len, zval *value TSRMLS_DC);

src/bson.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,18 @@
4141
#include "php_phongo.h"
4242
#include "php_bson.h"
4343

44-
#if SIZEOF_LONG == 8
45-
# define BSON_APPEND_INT(b, key, keylen, val) \
44+
#if SIZEOF_PHONGO_LONG == 8
45+
# define BSON_APPEND_INT(b, key, keylen, val) \
4646
if (val > INT_MAX || val < INT_MIN) { \
4747
bson_append_int64(b, key, keylen, val); \
4848
} else { \
4949
bson_append_int32(b, key, keylen, val); \
5050
}
51-
#elif SIZEOF_LONG == 4
52-
# define BSON_APPEND_INT(b, key, keylen, val) \
53-
bson_append_int32(b, key, keylen, val);
51+
#elif SIZEOF_PHONGO_LONG == 4
52+
# define BSON_APPEND_INT(b, key, keylen, val) \
53+
bson_append_int32(b, key, keylen, val)
54+
#else
55+
# error Unsupported architecture (integers are neither 32-bit nor 64-bit)
5456
#endif
5557

5658
#undef MONGOC_LOG_DOMAIN

tests/bson/bug0544.phpt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
--TEST--
2+
PHPC-544: Consult SIZEOF_ZEND_LONG for 64-bit integer support
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+
--INI--
7+
mongodb.debug=stderr
8+
--FILE--
9+
<?php
10+
11+
require_once __DIR__ . "/../utils/basic.inc";
12+
13+
$tests = [
14+
['x' => -2147483648],
15+
['x' => 2147483647],
16+
['x' => -4294967294],
17+
['x' => 4294967294],
18+
['x' => -4294967295],
19+
['x' => 4294967295],
20+
['x' => -9223372036854775807],
21+
['x' => 9223372036854775807],
22+
];
23+
24+
foreach ($tests as $test) {
25+
$bson = fromPHP($test);
26+
/* Note: Although libbson can parse the extended JSON representation for
27+
* 64-bit integers (i.e. "$numberLong"), it currently prints them as
28+
* doubles (see: https://jira.mongodb.org/browse/CDRIVER-375). */
29+
printf("Test %s\n", toJSON($bson));
30+
hex_dump($bson);
31+
var_dump(toPHP($bson));
32+
echo "\n";
33+
}
34+
35+
?>
36+
===DONE===
37+
<?php exit(0); ?>
38+
--EXPECTF--
39+
Test { "x" : -2147483648 }
40+
0 : 0c 00 00 00 10 78 00 00 00 00 80 00 [.....x......]
41+
object(stdClass)#%d (%d) {
42+
["x"]=>
43+
int(-2147483648)
44+
}
45+
46+
Test { "x" : 2147483647 }
47+
0 : 0c 00 00 00 10 78 00 ff ff ff 7f 00 [.....x......]
48+
object(stdClass)#%d (%d) {
49+
["x"]=>
50+
int(2147483647)
51+
}
52+
53+
Test { "x" : -4294967294 }
54+
0 : 10 00 00 00 12 78 00 02 00 00 00 ff ff ff ff 00 [.....x..........]
55+
object(stdClass)#%d (%d) {
56+
["x"]=>
57+
int(-4294967294)
58+
}
59+
60+
Test { "x" : 4294967294 }
61+
0 : 10 00 00 00 12 78 00 fe ff ff ff 00 00 00 00 00 [.....x..........]
62+
object(stdClass)#%d (%d) {
63+
["x"]=>
64+
int(4294967294)
65+
}
66+
67+
Test { "x" : -4294967295 }
68+
0 : 10 00 00 00 12 78 00 01 00 00 00 ff ff ff ff 00 [.....x..........]
69+
object(stdClass)#%d (%d) {
70+
["x"]=>
71+
int(-4294967295)
72+
}
73+
74+
Test { "x" : 4294967295 }
75+
0 : 10 00 00 00 12 78 00 ff ff ff ff 00 00 00 00 00 [.....x..........]
76+
object(stdClass)#%d (%d) {
77+
["x"]=>
78+
int(4294967295)
79+
}
80+
81+
Test { "x" : -9223372036854775807 }
82+
0 : 10 00 00 00 12 78 00 01 00 00 00 00 00 00 80 00 [.....x..........]
83+
object(stdClass)#%d (%d) {
84+
["x"]=>
85+
int(-9223372036854775807)
86+
}
87+
88+
Test { "x" : 9223372036854775807 }
89+
0 : 10 00 00 00 12 78 00 ff ff ff ff ff ff ff 7f 00 [.....x..........]
90+
object(stdClass)#%d (%d) {
91+
["x"]=>
92+
int(9223372036854775807)
93+
}
94+
95+
===DONE===

0 commit comments

Comments
 (0)