[njs] Fixed misaligned reading and writing.

Dmitry Volyntsev xeioex at nginx.com
Mon May 31 07:22:29 UTC 2021


details:   https://hg.nginx.org/njs/rev/de189c66c757
branches:  
changeset: 1647:de189c66c757
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon May 31 06:55:34 2021 +0000
description:
Fixed misaligned reading and writing.

error: load of misaligned address 0x62500de0ab11 for type 'uint16_t',
    which requires 2 byte alignment.

Found by UndefinedBehaviorSanitizer.

diffstat:

 auto/clang            |  13 +++++++++++++
 src/njs_buffer.c      |  14 +++++++-------
 src/njs_clang.h       |   8 ++++++++
 src/njs_typed_array.c |  16 ++++++++--------
 src/njs_utils.h       |  49 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 15 deletions(-)

diffs (246 lines):

diff -r 7d835eb234e1 -r de189c66c757 auto/clang
--- a/auto/clang	Mon May 31 06:55:32 2021 +0000
+++ b/auto/clang	Mon May 31 06:55:34 2021 +0000
@@ -129,6 +129,19 @@ njs_feature_test="int n __attribute__ ((
 . auto/feature
 
 
+njs_feature="GCC __attribute__ packed"
+njs_feature_name=NJS_HAVE_GCC_ATTRIBUTE_PACKED
+njs_feature_run=no
+njs_feature_path=
+njs_feature_libs=
+njs_feature_test="struct __attribute__((packed)) s { char v; };
+
+                  int main(void) {
+                    return 0;
+                  }"
+. auto/feature
+
+
 njs_feature="Address sanitizer"
 njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER
 njs_feature_run=no
