Skip to content

Commit a4bc271

Browse files
committed
Revert "ext/gmp: Fix segfault when null is encountered on an overloaded operator"
This reverts commit 9cea1a2.
1 parent e1a8d54 commit a4bc271

6 files changed

+46
-103
lines changed

ext/gmp/gmp.c

Lines changed: 11 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ typedef void (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, gmp_ulong);
199199
typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
200200
typedef gmp_ulong (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, gmp_ulong);
201201

202-
static inline zend_result gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator);
202+
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator);
203203
static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero);
204204
static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op);
205205

@@ -356,7 +356,10 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva
356356
}
357357

358358
#define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \
359-
return gmp_zval_binary_ui_op(result, op1, op2, op, uop, check_b_zero, /* is_operator */ true);
359+
gmp_zval_binary_ui_op( \
360+
result, op1, op2, op, uop, check_b_zero, /* is_operator */ true); \
361+
if (UNEXPECTED(EG(exception))) { return FAILURE; } \
362+
return SUCCESS;
360363

361364
#define DO_BINARY_UI_OP(op) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
362365
#define DO_BINARY_OP(op) DO_BINARY_UI_OP_EX(op, NULL, 0)
@@ -434,7 +437,7 @@ static int gmp_compare(zval *op1, zval *op2) /* {{{ */
434437
/* An error/exception occurs if one of the operands is not a numeric string
435438
* or an object which is different from GMP */
436439
if (EG(exception)) {
437-
return ZEND_UNCOMPARABLE;
440+
return 1;
438441
}
439442
/* result can only be a zend_long if gmp_cmp hasn't thrown an Error */
440443
ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
@@ -616,16 +619,7 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
616619
case IS_STRING: {
617620
return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos);
618621
}
619-
case IS_NULL:
620-
/* For operator overloading just reject null */
621-
if (arg_pos == 0) {
622-
return FAILURE;
623-
}
624-
ZEND_FALLTHROUGH;
625-
case IS_DOUBLE:
626-
case IS_FALSE:
627-
case IS_TRUE:
628-
{
622+
default: {
629623
zend_long lval;
630624
if (!zend_parse_arg_long_slow(val, &lval, arg_pos)) {
631625
if (arg_pos == 0) {
@@ -641,12 +635,6 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
641635
mpz_set_si(gmpnumber, lval);
642636
return SUCCESS;
643637
}
644-
default:
645-
if (arg_pos != 0) {
646-
zend_argument_type_error(arg_pos,
647-
"must be of type GMP|string|int, %s given", zend_zval_type_name(val));
648-
}
649-
return FAILURE;
650638
}
651639
}
652640
/* }}} */
@@ -714,45 +702,18 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operat
714702
/* {{{ gmp_zval_binary_ui_op
715703
Execute GMP binary operation.
716704
*/
717-
static inline zend_result gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator)
705+
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator)
718706
{
719707
mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result;
720708
gmp_temp_t temp_a, temp_b;
721709

722-
/* Inline version of FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, is_operator ? 0 : 1);
723-
* because we cannot use RETURN_THROWS() here */
724-
if (IS_GMP(a_arg)) {
725-
gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
726-
temp_a.is_used = 0;
727-
} else {
728-
mpz_init(temp_a.num);
729-
if (convert_to_gmp(temp_a.num, a_arg, 0, is_operator ? 0 : 1) == FAILURE) {
730-
mpz_clear(temp_a.num);
731-
return FAILURE;
732-
}
733-
temp_a.is_used = 1;
734-
gmpnum_a = temp_a.num;
735-
}
710+
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, is_operator ? 0 : 1);
736711

