Skip to content

Commit 7516997

Browse files
committed
Merge branch 'phpc-1411'
* phpc-1411: PHPC-1411: Prefer integer types for wtimeout when possible PHPC-1411: Simplify handling of 64-bit values on 32-bit architectures PHPC-1411: Emit warning when truncating 64-bit value PHPC-1411: Accept 64-bit integers for wTimeoutMS
2 parents 2871dfe + 366dcbe commit 7516997

25 files changed

+391
-209
lines changed

phongo_compat.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@
9191
#define ADD_ASSOC_ZVAL(_zv, _key, _value) add_assoc_zval(_zv, _key, _value);
9292
#define ADD_ASSOC_NULL_EX(_zv, _key) add_assoc_null_ex(_zv, ZEND_STRL(_key));
9393
#define ADD_ASSOC_BOOL_EX(_zv, _key, _value) add_assoc_bool_ex(_zv, ZEND_STRL(_key), _value);
94+
#define ZVAL_INT64_STRING(_zv, _value) \
95+
do { \
96+
char tmp[24]; \
97+
int tmp_len; \
98+
tmp_len = snprintf(tmp, sizeof(tmp), "%" PRId64, (_value)); \
99+
ZVAL_STRINGL((_zv), tmp, tmp_len); \
100+
} while (0)
101+
#define ADD_ASSOC_INT64_AS_STRING(_zv, _key, _value) \
102+
do { \
103+
zval z_int; \
104+
ZVAL_INT64_STRING(&z_int, (_value)); \
105+
ADD_ASSOC_ZVAL_EX((_zv), (_key), &z_int); \
106+
} while (0)
94107
#define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len);
95108
#define phongo_free_object_arg zend_object
96109
#define phongo_zpp_char_len size_t
@@ -107,7 +120,7 @@
107120
0 \
108121
} \
109122
}
110-
#else
123+
#else /* PHP_VERSION_ID < 70000 */
111124
#define phongo_char char
112125
#define phongo_long long
113126
#define PHONGO_LONG_FORMAT "ld"
@@ -127,6 +140,21 @@
127140
#define ADD_ASSOC_ZVAL(_zv, _key, _value) add_assoc_zval(_zv, _key, _value);
128141
#define ADD_ASSOC_NULL_EX(_zv, _key) add_assoc_null_ex(_zv, ZEND_STRS(_key));
129142
#define ADD_ASSOC_BOOL_EX(_zv, _key, _value) add_assoc_bool_ex(_zv, ZEND_STRS(_key), _value);
143+
#define ZVAL_INT64_STRING(_zv, _value) \
144+
do { \
145+
char tmp[24]; \
146+
int tmp_len; \
147+
tmp_len = snprintf(tmp, sizeof(tmp), "%" PRId64, (_value)); \
148+
ZVAL_STRINGL((_zv), tmp, tmp_len, 1); \
149+
} while (0)
150+
151+
#define ADD_ASSOC_INT64_AS_STRING(_zv, _key, _value) \
152+
do { \
153+
zval* z_int; \
154+
MAKE_STD_ZVAL(z_int); \
155+
ZVAL_INT64_STRING(z_int, (_value)); \
156+
ADD_ASSOC_ZVAL_EX((_zv), (_key), z_int); \
157+
} while (0)
130158
#define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len, 1);
131159
#define Z_PHPDATE_P(object) ((php_date_obj*) zend_object_store_get_object(object TSRMLS_CC))
132160
#define Z_ISUNDEF(x) !x
@@ -160,6 +188,7 @@
160188
#define ADD_INDEX_INT64(_zv, _index, _value) add_index_long((_zv), (_index), (_value))
161189
#define ADD_NEXT_INDEX_INT64(_zv, _value) add_next_index_long((_zv), (_value))
162190
#define ADD_ASSOC_INT64(_zv, _key, _value) add_assoc_long((_zv), (_key), (_value))
191+
#define ZVAL_INT64(_zv, _value) ZVAL_LONG((_zv), (_value))
163192
#elif SIZEOF_PHONGO_LONG == 4
164193
#if PHP_VERSION_ID >= 70000
165194
#define ADD_INDEX_INT64(_zv, _index, _value) \
@@ -218,6 +247,12 @@
218247
add_assoc_long((_zv), (_key), (_value)); \
219248
}
220249
#endif /* PHP_VERSION_ID */
250+
#define ZVAL_INT64(_zv, _value) \
251+
if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
252+
php_phongo_bson_new_int64((_zv), (_value) TSRMLS_CC); \
253+
} else { \
254+
ZVAL_LONG((_zv), (_value)); \
255+
}
221256
#else /* SIZEOF_PHONGO_LONG != 8 && SIZEOF_PHONGO_LONG != 4 */
222257
#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
223258
#endif /* SIZEOF_PHONGO_LONG */

php_phongo.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,10 +1365,15 @@ void php_phongo_write_concern_to_zval(zval* retval, const mongoc_write_concern_t
13651365
}
13661366