diff -r 7d835eb234e1 -r de189c66c757 src/njs_buffer.c
--- a/src/njs_buffer.c	Mon May 31 06:55:32 2021 +0000
+++ b/src/njs_buffer.c	Mon May 31 06:55:34 2021 +0000
@@ -989,7 +989,7 @@ njs_buffer_prototype_read_int(njs_vm_t *
         break;
 
     case 2:
-        u32 = *((uint16_t *) u8);
+        u32 = njs_get_u16(u8);
 
         if (swap) {
             u32 = njs_bswap_u16(u32);
@@ -1028,7 +1028,7 @@ njs_buffer_prototype_read_int(njs_vm_t *
         break;
 
     case 4:
-        u32 = *((uint32_t *) u8);
+        u32 = njs_get_u32(u8);
 
         if (swap) {
             u32 = njs_bswap_u32(u32);
@@ -1273,7 +1273,7 @@ njs_buffer_prototype_write_int(njs_vm_t 
             u32 = njs_bswap_u16(u32);
         }
 
-        *((uint16_t *) u8) = u32;
+        njs_set_u16(u8, u32);
         break;
 
     case 3:
@@ -1299,7 +1299,7 @@ njs_buffer_prototype_write_int(njs_vm_t 
             u32 = njs_bswap_u32(u32);
         }
 
-        *((uint32_t *) u8) = u32;
+        njs_set_u32(u8, u32);
         break;
 
     case 5:
@@ -2153,14 +2153,14 @@ njs_buffer_prototype_swap(njs_vm_t *vm, 
     switch (size) {
     case 2:
         for (; p < end; p += 2) {
-            *((uint16_t *) p) = njs_bswap_u16(*((uint16_t *) p));
+            njs_set_u16(p, njs_bswap_u16(njs_get_u16(p)));
         }
 
         break;
 
     case 4:
         for (; p < end; p += 4) {
-            *((uint32_t *) p) = njs_bswap_u32(*((uint32_t *) p));
+            njs_set_u32(p, njs_bswap_u32(njs_get_u32(p)));
         }
 
         break;
@@ -2168,7 +2168,7 @@ njs_buffer_prototype_swap(njs_vm_t *vm, 
     case 8:
     default:
         for (; p < end; p += 8) {
-            *((uint64_t *) p) = njs_bswap_u64(*((uint64_t *) p));
+            njs_set_u64(p, njs_bswap_u64(njs_get_u64(p)));
         }
     }
 
diff -r 7d835eb234e1 -r de189c66c757 src/njs_clang.h
--- a/src/njs_clang.h	Mon May 31 06:55:32 2021 +0000
+++ b/src/njs_clang.h	Mon May 31 06:55:34 2021 +0000
@@ -138,6 +138,14 @@ njs_leading_zeros64(uint64_t x)
 #endif
 
 
+#if (NJS_HAVE_GCC_ATTRIBUTE_PACKED)
+#define NJS_PACKED    __attribute__((packed))
+
+#else
+#define NJS_PACKED
+#endif
+
+
 #if (NJS_HAVE_GCC_ATTRIBUTE_MALLOC)
 #define NJS_MALLOC_LIKE    __attribute__((__malloc__))
 
diff -r 7d835eb234e1 -r de189c66c757 src/njs_typed_array.c
--- a/src/njs_typed_array.c	Mon May 31 06:55:32 2021 +0000
+++ b/src/njs_typed_array.c	Mon May 31 06:55:34 2021 +0000
@@ -2736,7 +2736,7 @@ njs_data_view_prototype_get(njs_vm_t *vm
         break;
 
     case NJS_OBJ_TYPE_UINT16_ARRAY:
-        u32 = *((uint16_t *) u8);
+        u32 = njs_get_u16(u8);
 
         if (swap) {
             u32 = njs_bswap_u16(u32);
@@ -2746,7 +2746,7 @@ njs_data_view_prototype_get(njs_vm_t *vm
         break;
 
     case NJS_OBJ_TYPE_INT16_ARRAY:
-        u32 = *((uint16_t *) u8);
+        u32 = njs_get_u16(u8);
 
         if (swap) {
             u32 = njs_bswap_u16(u32);
@@ -2758,7 +2758,7 @@ njs_data_view_prototype_get(njs_vm_t *vm
     case NJS_OBJ_TYPE_UINT32_ARRAY:
     case NJS_OBJ_TYPE_INT32_ARRAY:
     case NJS_OBJ_TYPE_FLOAT32_ARRAY:
-        u32 = *((uint32_t *) u8);
+        u32 = njs_get_u32(u8);
 
         if (swap) {
             u32 = njs_bswap_u32(u32);
@@ -2783,7 +2783,7 @@ njs_data_view_prototype_get(njs_vm_t *vm
     default:
         /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */
 
-        conv_f64.u = *((uint64_t *) u8);
+        conv_f64.u = njs_get_u64(u8);
 
         if (swap) {
             conv_f64.u = njs_bswap_u64(conv_f64.u);
@@ -2865,7 +2865,7 @@ njs_data_view_prototype_set(njs_vm_t *vm
             u32 = njs_bswap_u16(u32);
         }
 
-        *((uint16_t *) u8) = u32;
+        njs_set_u16(u8, u32);
         break;
 
     case NJS_OBJ_TYPE_UINT32_ARRAY:
@@ -2876,7 +2876,7 @@ njs_data_view_prototype_set(njs_vm_t *vm
             u32 = njs_bswap_u32(u32);
         }
 
-        *((uint32_t *) u8) = u32;
+        njs_set_u32(u8, u32);
         break;
 
     case NJS_OBJ_TYPE_FLOAT32_ARRAY:
@@ -2886,7 +2886,7 @@ njs_data_view_prototype_set(njs_vm_t *vm
             conv_f32.u = njs_bswap_u32(conv_f32.u);
         }
 
-        *((uint32_t *) u8) = conv_f32.u;
+        njs_set_u32(u8, conv_f32.u);
         break;
 
     default:
@@ -2898,7 +2898,7 @@ njs_data_view_prototype_set(njs_vm_t *vm
             conv_f64.u = njs_bswap_u64(conv_f64.u);
         }
 
-        *((uint64_t *) u8) = conv_f64.u;
+        njs_set_u64(u8, conv_f64.u);
     }
 
     njs_set_undefined(&vm->retval);
diff -r 7d835eb234e1 -r de189c66c757 src/njs_utils.h
--- a/src/njs_utils.h	Mon May 31 06:55:32 2021 +0000
+++ b/src/njs_utils.h	Mon May 31 06:55:34 2021 +0000
@@ -20,6 +20,19 @@ typedef union {
 } njs_conv_f64_t;
 
 
+struct NJS_PACKED njs_packed_u16_t {
+    uint16_t v;
+};
+
+struct NJS_PACKED njs_packed_u32_t {
+    uint32_t v;
+};
+
+struct NJS_PACKED njs_packed_u64_t {
+    uint64_t v;
+};
+
+
 typedef int (*njs_sort_cmp_t)(const void *, const void *, void *ctx);
 
 void njs_qsort(void *base, size_t n, size_t size, njs_sort_cmp_t cmp,
@@ -115,5 +128,41 @@ njs_bswap_u64(uint64_t u64)
            | ((u64 & 0x00000000000000ffULL) << 56);
 }
 
+njs_inline uint16_t
+njs_get_u16(const uint8_t *p)
+{
+    return ((const struct njs_packed_u16_t *) p)->v;
+}
+
+njs_inline uint32_t
+njs_get_u32(const uint8_t *p)
+{
+    return ((const struct njs_packed_u32_t *) p)->v;
+}
+
+njs_inline uint64_t
+njs_get_u64(const uint8_t *p)
+{
+    return ((const struct njs_packed_u64_t *) p)->v;
+}
+
+njs_inline void
+njs_set_u16(uint8_t *p, uint16_t val)
+{
+    ((struct njs_packed_u16_t *) p)->v = val;
+}
+
+njs_inline void
+njs_set_u32(uint8_t *p, uint32_t val)
+{
+    ((struct njs_packed_u32_t *) p)->v = val;
+}
+
+njs_inline void
+njs_set_u64(uint8_t *p, uint64_t val)
+{
+    ((struct njs_packed_u64_t *) p)->v = val;
+}
+
 
 #endif /* _NJS_UTILS_H_INCLUDED_ */


More information about the nginx-devel mailing list