From a48e129d4873c1741efe8e0dcfba0568e29aefba Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 19 Jun 2017 15:48:30 -0700 Subject: [PATCH] [linux] Port libzstd UBSAN fix --- contrib/linux-kernel/lib/zstd/compress.c | 7 ++++++- contrib/linux-kernel/zstd.diff | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/contrib/linux-kernel/lib/zstd/compress.c b/contrib/linux-kernel/lib/zstd/compress.c index 42236a3e..1aff542b 100644 --- a/contrib/linux-kernel/lib/zstd/compress.c +++ b/contrib/linux-kernel/lib/zstd/compress.c @@ -1978,10 +1978,15 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx *ctx, const void *src, size_t src break; /* nothing found : store previous solution */ } + /* NOTE: + * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior. + * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which + * overflows the pointer, which is undefined behavior. + */ /* catch up */ if (offset) { while ((start > anchor) && (start > base + offset - ZSTD_REP_MOVE) && - (start[-1] == start[-1 - offset + ZSTD_REP_MOVE])) /* only search for offset within prefix */ + (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1])) /* only search for offset within prefix */ { start--; matchLength++; diff --git a/contrib/linux-kernel/zstd.diff b/contrib/linux-kernel/zstd.diff index 1fa64ff8..e83b56ed 100644 --- a/contrib/linux-kernel/zstd.diff +++ b/contrib/linux-kernel/zstd.diff @@ -1599,10 +1599,10 @@ index 0000000..a826b99 +#endif /* BITSTREAM_H_MODULE */ diff --git a/lib/zstd/compress.c b/lib/zstd/compress.c new file mode 100644 -index 0000000..42236a3 +index 0000000..1aff542 --- /dev/null +++ b/lib/zstd/compress.c -@@ -0,0 +1,3463 @@ +@@ -0,0 +1,3468 @@ +/** + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. @@ -3583,10 +3583,15 @@ index 0000000..42236a3 + break; /* nothing found : store previous solution */ + } + ++ /* NOTE: ++ * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior. ++ * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which ++ * overflows the pointer, which is undefined behavior. ++ */ + /* catch up */ + if (offset) { + while ((start > anchor) && (start > base + offset - ZSTD_REP_MOVE) && -+ (start[-1] == start[-1 - offset + ZSTD_REP_MOVE])) /* only search for offset within prefix */ ++ (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1])) /* only search for offset within prefix */ + { + start--; + matchLength++;