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
+}