737712
if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
738713
gmpnum_b = NULL;
739714
temp_b.is_used = 0;
740715
} else {
741-
/* Inline version of FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, is_operator ? 0 : 2);
742-
* because we cannot use RETURN_THROWS() here */
743-
if (IS_GMP(b_arg)) {
744-
gmpnum_b = GET_GMP_FROM_ZVAL(b_arg);
745-
temp_b.is_used = 0;
746-
} else {
747-
mpz_init(temp_b.num);
748-
if (convert_to_gmp(temp_b.num, b_arg, 0, is_operator ? 0 : 2) == FAILURE) {
749-
mpz_clear(temp_b.num);
750-
FREE_GMP_TEMP(temp_a);
751-
return FAILURE;
752-
}
753-
temp_b.is_used = 1;
754-
gmpnum_b = temp_b.num;
755-
}
716+
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, is_operator ? 0 : 2);
756717
}
757718

758719
if (check_b_zero) {
@@ -771,7 +732,7 @@ static inline zend_result gmp_zval_binary_ui_op(zval *return_value, zval *a_arg,
771732
}
772733
FREE_GMP_TEMP(temp_a);
773734
FREE_GMP_TEMP(temp_b);
774-
return FAILURE;
735+
RETURN_THROWS();
775736
}
776737
}
777738

@@ -785,7 +746,6 @@ static inline zend_result gmp_zval_binary_ui_op(zval *return_value, zval *a_arg,
785746

786747
FREE_GMP_TEMP(temp_a);
787748
FREE_GMP_TEMP(temp_b);
788-
return SUCCESS;
789749
}
790750
/* }}} */
791751

ext/gmp/tests/overloading_with_array.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,18 @@ try {
7171

7272
?>
7373
--EXPECT--
74-
TypeError: Unsupported operand types: GMP + array
75-
TypeError: Unsupported operand types: GMP - array
76-
TypeError: Unsupported operand types: GMP * array
77-
TypeError: Unsupported operand types: GMP / array
78-
TypeError: Unsupported operand types: GMP % array
74+
TypeError: Number must be of type GMP|string|int, array given
75+
TypeError: Number must be of type GMP|string|int, array given
76+
TypeError: Number must be of type GMP|string|int, array given
77+
TypeError: Number must be of type GMP|string|int, array given
78+
TypeError: Number must be of type GMP|string|int, array given
7979
object(GMP)#3 (1) {
8080
["num"]=>
8181
string(1) "1"
8282
}
83-
TypeError: Unsupported operand types: GMP | array
84-
TypeError: Unsupported operand types: GMP & array
85-
TypeError: Unsupported operand types: GMP ^ array
83+
TypeError: Number must be of type GMP|string|int, array given
84+
TypeError: Number must be of type GMP|string|int, array given
85+
TypeError: Number must be of type GMP|string|int, array given
8686
object(GMP)#2 (1) {
8787
["num"]=>
8888
string(2) "42"

ext/gmp/tests/overloading_with_null.phpt

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
GMP operator overloading does not support null
33
--EXTENSIONS--
44
gmp
5+
--XFAIL--
6+
Test showcasing segfaulting behaviour
57
--FILE--
68
<?php
79

@@ -71,23 +73,4 @@ try {
7173

7274
?>
7375
--EXPECT--
74-
int(42)
75-
int(42)
76-
int(0)
77-
DivisionByZeroError: Division by zero
78-
DivisionByZeroError: Modulo by zero
79-
object(GMP)#2 (1) {
80-
["num"]=>
81-
string(1) "1"
82-
}
83-
int(42)
84-
int(0)
85-
int(42)
86-
object(GMP)#2 (1) {
87-
["num"]=>
88-
string(2) "42"
89-
}
90-
object(GMP)#2 (1) {
91-
["num"]=>
92-
string(2) "42"
93-
}
76+
SEGFAULT

