Skip to content

Commit 8604fb4

Browse files
PHP-151 - All numeric type constructors should error out with RangeException for out-of-range parameters
1 parent 71952d9 commit 8604fb4

File tree

8 files changed

+311
-225
lines changed

8 files changed

+311
-225
lines changed

ext/php_driver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ typedef int pid_t;
3636
#include <process.h>
3737
#endif
3838

39+
#ifdef WIN32
40+
# define LL_FORMAT "%I64d"
41+
#else
42+
# define LL_FORMAT "%lld"
43+
#endif
44+
3945
#if PHP_VERSION_ID < 50600
4046
# error PHP 5.6.0 or later is required in order to build the driver
4147
#endif

ext/src/Bigint.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,7 @@ static int
5555
to_string(zval *result, php_driver_numeric *bigint TSRMLS_DC)
5656
{
5757
char *string;
58-
#ifdef WIN32
59-
spprintf(&string, 0, "%I64d", (long long int) bigint->data.bigint.value);
60-
#else
61-
spprintf(&string, 0, "%lld", (long long int) bigint->data.bigint.value);
62-
#endif
58+
spprintf(&string, 0, LL_FORMAT, (long long int) bigint->data.bigint.value);
6359
PHP5TO7_ZVAL_STRING(result, string);
6460
efree(string);
6561
return SUCCESS;
@@ -85,6 +81,15 @@ php_driver_bigint_init(INTERNAL_FUNCTION_PARAMETERS)
8581
if (Z_TYPE_P(value) == IS_LONG) {
8682
self->data.bigint.value = (cass_int64_t) Z_LVAL_P(value);
8783
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
84+
double double_value = Z_DVAL_P(value);
85+
86+
if (double_value > INT64_MAX || double_value < INT64_MIN) {
87+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
88+
"value must be between " LL_FORMAT " and " LL_FORMAT ", %g given",
89+
INT64_MIN, INT64_MAX, double_value);
90+
return;
91+
}
92+
8893
self->data.bigint.value = (cass_int64_t) Z_DVAL_P(value);
8994
} else if (Z_TYPE_P(value) == IS_STRING) {
9095
if (!php_driver_parse_bigint(Z_STRVAL_P(value), Z_STRLEN_P(value),

ext/src/Duration.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ static int get_int32(zval* value, cass_int32_t* destination, const char* param_n
2929
cass_int64_t long_value = Z_LVAL_P(value);
3030

3131
if (long_value > INT32_MAX || long_value < INT32_MIN) {
32-
zend_throw_exception_ex(php_driver_invalid_argument_exception_ce, 0 TSRMLS_CC,
33-
"%s must be between %d and %d, %lld given",
32+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
33+
"%s must be between %d and %d, " LL_FORMAT " given",
3434
param_name, INT32_MIN, INT32_MAX, long_value);
3535
return 0;
3636
}
@@ -40,7 +40,7 @@ static int get_int32(zval* value, cass_int32_t* destination, const char* param_n
4040
double double_value = Z_DVAL_P(value);
4141

4242
if (double_value > INT32_MAX || double_value < INT32_MIN) {
43-
zend_throw_exception_ex(php_driver_invalid_argument_exception_ce, 0 TSRMLS_CC,
43+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
4444
"%s must be between %d and %d, %g given",
4545
param_name, INT32_MIN, INT32_MAX, double_value);
4646
return 0;
@@ -53,8 +53,8 @@ static int get_int32(zval* value, cass_int32_t* destination, const char* param_n
5353
}
5454

5555
if (parsed_big_int > INT32_MAX || parsed_big_int < INT32_MIN) {
56-
zend_throw_exception_ex(php_driver_invalid_argument_exception_ce, 0 TSRMLS_CC,
57-
"%s must be between %d and %d, %lld given",
56+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
57+
"%s must be between %d and %d, " LL_FORMAT " given",
5858
param_name, INT32_MIN, INT32_MAX, parsed_big_int);
5959
return 0;
6060
}
@@ -65,8 +65,8 @@ static int get_int32(zval* value, cass_int32_t* destination, const char* param_n
6565
cass_int64_t bigint_value = bigint->data.bigint.value;
6666

6767
if (bigint_value > INT32_MAX || bigint_value < INT32_MIN) {
68-
zend_throw_exception_ex(php_driver_invalid_argument_exception_ce, 0 TSRMLS_CC,
69-
"%s must be between %d and %d, %lld given",
68+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
69+
"%s must be between %d and %d, " LL_FORMAT " given",
7070
param_name, INT32_MIN, INT32_MAX, bigint_value);
7171
return 0;
7272
}

ext/src/Smallint.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,45 @@ php_driver_smallint_init(INTERNAL_FUNCTION_PARAMETERS)
7676
} else {
7777
if (Z_TYPE_P(value) == IS_LONG) {
7878
number = (cass_int32_t) Z_LVAL_P(value);
79+
80+
if (number < INT16_MIN || number > INT16_MAX) {
81+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
82+
"value must be between -32768 and 32767, %ld given", Z_LVAL_P(value));
83+
return;
84+
}
7985
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
8086
number = (cass_int32_t) Z_DVAL_P(value);
87+
88+
if (number < INT16_MIN || number > INT16_MAX) {
89+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
90+
"value must be between -32768 and 32767, %g given", Z_DVAL_P(value));
91+
return;
92+
}
8193
} else if (Z_TYPE_P(value) == IS_STRING) {
8294
if (!php_driver_parse_int(Z_STRVAL_P(value), Z_STRLEN_P(value),
8395
&number TSRMLS_CC)) {
96+
97+
// If the parsing function fails, it would have set an exception. If it's
98+
// a range error, the error message would be wrong because the parsing
99+
// function supports all 32-bit values, so the "valid" range it reports would
100+
// be too large for Smallint. Reset the exception in that case.
101+
102+
if (errno == ERANGE) {
103+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
104+
"value must be between -32768 and 32767, %s given", Z_STRVAL_P(value));
105+
}
106+
return;
107+
}
108+
109+
if (number < INT16_MIN || number > INT16_MAX) {
110+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
111+
"value must be between -32768 and 32767, %s given", Z_STRVAL_P(value));
84112
return;
85113
}
86114
} else {
87115
INVALID_ARGUMENT(value, "a long, a double, a numeric string or a " \
88116
PHP_DRIVER_NAMESPACE "\\Smallint");
89117
}
90-
if (number < INT16_MIN || number > INT16_MAX) {
91-
INVALID_ARGUMENT(value, ("between -32768 and 32767"));
92-
}
93118
self->data.smallint.value = (cass_int16_t) number;
94119
}
95120
}

ext/src/Tinyint.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,44 @@ php_driver_tinyint_init(INTERNAL_FUNCTION_PARAMETERS)
7676
} else {
7777
if (Z_TYPE_P(value) == IS_LONG) {
7878
number = (cass_int32_t) Z_LVAL_P(value);
79+
80+
if (number < INT8_MIN || number > INT8_MAX) {
81+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
82+
"value must be between -128 and 127, %ld given", Z_LVAL_P(value));
83+
return;
84+
}
7985
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
8086
number = (cass_int32_t) Z_DVAL_P(value);
87+
88+
if (number < INT8_MIN || number > INT8_MAX) {
89+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
90+
"value must be between -128 and 127, %g given", Z_DVAL_P(value));
91+
return;
92+
}
8193
} else if (Z_TYPE_P(value) == IS_STRING) {
8294
if (!php_driver_parse_int(Z_STRVAL_P(value), Z_STRLEN_P(value),
8395
&number TSRMLS_CC)) {
96+
// If the parsing function fails, it would have set an exception. If it's
97+
// a range error, the error message would be wrong because the parsing
98+
// function supports all 32-bit values, so the "valid" range it reports would
99+
// be too large for Tinyint. Reset the exception in that case.
100+
101+
if (errno == ERANGE) {
102+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
103+
"value must be between -128 and 127, %s given", Z_STRVAL_P(value));
104+
}
105+
return;
106+
}
107+
108+
if (number < INT8_MIN || number > INT8_MAX) {
109+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
110+
"value must be between -128 and 127, %s given", Z_STRVAL_P(value));
84111
return;
85112
}
86113
} else {
87114
INVALID_ARGUMENT(value, "a long, a double, a numeric string or a " \
88115
PHP_DRIVER_NAMESPACE "\\Tinyint");
89116
}
90-
if (number < INT8_MIN || number > INT8_MAX) {
91-
INVALID_ARGUMENT(value, ("between -128 and 127"));
92-
}
93117
self->data.tinyint.value = (cass_int8_t) number;
94118
}
95119
}

