[njs] Ignoring UndefinedBehaviorSanitizer warnings where appropriate.

Dmitry Volyntsev xeioex at nginx.com
Tue Jan 9 06:16:17 UTC 2024


details:   https://hg.nginx.org/njs/rev/0490f1ae4cf5
branches:  
changeset: 2258:0490f1ae4cf5
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Sun Jul 30 10:21:51 2023 +0100
description:
Ignoring UndefinedBehaviorSanitizer warnings where appropriate.

Prodded by David Carlier and Ben Kallus.

diffstat:

 auto/clang            |  11 +++++++++++
 src/njs_clang.h       |  25 +++++++++++++++++++++++++
 src/njs_number.c      |   4 +++-
 src/njs_number.h      |   2 +-
 src/njs_typed_array.c |   2 +-
 5 files changed, 41 insertions(+), 3 deletions(-)

diffs (94 lines):

diff -r 275d785ab5bf -r 0490f1ae4cf5 auto/clang
--- a/auto/clang	Mon Jan 08 16:40:42 2024 -0800
+++ b/auto/clang	Sun Jul 30 10:21:51 2023 +0100
@@ -161,6 +161,17 @@ njs_feature_test="int main(int argc, cha
 . 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
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_clang.h
--- a/src/njs_clang.h	Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_clang.h	Sun Jul 30 10:21:51 2023 +0100
@@ -183,6 +183,31 @@ njs_leading_zeros64(uint64_t x)
 #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>
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.c
--- a/src/njs_number.c	Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_number.c	Sun Jul 30 10:21:51 2023 +0100
@@ -382,7 +382,9 @@ njs_number_is_safe_integer(njs_vm_t *vm,
     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;
         }
     }
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.h
--- a/src/njs_number.h	Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_number.h	Sun Jul 30 10:21:51 2023 +0100
@@ -36,7 +36,7 @@ njs_int_t njs_number_parse_float(njs_vm_
     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;
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_typed_array.c
--- a/src/njs_typed_array.c	Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_typed_array.c	Sun Jul 30 10:21:51 2023 +0100
@@ -1388,7 +1388,7 @@ njs_typed_array_prototype_index_of(njs_v
 
     v = njs_number(njs_argument(args, 1));
 
-    i64 = v;
+    i64 = njs_unsafe_cast_double_to_int64(v);
     integer = (v == i64);
 
     buffer = array->buffer;


More information about the nginx-devel mailing list