13671367
if (wtimeout != 0) {
1368-
/* Note: PHP currently enforces that wimeoutMS is a 32-bit integer, so
1369-
* casting will never truncate the value. This may change with
1370-
* PHPC-1411. */
1371-
ADD_ASSOC_LONG_EX(retval, "wtimeout", (int32_t) wtimeout);
1368+
#if SIZEOF_LONG == 4
1369+
if (wtimeout > INT32_MAX || wtimeout < INT32_MIN) {
1370+
ADD_ASSOC_INT64_AS_STRING(&retval, "wtimeout", wtimeout);
1371+
} else {
1372+
ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
1373+
}
1374+
#else
1375+
ADD_ASSOC_LONG_EX(retval, "wtimeout", wtimeout);
1376+
#endif
13721377
}
13731378
} /* }}} */
13741379
/* }}} */
@@ -1966,10 +1971,8 @@ static bool php_phongo_apply_wc_options_to_uri(mongoc_uri_t* uri, bson_t* option
19661971
if (!strcasecmp(key, MONGOC_URI_WTIMEOUTMS)) {
19671972
int64_t wtimeout;
19681973

1969-
/* Although the write concern spec defines wtimeoutMS as 64-bit, PHP has
1970-
* historically required 32-bit. This may change with PHPC-1411. */
1971-
if (!BSON_ITER_HOLDS_INT32(&iter)) {
1972-
PHONGO_URI_INVALID_TYPE(iter, "32-bit integer");
1974+
if (!BSON_ITER_HOLDS_INT(&iter)) {
1975+
PHONGO_URI_INVALID_TYPE(iter, "integer");
19731976
mongoc_write_concern_destroy(new_wc);
19741977

19751978
return false;
@@ -2746,6 +2749,24 @@ void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string,
27462749
#endif
27472750
} /* }}} */
27482751

2752+
bool php_phongo_parse_int64(int64_t* retval, const char* data, phongo_zpp_char_len data_len) /* {{{ */
2753+
{
2754+
int64_t value;
2755+
char* endptr = NULL;
2756+
2757+
/* bson_ascii_strtoll() sets errno if conversion fails. If conversion
2758+
* succeeds, we still want to ensure that the entire string was parsed. */
2759+
value = bson_ascii_strtoll(data, &endptr, 10);
2760+
2761+
if (errno || (endptr && endptr != ((const char*) data + data_len))) {
2762+
return false;
2763+
}
2764+
2765+
*retval = value;
2766+
2767+
return true;
2768+
} /* }}} */
2769+
27492770
/* {{{ Memory allocation wrappers */
27502771
static void* php_phongo_malloc(size_t num_bytes) /* {{{ */
27512772
{

php_phongo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ void php_phongo_cursor_to_zval(zval* retval, const mongoc_cursor_t* cursor);
163163
void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions TSRMLS_DC);
164164
int php_phongo_set_monitoring_callbacks(mongoc_client_t* client);
165165

166+
bool php_phongo_parse_int64(int64_t* retval, const char* data, phongo_zpp_char_len data_len);
167+
166168
zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson TSRMLS_DC);
167169
zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson TSRMLS_DC);
168170

src/BSON/Int64.c

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,8 @@ static bool php_phongo_int64_init(php_phongo_int64_t* intern, int64_t integer) /
4747
static bool php_phongo_int64_init_from_string(php_phongo_int64_t* intern, const char* s_integer, phongo_zpp_char_len s_integer_len TSRMLS_DC) /* {{{ */
4848
{
4949
int64_t integer;
50-
char* endptr = NULL;
5150

52-
/* bson_ascii_strtoll() sets errno if conversion fails. If conversion
53-
* succeeds, we still want to ensure that the entire string was parsed. */
54-
integer = bson_ascii_strtoll(s_integer, &endptr, 10);
55-
56-
if (errno || (endptr && endptr != ((const char*) s_integer + s_integer_len))) {
51+
if (!php_phongo_parse_int64(&integer, s_integer, s_integer_len)) {
5752
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error parsing \"%s\" as 64-bit integer for %s initialization", s_integer, ZSTR_VAL(php_phongo_int64_ce->name));
5853
return false;
5954
}
@@ -88,39 +83,31 @@ static bool php_phongo_int64_init_from_hash(php_phongo_int64_t* intern, HashTabl
8883
static PHP_METHOD(Int64, __toString)
8984
{
9085
php_phongo_int64_t* intern;
91-
char s_integer[24];
92-
int s_integer_len;
9386

9487
if (zend_parse_parameters_none() == FAILURE) {
9588
return;
9689
}
9790

9891
intern = Z_INT64_OBJ_P(getThis());
9992

100-
s_integer_len = snprintf(s_integer, sizeof(s_integer), "%" PRId64, intern->integer);
101-
102-
PHONGO_RETVAL_STRINGL(s_integer, s_integer_len);
93+
ZVAL_INT64_STRING(return_value, intern->integer);
10394
} /* }}} */
10495

10596
/* {{{ proto array MongoDB\BSON\Int64::jsonSerialize()
10697
*/
10798
static PHP_METHOD(Int64, jsonSerialize)
10899
{
109100
php_phongo_int64_t* intern;
110-
char s_integer[24];
111-
int s_integer_len;
112101

113102
if (zend_parse_parameters_none() == FAILURE) {
114103
return;
115104
}
116105

117106
intern = Z_INT64_OBJ_P(getThis());
118107

119-
s_integer_len = snprintf(s_integer, sizeof(s_integer), "%" PRId64, intern->integer);
120-
121108
array_init_size(return_value, 1);
122109

123-
ADD_ASSOC_STRINGL(return_value, "$numberLong", s_integer, s_integer_len);
110+
ADD_ASSOC_INT64_AS_STRING(return_value, "$numberLong", intern->integer);
124111
} /* }}} */
125112

126113
/* {{{ proto string MongoDB\BSON\Int64::serialize()
@@ -131,24 +118,20 @@ static PHP_METHOD(Int64, serialize)
131118
ZVAL_RETVAL_TYPE retval;
132119
php_serialize_data_t var_hash;
133120
smart_str buf = { 0 };
134-
char s_integer[24];
135-
int s_integer_len;
136121

137122
if (zend_parse_parameters_none() == FAILURE) {
138123
return;
139124
}
140125

141126
intern = Z_INT64_OBJ_P(getThis());
142127

143-
s_integer_len = snprintf(s_integer, sizeof(s_integer), "%" PRId64, intern->integer);
144-
145128
#if PHP_VERSION_ID >= 70000
146129
array_init_size(&retval, 1);
147-
ADD_ASSOC_STRINGL(&retval, "integer", s_integer, s_integer_len);
130+
ADD_ASSOC_INT64_AS_STRING(&retval, "integer", intern->integer);
148131
#else
149132
ALLOC_INIT_ZVAL(retval);
150133
array_init_size(retval, 1);
151-
ADD_ASSOC_STRINGL(retval, "integer", s_integer, s_integer_len);
134+
ADD_ASSOC_INT64_AS_STRING(retval, "integer", intern->integer);
152135
#endif
153136

154137
PHP_VAR_SERIALIZE_INIT(var_hash);
@@ -323,8 +306,6 @@ HashTable* php_phongo_int64_get_properties_hash(zval* object, bool is_debug TSRM
323306
{
324307
php_phongo_int64_t* intern;
325308
HashTable* props;
326-
char s_integer[24];
327-
int s_integer_len;
328309

329310
intern = Z_INT64_OBJ_P(object);
330311

@@ -334,21 +315,19 @@ HashTable* php_phongo_int64_get_properties_hash(zval* object, bool is_debug TSRM
334315
return props;
335316
}
336317

337-
s_integer_len = snprintf(s_integer, sizeof(s_integer), "%" PRId64, intern->integer);
338-
339318
#if PHP_VERSION_ID >= 70000
340319
{
341320
zval value;
342321

343-
ZVAL_STRINGL(&value, s_integer, s_integer_len);
322+
ZVAL_INT64_STRING(&value, intern->integer);
344323
zend_hash_str_update(props, "integer", sizeof("integer") - 1, &value);
345324
}
346325
#else
347326
{
348327
zval* value;
349328

350329
MAKE_STD_ZVAL(value);
351-
ZVAL_STRINGL(value, s_integer, s_integer_len, 1);
330+
ZVAL_INT64_STRING(value, intern->integer);
352331
zend_hash_update(props, "integer", sizeof("integer"), &value, sizeof(value), NULL);
353332
}
354333
#endif

src/BSON/Timestamp.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,13 @@ static bool php_phongo_timestamp_init(php_phongo_timestamp_t* intern, int64_t in
5858
static bool php_phongo_timestamp_init_from_string(php_phongo_timestamp_t* intern, const char* s_increment, phongo_zpp_char_len s_increment_len, const char* s_timestamp, phongo_zpp_char_len s_timestamp_len TSRMLS_DC) /* {{{ */
5959
{
6060
int64_t increment, timestamp;
61-
char* endptr = NULL;
6261

63-
/* bson_ascii_strtoll() sets errno if conversion fails. If conversion
64-
* succeeds, we still want to ensure that the entire string was parsed. */
65-
66-
increment = bson_ascii_strtoll(s_increment, &endptr, 10);
67-
68-
if (errno || (endptr && endptr != ((const char*) s_increment + s_increment_len))) {
62+
if (!php_phongo_parse_int64(&increment, s_increment, s_increment_len)) {
6963
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error parsing \"%s\" as 64-bit integer increment for %s initialization", s_increment, ZSTR_VAL(php_phongo_timestamp_ce->name));
7064
return false;
7165
}
7266

73-
timestamp = bson_ascii_strtoll(s_timestamp, &endptr, 10);
74-
75-
if (errno || (endptr && endptr != ((const char*) s_timestamp + s_timestamp_len))) {
67+
if (!php_phongo_parse_int64(&timestamp, s_timestamp, s_timestamp_len)) {
7668
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error parsing \"%s\" as 64-bit integer timestamp for %s initialization", s_timestamp, ZSTR_VAL(php_phongo_timestamp_ce->name));
7769
return false;
7870
}

0 commit comments

Comments
 (0)