Skip to content

Commit 7512685

Browse files
authored
Use built-ins for addition and subtraction on Windows (GH-17472)
For Clang, we just need to define the respective macros, since these built-ins are available in all supported Clang versions (>= 4.0.0, currently)[1]. For MSVC (and possibly other compilers) we use the respective APIs of intsafe.h[2] which are available as of Windows 7/Server 2008 R2. This avoids the UB due to signed integer overflow that may happen with our fallback implementations. We also drop the superfluous SHORT_MAX definition from pdo_firebird. This shouldn't be defined unconditionally, but since it is apparently unused, we remove it altogether. [1] <https://releases.llvm.org/4.0.0/tools/clang/docs/LanguageExtensions.html> [2] <https://learn.microsoft.com/en-us/windows/win32/api/intsafe/>
1 parent abfa377 commit 7512685

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

Zend/zend_config.w32.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <winsock2.h>
3737
#include <windows.h>
3838

39+
#include <intsafe.h>
3940
#include <float.h>
4041

4142
#define strcasecmp(s1, s2) _stricmp(s1, s2)

Zend/zend_operators.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,22 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
579579
} else {
580580
Z_LVAL_P(op1) = llresult;
581581
}
582+
#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG
583+
long lresult;
584+
if (UNEXPECTED(FAILED(LongAdd(Z_LVAL_P(op1), 1, &lresult)))) {
585+
/* switch to double */
586+
ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
587+
} else {
588+
Z_LVAL_P(op1) = lresult;
589+
}
590+
#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
591+
long long llresult;
592+
if (UNEXPECTED(FAILED(LongLongAdd(Z_LVAL_P(op1), 1, &llresult)))) {
593+
/* switch to double */
594+
ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
595+
} else {
596+
Z_LVAL_P(op1) = llresult;
597+
}
582598
#else
583599
if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MAX)) {
584600
/* switch to double */
@@ -642,6 +658,22 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
642658
} else {
643659
Z_LVAL_P(op1) = llresult;
644660
}
661+
#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG
662+
long lresult;
663+
if (UNEXPECTED(FAILED(LongSub(Z_LVAL_P(op1), 1, &lresult)))) {
664+
/* switch to double */
665+
ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
666+
} else {
667+
Z_LVAL_P(op1) = lresult;
668+
}
669+
#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
670+
long long llresult;
671+
if (UNEXPECTED(FAILED(LongLongSub(Z_LVAL_P(op1), 1, &llresult)))) {
672+
/* switch to double */
673+
ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
674+
} else {
675+
Z_LVAL_P(op1) = llresult;
676+
}
645677
#else
646678
if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
647679
/* switch to double */
@@ -724,6 +756,20 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
724756
} else {
725757
ZVAL_LONG(result, llresult);
726758
}
759+
#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG
760+
long lresult;
761+
if (UNEXPECTED(FAILED(LongAdd(Z_LVAL_P(op1), Z_LVAL_P(op2), &lresult)))) {
762+
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
763+
} else {
764+
ZVAL_LONG(result, lresult);
765+
}
766+
#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
767+
long long llresult;
768+
if (UNEXPECTED(FAILED(LongLongAdd(Z_LVAL_P(op1), Z_LVAL_P(op2), &llresult)))) {
769+
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
770+
} else {
771+
ZVAL_LONG(result, llresult);
772+
}
727773
#else
728774
/*
729775
* 'result' may alias with op1 or op2, so we need to
@@ -812,6 +858,20 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
812858
} else {
813859
ZVAL_LONG(result, llresult);
814860
}
861+
#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG
862+
long lresult;
863+
if (UNEXPECTED(FAILED(LongSub(Z_LVAL_P(op1), Z_LVAL_P(op2), &lresult)))) {
864+
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
865+
} else {
866+
ZVAL_LONG(result, lresult);
867+
}
868+
#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
869+
long long llresult;
870+
if (UNEXPECTED(FAILED(LongLongSub(Z_LVAL_P(op1), Z_LVAL_P(op2), &llresult)))) {
871+
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
872+
} else {
873+
ZVAL_LONG(result, llresult);
874+
}
815875
#else
816876
ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
817877

ext/pdo_firebird/php_pdo_firebird_int.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
#define PDO_FB_DEF_TIME_FMT "%H:%M:%S"
3434
#define PDO_FB_DEF_TIMESTAMP_FMT PDO_FB_DEF_DATE_FMT " " PDO_FB_DEF_TIME_FMT
3535

36-
#define SHORT_MAX (1 << (8*sizeof(short)-1))
37-
3836
#if SIZEOF_ZEND_LONG == 8 && !defined(PHP_WIN32)
3937
# define LL_LIT(lit) lit ## L
4038
#else

win32/build/config.w32

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ if (VS_TOOLSET) {
370370
}
371371
}
372372
} else if (CLANG_TOOLSET) {
373+
AC_DEFINE("PHP_HAVE_BUILTIN_SADDL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_saddl_overflow'.");
374+
AC_DEFINE("PHP_HAVE_BUILTIN_SADDLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_saddll_overflow'.");
375+
AC_DEFINE("PHP_HAVE_BUILTIN_SSUBL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubl_overflow'.");
376+
AC_DEFINE("PHP_HAVE_BUILTIN_SSUBLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubll_overflow'.");
373377
if (PHP_UNCRITICAL_WARN_CHOKE != "no") {
374378
ADD_FLAG("CFLAGS", "-Wno-ignored-attributes -Wno-deprecated-declarations -Wno-missing-braces " +
375379
"-Wno-logical-op-parentheses -Wno-msvc-include -Wno-invalid-source-encoding -Wno-unknown-pragmas " +

win32/build/confutils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3318,6 +3318,11 @@ function toolset_setup_common_cflags()
33183318
var vc_ver = probe_binary(PATH_PROG('cl', null));
33193319
ADD_FLAG("CFLAGS"," -fms-compatibility -fms-compatibility-version=" + vc_ver + " -fms-extensions");
33203320
}
3321+
3322+
if (!CLANG_TOOLSET) {
3323+
/* clang uses __builtin_*() instead */
3324+
ADD_FLAG("CFLAGS", "/DENABLE_INTSAFE_SIGNED_FUNCTIONS");
3325+
}
33213326
}
33223327

33233328
function toolset_setup_intrinsic_cflags()

0 commit comments

Comments
 (0)