ext/util/math.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,8 @@ php_driver_parse_int(char* in, int in_len, cass_int32_t* number TSRMLS_DC)
147147
}
148148

149149
if (errno == ERANGE) {
150-
if (*number == INT_MAX) {
151-
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC, "Value is too big for int: '%s'", in);
152-
} else {
153-
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC, "Value is too small for int: '%s'", in);
154-
}
150+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
151+
"value must be between %d and %d, %s given", INT_MIN, INT_MAX, in);
155152
return 0;
156153
}
157154

@@ -200,11 +197,8 @@ php_driver_parse_bigint(char *in, int in_len, cass_int64_t *number TSRMLS_DC)
200197
}
201198

202199
if (errno == ERANGE) {
203-
if (*number == INT64_MAX) {
204-
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC, "Value is too big for bigint: '%s'", in);
205-
} else {
206-
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC, "Value is too small for bigint: '%s'", in);
207-
}
200+
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
201+
"value must be between " LL_FORMAT " and " LL_FORMAT ", %s given", INT64_MIN, INT64_MAX, in);
208202
return 0;
209203
}
210204

tests/unit/Cassandra/DurationTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function testStringArgParseError()
4949
}
5050

5151
/**
52-
* @expectedException InvalidArgumentException
52+
* @expectedException RangeException
5353
* @expectedExceptionMessage nanos must be between -2147483648 and 2147483647, 8589934592 given
5454
*/
5555
public function testStringArgOverflowError()
@@ -58,7 +58,7 @@ public function testStringArgOverflowError()
5858
}
5959

