diff options
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r-- | Zend/zend_operators.c | 157 |
1 files changed, 83 insertions, 74 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index c08622084d..a19990e605 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -217,6 +217,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZVAL_COPY(&(holder), op); \ convert_to_long_base(&(holder), 10); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ if (Z_TYPE(holder) == IS_LONG) { \ @@ -252,7 +255,7 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ /* }}} */ -#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \ +#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \ do { \ if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \ if (Z_ISREF_P(op1)) { \ @@ -265,6 +268,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \ op1_lval = _zval_get_long_func_noisy(op1); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ } else { \ @@ -283,6 +289,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \ op2_lval = _zval_get_long_func_noisy(op2); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ } else { \ @@ -421,19 +430,6 @@ try_again: ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */ { - if (Z_TYPE_P(op) == IS_OBJECT) { - if (Z_OBJ_HT_P(op)->cast_object) { - zval org; - - ZVAL_COPY_VALUE(&org, op); - if (Z_OBJ_HT_P(op)->cast_object(&org, op, IS_NULL) == SUCCESS) { - zval_dtor(&org); - return; - } - ZVAL_COPY_VALUE(op, &org); - } - } - zval_ptr_dtor(op); ZVAL_NULL(op); } @@ -529,11 +525,7 @@ try_again: break; } case IS_TRUE: - if (CG(one_char_string)['1']) { - ZVAL_INTERNED_STR(op, CG(one_char_string)['1']); - } else { - ZVAL_NEW_STR(op, zend_string_init("1", 1, 0)); - } + ZVAL_INTERNED_STR(op, ZSTR_CHAR('1')); break; case IS_STRING: break; @@ -545,7 +537,7 @@ try_again: break; } case IS_LONG: { - ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op))); + ZVAL_STR(op, zend_long_to_str(Z_LVAL_P(op))); break; } case IS_DOUBLE: { @@ -611,25 +603,17 @@ try_again: if (obj_ht) { zend_array *arr; + /* fast copy */ if (!Z_OBJCE_P(op)->default_properties_count && obj_ht == Z_OBJ_P(op)->properties && - !ZEND_HASH_GET_APPLY_COUNT(Z_OBJ_P(op)->properties)) { - /* fast copy */ - if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) { - arr = obj_ht; - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_REFCOUNT(Z_OBJ_P(op)->properties)++; - } - } else { - arr = zend_array_dup(obj_ht); - } - zval_dtor(op); - ZVAL_ARR(op, arr); + !ZEND_HASH_GET_APPLY_COUNT(Z_OBJ_P(op)->properties) && + EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) { + arr = zend_proptable_to_symtable(obj_ht, 0); } else { - arr = zend_array_dup(obj_ht); - zval_dtor(op); - ZVAL_ARR(op, arr); + arr = zend_proptable_to_symtable(obj_ht, 1); } + zval_dtor(op); + ZVAL_ARR(op, arr); return; } } else { @@ -668,10 +652,12 @@ try_again: case IS_ARRAY: { HashTable *ht = Z_ARR_P(op); - if (Z_IMMUTABLE_P(op)) { + ht = zend_symtable_to_proptable(ht); + if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { /* TODO: try not to duplicate immutable arrays as well ??? */ ht = zend_array_dup(ht); } + zval_dtor(op); object_and_properties_init(op, zend_standard_class_def, ht); break; } @@ -687,7 +673,7 @@ try_again: zval tmp; ZVAL_COPY_VALUE(&tmp, op); object_init(op); - zend_hash_add_new(Z_OBJPROP_P(op), CG(known_strings)[ZEND_STR_SCALAR], &tmp); + zend_hash_add_new(Z_OBJPROP_P(op), ZSTR_KNOWN(ZEND_STR_SCALAR), &tmp); break; } } @@ -860,11 +846,7 @@ try_again: case IS_FALSE: return ZSTR_EMPTY_ALLOC(); case IS_TRUE: - if (CG(one_char_string)['1']) { - return CG(one_char_string)['1']; - } else { - return zend_string_init("1", 1, 0); - } + return ZSTR_CHAR('1'); case IS_RESOURCE: { char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG]; int len; @@ -960,6 +942,9 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1007,6 +992,9 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1059,6 +1047,9 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1157,6 +1148,9 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; } @@ -1227,6 +1221,9 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1239,7 +1236,7 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* { { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_MOD, mod_function); if (op2_lval == 0) { /* modulus by zero */ @@ -1359,11 +1356,7 @@ try_again: if (Z_STRLEN_P(op1) == 1) { zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1); - if (CG(one_char_string)[not]) { - ZVAL_INTERNED_STR(result, CG(one_char_string)[not]); - } else { - ZVAL_NEW_STR(result, zend_string_init((char *) ¬, 1, 0)); - } + ZVAL_INTERNED_STR(result, ZSTR_CHAR(not)); } else { ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0)); for (i = 0; i < Z_STRLEN_P(op1); i++) { @@ -1379,6 +1372,9 @@ try_again: default: ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT); + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; } @@ -1408,11 +1404,7 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op if (result==op1) { zend_string_release(Z_STR_P(result)); } - if (CG(one_char_string)[or]) { - ZVAL_INTERNED_STR(result, CG(one_char_string)[or]); - } else { - ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0)); - } + ZVAL_INTERNED_STR(result, ZSTR_CHAR(or)); return SUCCESS; } longer = op1; @@ -1438,6 +1430,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1447,6 +1442,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1484,11 +1482,7 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o if (result==op1) { zend_string_release(Z_STR_P(result)); } - if (CG(one_char_string)[and]) { - ZVAL_INTERNED_STR(result, CG(one_char_string)[and]); - } else { - ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0)); - } + ZVAL_INTERNED_STR(result, ZSTR_CHAR(and)); return SUCCESS; } longer = op1; @@ -1514,6 +1508,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1523,6 +1520,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1560,11 +1560,7 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o if (result==op1) { zend_string_release(Z_STR_P(result)); } - if (CG(one_char_string)[xor]) { - ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]); - } else { - ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0)); - } + ZVAL_INTERNED_STR(result, ZSTR_CHAR(xor)); return SUCCESS; } longer = op1; @@ -1590,6 +1586,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1599,6 +1598,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1617,7 +1619,7 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SL, shift_left_function); /* prevent wrapping quirkiness on some processors where << 64 + x == << x */ if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) { @@ -1653,7 +1655,7 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SR, shift_right_function); /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */ if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) { @@ -1702,6 +1704,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) / if (use_copy1) { if (UNEXPECTED(EG(exception))) { zval_dtor(&op1_copy); + if (orig_op1 != result) { + ZVAL_UNDEF(result); + } return FAILURE; } if (result == op1) { @@ -1727,6 +1732,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) / zval_dtor(op1); } zval_dtor(&op2_copy); + if (orig_op1 != result) { + ZVAL_UNDEF(result); + } return FAILURE; } op2 = &op2_copy; @@ -2285,12 +2293,7 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ if (Z_STRLEN_P(str) == 0) { zend_string_release(Z_STR_P(str)); - if (CG(one_char_string)['1']) { - ZVAL_INTERNED_STR(str, CG(one_char_string)['1']); - } else { - Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0); - Z_TYPE_INFO_P(str) = IS_STRING_EX; - } + ZVAL_INTERNED_STR(str, ZSTR_CHAR('1')); return; } @@ -2873,9 +2876,13 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */ { - char buf[MAX_LENGTH_OF_LONG + 1]; - char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num); - return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0); + if ((zend_ulong)num <= 9) { + return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num); + } else { + char buf[MAX_LENGTH_OF_LONG + 1]; + char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num); + return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0); + } } /* }}} */ @@ -3146,4 +3153,6 @@ ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d) * c-basic-offset: 4 * indent-tabs-mode: t * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 */ |