fix ASan and UBSan errors; the one in loadn() seems a false positive
diff --git a/deps/cifra/src/bitops.h b/deps/cifra/src/bitops.h
index f2ca308..a1c1e7d 100644
--- a/deps/cifra/src/bitops.h
+++ b/deps/cifra/src/bitops.h
@@ -55,19 +55,19 @@
 /** Read 4 bytes from buf, as a 32-bit big endian quantity. */
 static inline uint32_t read32_be(const uint8_t buf[4])
 {
-  return (buf[0] << 24) |
-         (buf[1] << 16) |
-         (buf[2] << 8) |
-         (buf[3]);
+  return ((uint32_t)buf[0] << 24) |
+         ((uint32_t)buf[1] << 16) |
+         ((uint32_t)buf[2] << 8) |
+         ((uint32_t)buf[3]);
 }
 
 /** Read 4 bytes from buf, as a 32-bit little endian quantity. */
 static inline uint32_t read32_le(const uint8_t buf[4])
 {
-  return (buf[3] << 24) |
-         (buf[2] << 16) |
-         (buf[1] << 8) |
-         (buf[0]);
+  return ((uint32_t)buf[3] << 24) |
+         ((uint32_t)buf[2] << 16) |
+         ((uint32_t)buf[1] << 8) |
+         ((uint32_t)buf[0]);
 }
 
 /** Read 8 bytes from buf, as a 64-bit big endian quantity. */
diff --git a/deps/cifra/src/gf128.c b/deps/cifra/src/gf128.c
index f7ea834..d438d13 100644
--- a/deps/cifra/src/gf128.c
+++ b/deps/cifra/src/gf128.c
@@ -45,7 +45,7 @@
   inword = in[2];   out[2] = (inword << 1) | borrow;  borrow = inword >> 31;
   inword = in[1];   out[1] = (inword << 1) | borrow;  borrow = inword >> 31;
   inword = in[0];   out[0] = (inword << 1) | borrow;  borrow = inword >> 31;
-  
+
 #if CF_CACHE_SIDE_CHANNEL_PROTECTION
   out[3] ^= select_u8(borrow, table, 2);
 #else
@@ -66,9 +66,9 @@
   inword = in[3];   out[3] = (inword >> 1) | (borrow << 31);  borrow = inword & 1;
 
 #if CF_CACHE_SIDE_CHANNEL_PROTECTION
-  out[0] ^= select_u8(borrow, table, 2) << 24;
+  out[0] ^= (uint32_t)select_u8(borrow, table, 2) << 24;
 #else
-  out[0] ^= table[borrow] << 24;
+  out[0] ^= (uint32_t)table[borrow] << 24;
 #endif
 }
 
@@ -87,9 +87,9 @@
 #if CF_TIME_SIDE_CHANNEL_PROTECTION
   cf_gf128 zero = { 0 };
 #endif
- 
+
   /* Z_0 = 0^128
-   * V_0 = Y */ 
+   * V_0 = Y */
   cf_gf128 Z, V;
   memset(Z, 0, sizeof Z);
   memcpy(V, y, sizeof V);
diff --git a/lib/fusion.c b/lib/fusion.c
index d6562b4..6aa0ed7 100644
--- a/lib/fusion.c
+++ b/lib/fusion.c
@@ -48,6 +48,16 @@
 #include "picotls.h"
 #include "picotls/fusion.h"
 
+#if defined(__clang__)
+#if __has_feature(address_sanitizer)
+#define ASAN_IN_USE 1
+#endif
+#elif __SANITIZE_ADDRESS__ /* gcc */
+#define ASAN_IN_USE 1
+#else
+#define ASAN_IN_USE 0
+#endif
+
 struct ptls_fusion_aesgcm_context {
     ptls_fusion_aesecb_context_t ecb;
     size_t capacity;
@@ -205,9 +215,16 @@
 
 static inline __m128i loadn(const void *p, size_t l)
 {
+#if ASAN_IN_USE
+    if (l < 16) {
+        __m128i v = {0};
+        memcpy(&v, p, l);
+        return v;
+    }
+#endif
+
     __m128i v, mask = _mm_loadu_si128((__m128i *)(loadn_mask + 16 - l));
     uintptr_t mod4k = (uintptr_t)p % 4096;
-
     if (PTLS_LIKELY(mod4k <= 4080) || mod4k + l > 4096) {
         v = _mm_loadu_si128(p);
     } else {
diff --git a/t/fusion.c b/t/fusion.c
index f9c61bb..548843e 100644
--- a/t/fusion.c
+++ b/t/fusion.c
@@ -49,7 +49,7 @@
     return buf;
 }
 
-static void test_loadn(void)
+static void test_loadn_11(void)
 {
     uint8_t buf[8192] = {0};
 
@@ -66,6 +66,23 @@
     ok(!!"success");
 }
 
+static void test_loadn_16(void)
+{
+    uint8_t buf[8192] = {0};
+
+    for (size_t off = 0; off < 8192 - 15; ++off) {
+        uint8_t *src = buf + off;
+        memcpy(src, "hello world12345", 16);
+        __m128i v = loadn(src, 16);
+        if (memcmp(&v, "hello world12345", 16) != 0) {
+            ok(!"fail");
+            return;
+        }
+        memset(src, 0, 16);
+    }
+    ok(!!"success");
+}
+
 static const uint8_t zero[16384] = {0};
 
 static void test_ecb(void)
@@ -326,7 +343,8 @@
         return done_testing();
     }
 
-    subtest("loadn", test_loadn);
+    subtest("loadn-11", test_loadn_11);
+    subtest("loadn-16", test_loadn_16);
     subtest("ecb", test_ecb);
     subtest("gcm-basic", gcm_basic);
     subtest("gcm-capacity", gcm_capacity);
@@ -338,4 +356,4 @@
     subtest("generated-256-iv96", test_generated_aes256_iv96);
 
     return done_testing();
-}
\ No newline at end of file
+}