ext/gmp/tests/overloading_with_object_not_stringable.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,20 @@ try {
7272

7373
?>
7474
--EXPECTF--
75-
TypeError: Unsupported operand types: GMP + stdClass
76-
TypeError: Unsupported operand types: GMP - stdClass
77-
TypeError: Unsupported operand types: GMP * stdClass
78-
TypeError: Unsupported operand types: GMP / stdClass
79-
TypeError: Unsupported operand types: GMP % stdClass
75+
TypeError: Number must be of type GMP|string|int, stdClass given
76+
TypeError: Number must be of type GMP|string|int, stdClass given
77+
TypeError: Number must be of type GMP|string|int, stdClass given
78+
TypeError: Number must be of type GMP|string|int, stdClass given
79+
TypeError: Number must be of type GMP|string|int, stdClass given
8080

8181
Warning: Object of class stdClass could not be converted to int in %s on line %d
8282
object(GMP)#4 (1) {
8383
["num"]=>
8484
string(2) "42"
8585
}
86-
TypeError: Unsupported operand types: GMP | stdClass
87-
TypeError: Unsupported operand types: GMP & stdClass
88-
TypeError: Unsupported operand types: GMP ^ stdClass
86+
TypeError: Number must be of type GMP|string|int, stdClass given
87+
TypeError: Number must be of type GMP|string|int, stdClass given
88+
TypeError: Number must be of type GMP|string|int, stdClass given
8989

9090
Warning: Object of class stdClass could not be converted to int in %s on line %d
9191
object(GMP)#3 (1) {

ext/gmp/tests/overloading_with_object_stringable.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,20 @@ try {
7878

7979
?>
8080
--EXPECTF--
81-
TypeError: Unsupported operand types: GMP + T
82-
TypeError: Unsupported operand types: GMP - T
83-
TypeError: Unsupported operand types: GMP * T
84-
TypeError: Unsupported operand types: GMP / T
85-
TypeError: Unsupported operand types: GMP % T
81+
TypeError: Number must be of type GMP|string|int, T given
82+
TypeError: Number must be of type GMP|string|int, T given
83+
TypeError: Number must be of type GMP|string|int, T given
84+
TypeError: Number must be of type GMP|string|int, T given
85+
TypeError: Number must be of type GMP|string|int, T given
8686

8787
Warning: Object of class T could not be converted to int in %s on line %d
8888
object(GMP)#4 (1) {
8989
["num"]=>
9090
string(2) "42"
9191
}
92-
TypeError: Unsupported operand types: GMP | T
93-
TypeError: Unsupported operand types: GMP & T
94-
TypeError: Unsupported operand types: GMP ^ T
92+
TypeError: Number must be of type GMP|string|int, T given
93+
TypeError: Number must be of type GMP|string|int, T given
94+
TypeError: Number must be of type GMP|string|int, T given
9595

9696
Warning: Object of class T could not be converted to int in %s on line %d
9797
object(GMP)#3 (1) {

ext/gmp/tests/overloading_with_resource.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,18 @@ try {
7171

7272
?>
7373
--EXPECT--
74-
TypeError: Unsupported operand types: GMP + resource
75-
TypeError: Unsupported operand types: GMP - resource
76-
TypeError: Unsupported operand types: GMP * resource
77-
TypeError: Unsupported operand types: GMP / resource
78-
TypeError: Unsupported operand types: GMP % resource
74+
TypeError: Number must be of type GMP|string|int, resource given
75+
TypeError: Number must be of type GMP|string|int, resource given
76+
TypeError: Number must be of type GMP|string|int, resource given
77+
TypeError: Number must be of type GMP|string|int, resource given
78+
TypeError: Number must be of type GMP|string|int, resource given
7979
object(GMP)#3 (1) {
8080
["num"]=>
8181
string(5) "74088"
8282
}
83-
TypeError: Unsupported operand types: GMP | resource
84-
TypeError: Unsupported operand types: GMP & resource
85-
TypeError: Unsupported operand types: GMP ^ resource
83+
TypeError: Number must be of type GMP|string|int, resource given
84+
TypeError: Number must be of type GMP|string|int, resource given
85+
TypeError: Number must be of type GMP|string|int, resource given
8686
object(GMP)#2 (1) {
8787
["num"]=>
8888
string(3) "336"

0 commit comments

Comments
 (0)