6060
/**
61-
* @expectedException InvalidArgumentException
61+
* @expectedException RangeException
6262
* @expectedExceptionMessage nanos must be between -2147483648 and 2147483647, -8589934592 given
6363
*/
6464
public function testStringArgUnderflowError()
@@ -67,7 +67,7 @@ public function testStringArgUnderflowError()
6767
}
6868

6969
/**
70-
* @expectedException InvalidArgumentException
70+
* @expectedException RangeException
7171
* @expectedExceptionMessage nanos must be between -2147483648 and 2147483647, 8589934592 given
7272
*/
7373
public function testBigintArgOverflowError()
@@ -76,7 +76,7 @@ public function testBigintArgOverflowError()
7676
}
7777

7878
/**
79-
* @expectedException InvalidArgumentException
79+
* @expectedException RangeException
8080
* @expectedExceptionMessage nanos must be between -2147483648 and 2147483647, -8589934592 given
8181
*/
8282
public function testBigintArgUnderflowError()
@@ -85,7 +85,7 @@ public function testBigintArgUnderflowError()
8585
}
8686

8787
/**
88-
* @expectedException InvalidArgumentException
88+
* @expectedException RangeException
8989
* @expectedExceptionMessageRegExp /days must be between -2147483648 and 2147483647, 8\.?58993.* given/
9090
*/
9191
public function testLongArgOverflowError()
@@ -94,7 +94,7 @@ public function testLongArgOverflowError()
9494
}
9595

9696
/**
97-
* @expectedException InvalidArgumentException
97+
* @expectedException RangeException
9898
* @expectedExceptionMessageRegExp /days must be between -2147483648 and 2147483647, -8\.?58993.* given/
9999
*/
100100
public function testLongArgUnderflowError()
@@ -103,7 +103,7 @@ public function testLongArgUnderflowError()
103103
}
104104

105105
/**
106-
* @expectedException InvalidArgumentException
106+
* @expectedException RangeException
107107
* @expectedExceptionMessage months must be between -2147483648 and 2147483647, 8.58993e+9 given
108108
*/
109109
public function testDoubleArgOverflowError()
@@ -112,7 +112,7 @@ public function testDoubleArgOverflowError()
112112
}
113113

114114
/**
115-
* @expectedException InvalidArgumentException
115+
* @expectedException RangeException
116116
* @expectedExceptionMessage months must be between -2147483648 and 2147483647, -8.58993e+9 given
117117
*/
118118
public function testDoubleArgUnderflowError()

0 commit comments

Comments
 (0)