]> granicus.if.org Git - php/commitdiff
Use checked add/sub intrinsics instead of asm for ++ and --
authorAndrea Faulds <ajf@ajf.me>
Tue, 9 Aug 2016 23:28:13 +0000 (00:28 +0100)
committerAndrea Faulds <ajf@ajf.me>
Tue, 9 Aug 2016 23:46:05 +0000 (00:46 +0100)
Zend/zend_operators.h

index d4bdb7fd474f8a4cde6ffd627fcf9781529bcf01..360231b3de1e3eddea7a660a9a9373422ba1aa9d 100644 (file)
@@ -445,7 +445,23 @@ ZEND_API void zend_update_current_locale(void);
 
 static zend_always_inline void fast_long_increment_function(zval *op1)
 {
-#if defined(__GNUC__) && defined(__i386__)
+#if __has_builtin(__builtin_saddl_overflow) && SIZEOF_LONG == SIZEOF_ZEND_LONG
+       long lresult;
+       if (UNEXPECTED(__builtin_saddl_overflow(Z_LVAL_P(op1), 1, &lresult))) {
+               /* switch to double */
+               ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
+       } else {
+               Z_LVAL_P(op1) = lresult;
+       }
+#elif __has_builtin(__builtin_saddll_overflow) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
+       long long llresult;
+       if (UNEXPECTED(__builtin_saddll_overflow(Z_LVAL_P(op1), 1, &llresult))) {
+               /* switch to double */
+               ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
+       } else {
+               Z_LVAL_P(op1) = llresult;
+       }
+#elif defined(__GNUC__) && defined(__i386__)
        __asm__(
                "incl (%0)\n\t"
                "jno  0f\n\t"
@@ -483,7 +499,23 @@ static zend_always_inline void fast_long_increment_function(zval *op1)
 
 static zend_always_inline void fast_long_decrement_function(zval *op1)
 {
-#if defined(__GNUC__) && defined(__i386__)
+#if __has_builtin(__builtin_ssubl_overflow) && SIZEOF_LONG == SIZEOF_ZEND_LONG
+       long lresult;
+       if (UNEXPECTED(__builtin_ssubl_overflow(Z_LVAL_P(op1), 1, &lresult))) {
+               /* switch to double */
+               ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
+       } else {
+               Z_LVAL_P(op1) = lresult;
+       }
+#elif __has_builtin(__builtin_ssubll_overflow) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
+       long long llresult;
+       if (UNEXPECTED(__builtin_ssubll_overflow(Z_LVAL_P(op1), 1, &llresult))) {
+               /* switch to double */
+               ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
+       } else {
+               Z_LVAL_P(op1) = llresult;
+       }
+#elif defined(__GNUC__) && defined(__i386__)
        __asm__(
                "decl (%0)\n\t"
                "jno  0f\n\t"