Prodded by David Carlier and Ben Kallus.
. auto/feature
+njs_feature="GCC __attribute__ no_sanitize"
+njs_feature_name=NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE
+njs_feature_run=no
+njs_feature_path=
+njs_feature_libs=
+njs_feature_test="__attribute__((no_sanitize(\"undefined\"))) int main(void) {
+ return 0;
+ }"
+. auto/feature
+
+
njs_feature="Address sanitizer"
njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER
njs_feature_run=no
#define njs_msan_unpoison(ptr, size)
#endif
+#if (NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE)
+#define NJS_NOSANITIZE(options) __attribute__((no_sanitize(options)))
+#else
+#define NJS_NOSANITIZE(options)
+#endif
+
+
+njs_inline NJS_NOSANITIZE("float-cast-overflow") int64_t
+njs_unsafe_cast_double_to_int64(double num)
+{
+ /*
+ * Casting NaN to integer is undefined behavior,
+ * but it is fine in some cases where we do additional checks later.
+ * For example:
+ * int64_t i64 = njs_unsafe_cast_double_to_int64(num);
+ * if (i64 == num) {
+ * // num is integer
+ * }
+ *
+ * We do this as inline function to avoid UndefinedBehaviorSanitizer
+ * warnings.
+ */
+ return (int64_t) num;
+}
+
#if (NJS_HAVE_DENORMALS_CONTROL)
#include <xmmintrin.h>
if (nargs > 1 && njs_is_number(&args[1])) {
num = njs_number(&args[1]);
- if (num == (int64_t) num && fabs(num) <= NJS_MAX_SAFE_INTEGER) {
+ if (num == njs_unsafe_cast_double_to_int64(num)
+ && fabs(num) <= NJS_MAX_SAFE_INTEGER)
+ {
integer = 1;
}
}
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
-njs_inline njs_bool_t
+njs_inline NJS_NOSANITIZE("float-cast-overflow") njs_bool_t
njs_number_is_integer_index(double num)
{
uint32_t u32;
v = njs_number(njs_argument(args, 1));
- i64 = v;
+ i64 = njs_unsafe_cast_double_to_int64(v);
integer = (v == i64);
buffer = array->buffer;