1 /*
2    LZ4 - Fast LZ compression algorithm
3    Copyright (C) 2011-2020, Yann Collet.
4 
5    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6 
7    Redistribution and use in source and binary forms, with or without
8    modification, are permitted provided that the following conditions are
9    met:
10 
11        * Redistributions of source code must retain the above copyright
12    notice, this list of conditions and the following disclaimer.
13        * Redistributions in binary form must reproduce the above
14    copyright notice, this list of conditions and the following disclaimer
15    in the documentation and/or other materials provided with the
16    distribution.
17 
18    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30    You can contact the author at :
31     - LZ4 homepage : http://www.lz4.org
32     - LZ4 source repository : https://github.com/lz4/lz4
33 */
34 
35 #include "../../lv_conf_internal.h"
36 #if LV_USE_LZ4_INTERNAL
37 
38 /*-************************************
39 *  Tuning parameters
40 **************************************/
41 /*
42  * LZ4_HEAPMODE :
43  * Select how stateless compression functions like `LZ4_compress_default()`
44  * allocate memory for their hash table,
45  * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
46  */
47 #ifndef LZ4_HEAPMODE
48 #  define LZ4_HEAPMODE 0
49 #endif
50 
51 /*
52  * LZ4_ACCELERATION_DEFAULT :
53  * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
54  */
55 #define LZ4_ACCELERATION_DEFAULT 1
56 /*
57  * LZ4_ACCELERATION_MAX :
58  * Any "acceleration" value higher than this threshold
59  * get treated as LZ4_ACCELERATION_MAX instead (fix #876)
60  */
61 #define LZ4_ACCELERATION_MAX 65537
62 
63 
64 /*-************************************
65 *  CPU Feature Detection
66 **************************************/
67 /* LZ4_FORCE_MEMORY_ACCESS
68  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
69  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
70  * The below switch allow to select different access method for improved performance.
71  * Method 0 (default) : use `memcpy()`. Safe and portable.
72  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
73  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
74  * Method 2 : direct access. This method is portable but violate C standard.
75  *            It can generate buggy code on targets which assembly generation depends on alignment.
76  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
77  * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
78  * Prefer these methods in priority order (0 > 1 > 2)
79  */
80 #ifndef LZ4_FORCE_MEMORY_ACCESS   /* can be defined externally */
81 #  if defined(__GNUC__) && \
82   ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \
83   || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
84 #    define LZ4_FORCE_MEMORY_ACCESS 2
85 #  elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) || defined(_MSC_VER)
86 #    define LZ4_FORCE_MEMORY_ACCESS 1
87 #  endif
88 #endif
89 
90 /*
91  * LZ4_FORCE_SW_BITCOUNT
92  * Define this parameter if your target system or compiler does not support hardware bit count
93  */
94 #if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for WinCE doesn't support Hardware bit count */
95 #  undef  LZ4_FORCE_SW_BITCOUNT  /* avoid double def */
96 #  define LZ4_FORCE_SW_BITCOUNT
97 #endif
98 
99 
100 
101 /*-************************************
102 *  Dependency
103 **************************************/
104 /*
105  * LZ4_SRC_INCLUDED:
106  * Amalgamation flag, whether lz4.c is included
107  */
108 #ifndef LZ4_SRC_INCLUDED
109 #  define LZ4_SRC_INCLUDED 1
110 #endif
111 
112 #ifndef LZ4_STATIC_LINKING_ONLY
113 #define LZ4_STATIC_LINKING_ONLY
114 #endif
115 
116 #ifndef LZ4_DISABLE_DEPRECATE_WARNINGS
117 #define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */
118 #endif
119 
120 #define LZ4_STATIC_LINKING_ONLY  /* LZ4_DISTANCE_MAX */
121 #include "lz4.h"
122 /* see also "memory routines" below */
123 
124 
125 /*-************************************
126 *  Compiler Options
127 **************************************/
128 #if defined(_MSC_VER) && (_MSC_VER >= 1400)  /* Visual Studio 2005+ */
129 #  include <intrin.h>               /* only present in VS2005+ */
130 #  pragma warning(disable : 4127)   /* disable: C4127: conditional expression is constant */
131 #  pragma warning(disable : 6237)   /* disable: C6237: conditional expression is always 0 */
132 #endif  /* _MSC_VER */
133 
134 #ifndef LZ4_FORCE_INLINE
135 #  ifdef _MSC_VER    /* Visual Studio */
136 #    define LZ4_FORCE_INLINE static __forceinline
137 #  else
138 #    if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
139 #      ifdef __GNUC__
140 #        define LZ4_FORCE_INLINE static inline __attribute__((always_inline))
141 #      else
142 #        define LZ4_FORCE_INLINE static inline
143 #      endif
144 #    else
145 #      define LZ4_FORCE_INLINE static
146 #    endif /* __STDC_VERSION__ */
147 #  endif  /* _MSC_VER */
148 #endif /* LZ4_FORCE_INLINE */
149 
150 /* LZ4_FORCE_O2 and LZ4_FORCE_INLINE
151  * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8,
152  * together with a simple 8-byte copy loop as a fall-back path.
153  * However, this optimization hurts the decompression speed by >30%,
154  * because the execution does not go to the optimized loop
155  * for typical compressible data, and all of the preamble checks
156  * before going to the fall-back path become useless overhead.
157  * This optimization happens only with the -O3 flag, and -O2 generates
158  * a simple 8-byte copy loop.
159  * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8
160  * functions are annotated with __attribute__((optimize("O2"))),
161  * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute
162  * of LZ4_wildCopy8 does not affect the compression speed.
163  */
164 #if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__)
165 #  define LZ4_FORCE_O2  __attribute__((optimize("O2")))
166 #  undef LZ4_FORCE_INLINE
167 #  define LZ4_FORCE_INLINE  static __inline __attribute__((optimize("O2"),always_inline))
168 #else
169 #  define LZ4_FORCE_O2
170 #endif
171 
172 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
173 #  define expect(expr,value)    (__builtin_expect ((expr),(value)) )
174 #else
175 #  define expect(expr,value)    (expr)
176 #endif
177 
178 #ifndef likely
179 #define likely(expr)     expect((expr) != 0, 1)
180 #endif
181 #ifndef unlikely
182 #define unlikely(expr)   expect((expr) != 0, 0)
183 #endif
184 
185 /* Should the alignment test prove unreliable, for some reason,
186  * it can be disabled by setting LZ4_ALIGN_TEST to 0 */
187 #ifndef LZ4_ALIGN_TEST  /* can be externally provided */
188 # define LZ4_ALIGN_TEST 1
189 #endif
190 
191 
192 /*-************************************
193 *  Memory routines
194 **************************************/
195 
196 /*! LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION :
197  *  Disable relatively high-level LZ4/HC functions that use dynamic memory
198  *  allocation functions (malloc(), calloc(), free()).
199  *
200  *  Note that this is a compile-time switch. And since it disables
201  *  public/stable LZ4 v1 API functions, we don't recommend using this
202  *  symbol to generate a library for distribution.
203  *
204  *  The following public functions are removed when this symbol is defined.
205  *  - lz4   : LZ4_createStream, LZ4_freeStream,
206  *            LZ4_createStreamDecode, LZ4_freeStreamDecode, LZ4_create (deprecated)
207  *  - lz4hc : LZ4_createStreamHC, LZ4_freeStreamHC,
208  *            LZ4_createHC (deprecated), LZ4_freeHC  (deprecated)
209  *  - lz4frame, lz4file : All LZ4F_* functions
210  */
211 #if defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
212 #  define ALLOC(s)          lz4_error_memory_allocation_is_disabled
213 #  define ALLOC_AND_ZERO(s) lz4_error_memory_allocation_is_disabled
214 #  define FREEMEM(p)        lz4_error_memory_allocation_is_disabled
215 #elif defined(LZ4_USER_MEMORY_FUNCTIONS)
216 /* memory management functions can be customized by user project.
217  * Below functions must exist somewhere in the Project
218  * and be available at link time */
219 void* LZ4_malloc(size_t s);
220 void* LZ4_calloc(size_t n, size_t s);
221 void  LZ4_free(void* p);
222 # define ALLOC(s)          LZ4_malloc(s)
223 # define ALLOC_AND_ZERO(s) LZ4_calloc(1,s)
224 # define FREEMEM(p)        LZ4_free(p)
225 #else
226 # include <stdlib.h>   /* malloc, calloc, free */
227 # define ALLOC(s)          malloc(s)
228 # define ALLOC_AND_ZERO(s) calloc(1,s)
229 # define FREEMEM(p)        free(p)
230 #endif
231 
232 #if ! LZ4_FREESTANDING
233 #  include <string.h>   /* memset, memcpy */
234 #endif
235 #if !defined(LZ4_memset)
236 #  define LZ4_memset(p,v,s) memset((p),(v),(s))
237 #endif
238 #define MEM_INIT(p,v,s)   LZ4_memset((p),(v),(s))
239 
240 
241 /*-************************************
242 *  Common Constants
243 **************************************/
244 #define MINMATCH 4
245 
246 #define WILDCOPYLENGTH 8
247 #define LASTLITERALS   5   /* see ../doc/lz4_Block_format.md#parsing-restrictions */
248 #define MFLIMIT       12   /* see ../doc/lz4_Block_format.md#parsing-restrictions */
249 #define MATCH_SAFEGUARD_DISTANCE  ((2*WILDCOPYLENGTH) - MINMATCH)   /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */
250 #define FASTLOOP_SAFE_DISTANCE 64
251 static const int LZ4_minLength = (MFLIMIT+1);
252 
253 #define KB *(1 <<10)
254 #define MB *(1 <<20)
255 #define GB *(1U<<30)
256 
257 #define LZ4_DISTANCE_ABSOLUTE_MAX 65535
258 #if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX)   /* max supported by LZ4 format */
259 #  error "LZ4_DISTANCE_MAX is too big : must be <= 65535"
260 #endif
261 
262 #define ML_BITS  4
263 #define ML_MASK  ((1U<<ML_BITS)-1)
264 #define RUN_BITS (8-ML_BITS)
265 #define RUN_MASK ((1U<<RUN_BITS)-1)
266 
267 
268 /*-************************************
269 *  Error detection
270 **************************************/
271 #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)
272 #  include <assert.h>
273 #else
274 #  ifndef assert
275 #    define assert(condition) ((void)0)
276 #  endif
277 #endif
278 
279 #define LZ4_STATIC_ASSERT(c)   { enum { LZ4_static_assert = 1/(int)(!!(c)) }; }   /* use after variable declarations */
280 
281 #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2)
282 #  include <stdio.h>
283    static int g_debuglog_enable = 1;
284 #  define DEBUGLOG(l, ...) {                          \
285         if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) {  \
286             fprintf(stderr, __FILE__  " %i: ", __LINE__); \
287             fprintf(stderr, __VA_ARGS__);             \
288             fprintf(stderr, " \n");                   \
289     }   }
290 #else
291 #  define DEBUGLOG(l, ...) {}    /* disabled */
292 #endif
293 
LZ4_isAligned(const void * ptr,size_t alignment)294 static int LZ4_isAligned(const void* ptr, size_t alignment)
295 {
296     return ((size_t)ptr & (alignment -1)) == 0;
297 }
298 
299 
300 /*-************************************
301 *  Types
302 **************************************/
303 #include <limits.h>
304 #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
305 # include <stdint.h>
306   typedef  uint8_t BYTE;
307   typedef uint16_t U16;
308   typedef uint32_t U32;
309   typedef  int32_t S32;
310   typedef uint64_t U64;
311   typedef uintptr_t uptrval;
312 #else
313 # if UINT_MAX != 4294967295UL
314 #   error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4"
315 # endif
316   typedef unsigned char       BYTE;
317   typedef unsigned short      U16;
318   typedef unsigned int        U32;
319   typedef   signed int        S32;
320   typedef unsigned long long  U64;
321   typedef size_t              uptrval;   /* generally true, except OpenVMS-64 */
322 #endif
323 
324 #if defined(__x86_64__)
325   typedef U64    reg_t;   /* 64-bits in x32 mode */
326 #else
327   typedef size_t reg_t;   /* 32-bits in x32 mode */
328 #endif
329 
330 typedef enum {
331     notLimited = 0,
332     limitedOutput = 1,
333     fillOutput = 2
334 } limitedOutput_directive;
335 
336 
337 /*-************************************
338 *  Reading and writing into memory
339 **************************************/
340 
341 /**
342  * LZ4 relies on memcpy with a constant size being inlined. In freestanding
343  * environments, the compiler can't assume the implementation of memcpy() is
344  * standard compliant, so it can't apply its specialized memcpy() inlining
345  * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze
346  * memcpy() as if it were standard compliant, so it can inline it in freestanding
347  * environments. This is needed when decompressing the Linux Kernel, for example.
348  */
349 #if !defined(LZ4_memcpy)
350 #  if defined(__GNUC__) && (__GNUC__ >= 4)
351 #    define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)
352 #  else
353 #    define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)
354 #  endif
355 #endif
356 
357 #if !defined(LZ4_memmove)
358 #  if defined(__GNUC__) && (__GNUC__ >= 4)
359 #    define LZ4_memmove __builtin_memmove
360 #  else
361 #    define LZ4_memmove memmove
362 #  endif
363 #endif
364 
LZ4_isLittleEndian(void)365 static unsigned LZ4_isLittleEndian(void)
366 {
367     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental */
368     return one.c[0];
369 }
370 
371 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
372 #define LZ4_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
373 #elif defined(_MSC_VER)
374 #define LZ4_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
375 #endif
376 
377 #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
378 /* lie to the compiler about data alignment; use with caution */
379 
LZ4_read16(const void * memPtr)380 static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }
LZ4_read32(const void * memPtr)381 static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }
LZ4_read_ARCH(const void * memPtr)382 static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; }
383 
LZ4_write16(void * memPtr,U16 value)384 static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
LZ4_write32(void * memPtr,U32 value)385 static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
386 
387 #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)
388 
389 /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
390 /* currently only defined for gcc and icc */
391 LZ4_PACK(typedef struct { U16 u16; }) LZ4_unalign16;
392 LZ4_PACK(typedef struct { U32 u32; }) LZ4_unalign32;
393 LZ4_PACK(typedef struct { reg_t uArch; }) LZ4_unalignST;
394 
LZ4_read16(const void * ptr)395 static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign16*)ptr)->u16; }
LZ4_read32(const void * ptr)396 static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign32*)ptr)->u32; }
LZ4_read_ARCH(const void * ptr)397 static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalignST*)ptr)->uArch; }
398 
LZ4_write16(void * memPtr,U16 value)399 static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign16*)memPtr)->u16 = value; }
LZ4_write32(void * memPtr,U32 value)400 static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign32*)memPtr)->u32 = value; }
401 
402 #else  /* safe and portable access using memcpy() */
403 
LZ4_read16(const void * memPtr)404 static U16 LZ4_read16(const void* memPtr)
405 {
406     U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
407 }
408 
LZ4_read32(const void * memPtr)409 static U32 LZ4_read32(const void* memPtr)
410 {
411     U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
412 }
413 
LZ4_read_ARCH(const void * memPtr)414 static reg_t LZ4_read_ARCH(const void* memPtr)
415 {
416     reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
417 }
418 
LZ4_write16(void * memPtr,U16 value)419 static void LZ4_write16(void* memPtr, U16 value)
420 {
421     LZ4_memcpy(memPtr, &value, sizeof(value));
422 }
423 
LZ4_write32(void * memPtr,U32 value)424 static void LZ4_write32(void* memPtr, U32 value)
425 {
426     LZ4_memcpy(memPtr, &value, sizeof(value));
427 }
428 
429 #endif /* LZ4_FORCE_MEMORY_ACCESS */
430 
431 
LZ4_readLE16(const void * memPtr)432 static U16 LZ4_readLE16(const void* memPtr)
433 {
434     if (LZ4_isLittleEndian()) {
435         return LZ4_read16(memPtr);
436     } else {
437         const BYTE* p = (const BYTE*)memPtr;
438         return (U16)((U16)p[0] + (p[1]<<8));
439     }
440 }
441 
LZ4_writeLE16(void * memPtr,U16 value)442 static void LZ4_writeLE16(void* memPtr, U16 value)
443 {
444     if (LZ4_isLittleEndian()) {
445         LZ4_write16(memPtr, value);
446     } else {
447         BYTE* p = (BYTE*)memPtr;
448         p[0] = (BYTE) value;
449         p[1] = (BYTE)(value>>8);
450     }
451 }
452 
453 /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
454 LZ4_FORCE_INLINE
LZ4_wildCopy8(void * dstPtr,const void * srcPtr,void * dstEnd)455 void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd)
456 {
457     BYTE* d = (BYTE*)dstPtr;
458     const BYTE* s = (const BYTE*)srcPtr;
459     BYTE* const e = (BYTE*)dstEnd;
460 
461     do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d<e);
462 }
463 
464 static const unsigned inc32table[8] = {0, 1, 2,  1,  0,  4, 4, 4};
465 static const int      dec64table[8] = {0, 0, 0, -1, -4,  1, 2, 3};
466 
467 
468 #ifndef LZ4_FAST_DEC_LOOP
469 #  if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64
470 #    define LZ4_FAST_DEC_LOOP 1
471 #  elif defined(__aarch64__) && defined(__APPLE__)
472 #    define LZ4_FAST_DEC_LOOP 1
473 #  elif defined(__aarch64__) && !defined(__clang__)
474      /* On non-Apple aarch64, we disable this optimization for clang because
475       * on certain mobile chipsets, performance is reduced with clang. For
476       * more information refer to https://github.com/lz4/lz4/pull/707 */
477 #    define LZ4_FAST_DEC_LOOP 1
478 #  else
479 #    define LZ4_FAST_DEC_LOOP 0
480 #  endif
481 #endif
482 
483 #if LZ4_FAST_DEC_LOOP
484 
485 LZ4_FORCE_INLINE void
LZ4_memcpy_using_offset_base(BYTE * dstPtr,const BYTE * srcPtr,BYTE * dstEnd,const size_t offset)486 LZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)
487 {
488     assert(srcPtr + offset == dstPtr);
489     if (offset < 8) {
490         LZ4_write32(dstPtr, 0);   /* silence an msan warning when offset==0 */
491         dstPtr[0] = srcPtr[0];
492         dstPtr[1] = srcPtr[1];
493         dstPtr[2] = srcPtr[2];
494         dstPtr[3] = srcPtr[3];
495         srcPtr += inc32table[offset];
496         LZ4_memcpy(dstPtr+4, srcPtr, 4);
497         srcPtr -= dec64table[offset];
498         dstPtr += 8;
499     } else {
500         LZ4_memcpy(dstPtr, srcPtr, 8);
501         dstPtr += 8;
502         srcPtr += 8;
503     }
504 
505     LZ4_wildCopy8(dstPtr, srcPtr, dstEnd);
506 }
507 
508 /* customized variant of memcpy, which can overwrite up to 32 bytes beyond dstEnd
509  * this version copies two times 16 bytes (instead of one time 32 bytes)
510  * because it must be compatible with offsets >= 16. */
511 LZ4_FORCE_INLINE void
LZ4_wildCopy32(void * dstPtr,const void * srcPtr,void * dstEnd)512 LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd)
513 {
514     BYTE* d = (BYTE*)dstPtr;
515     const BYTE* s = (const BYTE*)srcPtr;
516     BYTE* const e = (BYTE*)dstEnd;
517 
518     do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e);
519 }
520 
521 /* LZ4_memcpy_using_offset()  presumes :
522  * - dstEnd >= dstPtr + MINMATCH
523  * - there is at least 8 bytes available to write after dstEnd */
524 LZ4_FORCE_INLINE void
LZ4_memcpy_using_offset(BYTE * dstPtr,const BYTE * srcPtr,BYTE * dstEnd,const size_t offset)525 LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)
526 {
527     BYTE v[8];
528 
529     assert(dstEnd >= dstPtr + MINMATCH);
530 
531     switch(offset) {
532     case 1:
533         MEM_INIT(v, *srcPtr, 8);
534         break;
535     case 2:
536         LZ4_memcpy(v, srcPtr, 2);
537         LZ4_memcpy(&v[2], srcPtr, 2);
538 #if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */
539 #  pragma warning(push)
540 #  pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */
541 #endif
542         LZ4_memcpy(&v[4], v, 4);
543 #if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */
544 #  pragma warning(pop)
545 #endif
546         break;
547     case 4:
548         LZ4_memcpy(v, srcPtr, 4);
549         LZ4_memcpy(&v[4], srcPtr, 4);
550         break;
551     default:
552         LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset);
553         return;
554     }
555 
556     LZ4_memcpy(dstPtr, v, 8);
557     dstPtr += 8;
558     while (dstPtr < dstEnd) {
559         LZ4_memcpy(dstPtr, v, 8);
560         dstPtr += 8;
561     }
562 }
563 #endif
564 
565 
566 /*-************************************
567 *  Common functions
568 **************************************/
LZ4_NbCommonBytes(reg_t val)569 static unsigned LZ4_NbCommonBytes (reg_t val)
570 {
571     assert(val != 0);
572     if (LZ4_isLittleEndian()) {
573         if (sizeof(val) == 8) {
574 #       if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) && !defined(_M_ARM64EC)) && !defined(LZ4_FORCE_SW_BITCOUNT)
575 /*-*************************************************************************************************
576 * ARM64EC is a Microsoft-designed ARM64 ABI compatible with AMD64 applications on ARM64 Windows 11.
577 * The ARM64EC ABI does not support AVX/AVX2/AVX512 instructions, nor their relevant intrinsics
578 * including _tzcnt_u64. Therefore, we need to neuter the _tzcnt_u64 code path for ARM64EC.
579 ****************************************************************************************************/
580 #         if defined(__clang__) && (__clang_major__ < 10)
581             /* Avoid undefined clang-cl intrinsics issue.
582              * See https://github.com/lz4/lz4/pull/1017 for details. */
583             return (unsigned)__builtin_ia32_tzcnt_u64(val) >> 3;
584 #         else
585             /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */
586             return (unsigned)_tzcnt_u64(val) >> 3;
587 #         endif
588 #       elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
589             unsigned long r = 0;
590             _BitScanForward64(&r, (U64)val);
591             return (unsigned)r >> 3;
592 #       elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
593                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
594                                         !defined(LZ4_FORCE_SW_BITCOUNT)
595             return (unsigned)__builtin_ctzll((U64)val) >> 3;
596 #       else
597             const U64 m = 0x0101010101010101ULL;
598             val ^= val - 1;
599             return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56);
600 #       endif
601         } else /* 32 bits */ {
602 #       if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
603             unsigned long r;
604             _BitScanForward(&r, (U32)val);
605             return (unsigned)r >> 3;
606 #       elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
607                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
608                         !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)
609             return (unsigned)__builtin_ctz((U32)val) >> 3;
610 #       else
611             const U32 m = 0x01010101;
612             return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;
613 #       endif
614         }
615     } else   /* Big Endian CPU */ {
616         if (sizeof(val)==8) {
617 #       if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
618                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
619                         !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)
620             return (unsigned)__builtin_clzll((U64)val) >> 3;
621 #       else
622 #if 1
623             /* this method is probably faster,
624              * but adds a 128 bytes lookup table */
625             static const unsigned char ctz7_tab[128] = {
626                 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
627                 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
628                 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
629                 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
630                 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
631                 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
632                 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
633                 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
634             };
635             U64 const mask = 0x0101010101010101ULL;
636             U64 const t = (((val >> 8) - mask) | val) & mask;
637             return ctz7_tab[(t * 0x0080402010080402ULL) >> 57];
638 #else
639             /* this method doesn't consume memory space like the previous one,
640              * but it contains several branches,
641              * that may end up slowing execution */
642             static const U32 by32 = sizeof(val)*4;  /* 32 on 64 bits (goal), 16 on 32 bits.
643             Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.
644             Note that this code path is never triggered in 32-bits mode. */
645             unsigned r;
646             if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; }
647             if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
648             r += (!val);
649             return r;
650 #endif
651 #       endif
652         } else /* 32 bits */ {
653 #       if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
654                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
655                                         !defined(LZ4_FORCE_SW_BITCOUNT)
656             return (unsigned)__builtin_clz((U32)val) >> 3;
657 #       else
658             val >>= 8;
659             val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |
660               (val + 0x00FF0000)) >> 24;
661             return (unsigned)val ^ 3;
662 #       endif
663         }
664     }
665 }
666 
667 
668 #define STEPSIZE sizeof(reg_t)
669 LZ4_FORCE_INLINE
LZ4_count(const BYTE * pIn,const BYTE * pMatch,const BYTE * pInLimit)670 unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
671 {
672     const BYTE* const pStart = pIn;
673 
674     if (likely(pIn < pInLimit-(STEPSIZE-1))) {
675         reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
676         if (!diff) {
677             pIn+=STEPSIZE; pMatch+=STEPSIZE;
678         } else {
679             return LZ4_NbCommonBytes(diff);
680     }   }
681 
682     while (likely(pIn < pInLimit-(STEPSIZE-1))) {
683         reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
684         if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
685         pIn += LZ4_NbCommonBytes(diff);
686         return (unsigned)(pIn - pStart);
687     }
688 
689     if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
690     if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
691     if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
692     return (unsigned)(pIn - pStart);
693 }
694 
695 
696 #ifndef LZ4_COMMONDEFS_ONLY
697 /*-************************************
698 *  Local Constants
699 **************************************/
700 static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
701 static const U32 LZ4_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */
702 
703 
704 /*-************************************
705 *  Local Structures and types
706 **************************************/
707 typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;
708 
709 /**
710  * This enum distinguishes several different modes of accessing previous
711  * content in the stream.
712  *
713  * - noDict        : There is no preceding content.
714  * - withPrefix64k : Table entries up to ctx->dictSize before the current blob
715  *                   blob being compressed are valid and refer to the preceding
716  *                   content (of length ctx->dictSize), which is available
717  *                   contiguously preceding in memory the content currently
718  *                   being compressed.
719  * - usingExtDict  : Like withPrefix64k, but the preceding content is somewhere
720  *                   else in memory, starting at ctx->dictionary with length
721  *                   ctx->dictSize.
722  * - usingDictCtx  : Everything concerning the preceding content is
723  *                   in a separate context, pointed to by ctx->dictCtx.
724  *                   ctx->dictionary, ctx->dictSize, and table entries
725  *                   in the current context that refer to positions
726  *                   preceding the beginning of the current compression are
727  *                   ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx
728  *                   ->dictSize describe the location and size of the preceding
729  *                   content, and matches are found by looking in the ctx
730  *                   ->dictCtx->hashTable.
731  */
732 typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive;
733 typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
734 
735 
736 /*-************************************
737 *  Local Utils
738 **************************************/
LZ4_versionNumber(void)739 int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
LZ4_versionString(void)740 const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
LZ4_compressBound(int isize)741 int LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }
LZ4_sizeofState(void)742 int LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); }
743 
744 
745 /*-****************************************
746 *  Internal Definitions, used only in Tests
747 *******************************************/
748 #if defined (__cplusplus)
749 extern "C" {
750 #endif
751 
752 int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize);
753 
754 int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
755                                      int compressedSize, int maxOutputSize,
756                                      const void* dictStart, size_t dictSize);
757 int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,
758                                      int compressedSize, int targetOutputSize, int dstCapacity,
759                                      const void* dictStart, size_t dictSize);
760 #if defined (__cplusplus)
761 }
762 #endif
763 
764 /*-******************************
765 *  Compression functions
766 ********************************/
LZ4_hash4(U32 sequence,tableType_t const tableType)767 LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
768 {
769     if (tableType == byU16)
770         return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
771     else
772         return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
773 }
774 
LZ4_hash5(U64 sequence,tableType_t const tableType)775 LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
776 {
777     const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
778     if (LZ4_isLittleEndian()) {
779         const U64 prime5bytes = 889523592379ULL;
780         return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
781     } else {
782         const U64 prime8bytes = 11400714785074694791ULL;
783         return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
784     }
785 }
786 
LZ4_hashPosition(const void * const p,tableType_t const tableType)787 LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
788 {
789     if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);
790     return LZ4_hash4(LZ4_read32(p), tableType);
791 }
792 
LZ4_clearHash(U32 h,void * tableBase,tableType_t const tableType)793 LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)
794 {
795     switch (tableType)
796     {
797     default: /* fallthrough */
798     case clearedTable: { /* illegal! */ assert(0); return; }
799     case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; }
800     case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; }
801     case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; }
802     }
803 }
804 
LZ4_putIndexOnHash(U32 idx,U32 h,void * tableBase,tableType_t const tableType)805 LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)
806 {
807     switch (tableType)
808     {
809     default: /* fallthrough */
810     case clearedTable: /* fallthrough */
811     case byPtr: { /* illegal! */ assert(0); return; }
812     case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; }
813     case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; }
814     }
815 }
816 
817 /* LZ4_putPosition*() : only used in byPtr mode */
LZ4_putPositionOnHash(const BYTE * p,U32 h,void * tableBase,tableType_t const tableType)818 LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h,
819                                   void* tableBase, tableType_t const tableType)
820 {
821     const BYTE** const hashTable = (const BYTE**)tableBase;
822     assert(tableType == byPtr); (void)tableType;
823     hashTable[h] = p;
824 }
825 
LZ4_putPosition(const BYTE * p,void * tableBase,tableType_t tableType)826 LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType)
827 {
828     U32 const h = LZ4_hashPosition(p, tableType);
829     LZ4_putPositionOnHash(p, h, tableBase, tableType);
830 }
831 
832 /* LZ4_getIndexOnHash() :
833  * Index of match position registered in hash table.
834  * hash position must be calculated by using base+index, or dictBase+index.
835  * Assumption 1 : only valid if tableType == byU32 or byU16.
836  * Assumption 2 : h is presumed valid (within limits of hash table)
837  */
LZ4_getIndexOnHash(U32 h,const void * tableBase,tableType_t tableType)838 LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)
839 {
840     LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2);
841     if (tableType == byU32) {
842         const U32* const hashTable = (const U32*) tableBase;
843         assert(h < (1U << (LZ4_MEMORY_USAGE-2)));
844         return hashTable[h];
845     }
846     if (tableType == byU16) {
847         const U16* const hashTable = (const U16*) tableBase;
848         assert(h < (1U << (LZ4_MEMORY_USAGE-1)));
849         return hashTable[h];
850     }
851     assert(0); return 0;  /* forbidden case */
852 }
853 
LZ4_getPositionOnHash(U32 h,const void * tableBase,tableType_t tableType)854 static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType)
855 {
856     assert(tableType == byPtr); (void)tableType;
857     { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; }
858 }
859 
860 LZ4_FORCE_INLINE const BYTE*
LZ4_getPosition(const BYTE * p,const void * tableBase,tableType_t tableType)861 LZ4_getPosition(const BYTE* p,
862                 const void* tableBase, tableType_t tableType)
863 {
864     U32 const h = LZ4_hashPosition(p, tableType);
865     return LZ4_getPositionOnHash(h, tableBase, tableType);
866 }
867 
868 LZ4_FORCE_INLINE void
LZ4_prepareTable(LZ4_stream_t_internal * const cctx,const int inputSize,const tableType_t tableType)869 LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
870            const int inputSize,
871            const tableType_t tableType) {
872     /* If the table hasn't been used, it's guaranteed to be zeroed out, and is
873      * therefore safe to use no matter what mode we're in. Otherwise, we figure
874      * out if it's safe to leave as is or whether it needs to be reset.
875      */
876     if ((tableType_t)cctx->tableType != clearedTable) {
877         assert(inputSize >= 0);
878         if ((tableType_t)cctx->tableType != tableType
879           || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU)
880           || ((tableType == byU32) && cctx->currentOffset > 1 GB)
881           || tableType == byPtr
882           || inputSize >= 4 KB)
883         {
884             DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx);
885             MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE);
886             cctx->currentOffset = 0;
887             cctx->tableType = (U32)clearedTable;
888         } else {
889             DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)");
890         }
891     }
892 
893     /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back,
894      * is faster than compressing without a gap.
895      * However, compressing with currentOffset == 0 is faster still,
896      * so we preserve that case.
897      */
898     if (cctx->currentOffset != 0 && tableType == byU32) {
899         DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset");
900         cctx->currentOffset += 64 KB;
901     }
902 
903     /* Finally, clear history */
904     cctx->dictCtx = NULL;
905     cctx->dictionary = NULL;
906     cctx->dictSize = 0;
907 }
908 
909 /** LZ4_compress_generic_validated() :
910  *  inlined, to ensure branches are decided at compilation time.
911  *  The following conditions are presumed already validated:
912  *  - source != NULL
913  *  - inputSize > 0
914  */
LZ4_compress_generic_validated(LZ4_stream_t_internal * const cctx,const char * const source,char * const dest,const int inputSize,int * inputConsumed,const int maxOutputSize,const limitedOutput_directive outputDirective,const tableType_t tableType,const dict_directive dictDirective,const dictIssue_directive dictIssue,const int acceleration)915 LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
916                  LZ4_stream_t_internal* const cctx,
917                  const char* const source,
918                  char* const dest,
919                  const int inputSize,
920                  int*  inputConsumed, /* only written when outputDirective == fillOutput */
921                  const int maxOutputSize,
922                  const limitedOutput_directive outputDirective,
923                  const tableType_t tableType,
924                  const dict_directive dictDirective,
925                  const dictIssue_directive dictIssue,
926                  const int acceleration)
927 {
928     int result;
929     const BYTE* ip = (const BYTE*)source;
930 
931     U32 const startIndex = cctx->currentOffset;
932     const BYTE* base = (const BYTE*)source - startIndex;
933     const BYTE* lowLimit;
934 
935     const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx;
936     const BYTE* const dictionary =
937         dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary;
938     const U32 dictSize =
939         dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize;
940     const U32 dictDelta =
941         (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0;   /* make indexes in dictCtx comparable with indexes in current context */
942 
943     int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx);
944     U32 const prefixIdxLimit = startIndex - dictSize;   /* used when dictDirective == dictSmall */
945     const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary;
946     const BYTE* anchor = (const BYTE*) source;
947     const BYTE* const iend = ip + inputSize;
948     const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;
949     const BYTE* const matchlimit = iend - LASTLITERALS;
950 
951     /* the dictCtx currentOffset is indexed on the start of the dictionary,
952      * while a dictionary in the current context precedes the currentOffset */
953     const BYTE* dictBase = (dictionary == NULL) ? NULL :
954                            (dictDirective == usingDictCtx) ?
955                             dictionary + dictSize - dictCtx->currentOffset :
956                             dictionary + dictSize - startIndex;
957 
958     BYTE* op = (BYTE*) dest;
959     BYTE* const olimit = op + maxOutputSize;
960 
961     U32 offset = 0;
962     U32 forwardH;
963 
964     DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType);
965     assert(ip != NULL);
966     if (tableType == byU16) assert(inputSize<LZ4_64Klimit);  /* Size too large (not within 64K limit) */
967     if (tableType == byPtr) assert(dictDirective==noDict);   /* only supported use case with byPtr */
968     /* If init conditions are not met, we don't have to mark stream
969      * as having dirty context, since no action was taken yet */
970     if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */
971     assert(acceleration >= 1);
972 
973     lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0);
974 
975     /* Update context state */
976     if (dictDirective == usingDictCtx) {
977         /* Subsequent linked blocks can't use the dictionary. */
978         /* Instead, they use the block we just compressed. */
979         cctx->dictCtx = NULL;
980         cctx->dictSize = (U32)inputSize;
981     } else {
982         cctx->dictSize += (U32)inputSize;
983     }
984     cctx->currentOffset += (U32)inputSize;
985     cctx->tableType = (U32)tableType;
986 
987     if (inputSize<LZ4_minLength) goto _last_literals;        /* Input too small, no compression (all literals) */
988 
989     /* First Byte */
990     {   U32 const h = LZ4_hashPosition(ip, tableType);
991         if (tableType == byPtr) {
992             LZ4_putPositionOnHash(ip, h, cctx->hashTable, byPtr);
993         } else {
994             LZ4_putIndexOnHash(startIndex, h, cctx->hashTable, tableType);
995     }   }
996     ip++; forwardH = LZ4_hashPosition(ip, tableType);
997 
998     /* Main Loop */
999     for ( ; ; ) {
1000         const BYTE* match;
1001         BYTE* token;
1002         const BYTE* filledIp;
1003 
1004         /* Find a match */
1005         if (tableType == byPtr) {
1006             const BYTE* forwardIp = ip;
1007             int step = 1;
1008             int searchMatchNb = acceleration << LZ4_skipTrigger;
1009             do {
1010                 U32 const h = forwardH;
1011                 ip = forwardIp;
1012                 forwardIp += step;
1013                 step = (searchMatchNb++ >> LZ4_skipTrigger);
1014 
1015                 if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;
1016                 assert(ip < mflimitPlusOne);
1017 
1018                 match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType);
1019                 forwardH = LZ4_hashPosition(forwardIp, tableType);
1020                 LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType);
1021 
1022             } while ( (match+LZ4_DISTANCE_MAX < ip)
1023                    || (LZ4_read32(match) != LZ4_read32(ip)) );
1024 
1025         } else {   /* byU32, byU16 */
1026 
1027             const BYTE* forwardIp = ip;
1028             int step = 1;
1029             int searchMatchNb = acceleration << LZ4_skipTrigger;
1030             do {
1031                 U32 const h = forwardH;
1032                 U32 const current = (U32)(forwardIp - base);
1033                 U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);
1034                 assert(matchIndex <= current);
1035                 assert(forwardIp - base < (ptrdiff_t)(2 GB - 1));
1036                 ip = forwardIp;
1037                 forwardIp += step;
1038                 step = (searchMatchNb++ >> LZ4_skipTrigger);
1039 
1040                 if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;
1041                 assert(ip < mflimitPlusOne);
1042 
1043                 if (dictDirective == usingDictCtx) {
1044                     if (matchIndex < startIndex) {
1045                         /* there was no match, try the dictionary */
1046                         assert(tableType == byU32);
1047                         matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);
1048                         match = dictBase + matchIndex;
1049                         matchIndex += dictDelta;   /* make dictCtx index comparable with current context */
1050                         lowLimit = dictionary;
1051                     } else {
1052                         match = base + matchIndex;
1053                         lowLimit = (const BYTE*)source;
1054                     }
1055                 } else if (dictDirective == usingExtDict) {
1056                     if (matchIndex < startIndex) {
1057                         DEBUGLOG(7, "extDict candidate: matchIndex=%5u  <  startIndex=%5u", matchIndex, startIndex);
1058                         assert(startIndex - matchIndex >= MINMATCH);
1059                         assert(dictBase);
1060                         match = dictBase + matchIndex;
1061                         lowLimit = dictionary;
1062                     } else {
1063                         match = base + matchIndex;
1064                         lowLimit = (const BYTE*)source;
1065                     }
1066                 } else {   /* single continuous memory segment */
1067                     match = base + matchIndex;
1068                 }
1069                 forwardH = LZ4_hashPosition(forwardIp, tableType);
1070                 LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
1071 
1072                 DEBUGLOG(7, "candidate at pos=%u  (offset=%u \n", matchIndex, current - matchIndex);
1073                 if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; }    /* match outside of valid area */
1074                 assert(matchIndex < current);
1075                 if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX))
1076                   && (matchIndex+LZ4_DISTANCE_MAX < current)) {
1077                     continue;
1078                 } /* too far */
1079                 assert((current - matchIndex) <= LZ4_DISTANCE_MAX);  /* match now expected within distance */
1080 
1081                 if (LZ4_read32(match) == LZ4_read32(ip)) {
1082                     if (maybe_extMem) offset = current - matchIndex;
1083                     break;   /* match found */
1084                 }
1085 
1086             } while(1);
1087         }
1088 
1089         /* Catch up */
1090         filledIp = ip;
1091         assert(ip > anchor); /* this is always true as ip has been advanced before entering the main loop */
1092         if ((match > lowLimit) && unlikely(ip[-1] == match[-1])) {
1093             do { ip--; match--; } while (((ip > anchor) & (match > lowLimit)) && (unlikely(ip[-1] == match[-1])));
1094         }
1095 
1096         /* Encode Literals */
1097         {   unsigned const litLength = (unsigned)(ip - anchor);
1098             token = op++;
1099             if ((outputDirective == limitedOutput) &&  /* Check output buffer overflow */
1100                 (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) {
1101                 return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
1102             }
1103             if ((outputDirective == fillOutput) &&
1104                 (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) {
1105                 op--;
1106                 goto _last_literals;
1107             }
1108             if (litLength >= RUN_MASK) {
1109                 int len = (int)(litLength - RUN_MASK);
1110                 *token = (RUN_MASK<<ML_BITS);
1111                 for(; len >= 255 ; len-=255) *op++ = 255;
1112                 *op++ = (BYTE)len;
1113             }
1114             else *token = (BYTE)(litLength<<ML_BITS);
1115 
1116             /* Copy Literals */
1117             LZ4_wildCopy8(op, anchor, op+litLength);
1118             op+=litLength;
1119             DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i",
1120                         (int)(anchor-(const BYTE*)source), litLength, (int)(ip-(const BYTE*)source));
1121         }
1122 
1123 _next_match:
1124         /* at this stage, the following variables must be correctly set :
1125          * - ip : at start of LZ operation
1126          * - match : at start of previous pattern occurrence; can be within current prefix, or within extDict
1127          * - offset : if maybe_ext_memSegment==1 (constant)
1128          * - lowLimit : must be == dictionary to mean "match is within extDict"; must be == source otherwise
1129          * - token and *token : position to write 4-bits for match length; higher 4-bits for literal length supposed already written
1130          */
1131 
1132         if ((outputDirective == fillOutput) &&
1133             (op + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit)) {
1134             /* the match was too close to the end, rewind and go to last literals */
1135             op = token;
1136             goto _last_literals;
1137         }
1138 
1139         /* Encode Offset */
1140         if (maybe_extMem) {   /* static test */
1141             DEBUGLOG(6, "             with offset=%u  (ext if > %i)", offset, (int)(ip - (const BYTE*)source));
1142             assert(offset <= LZ4_DISTANCE_MAX && offset > 0);
1143             LZ4_writeLE16(op, (U16)offset); op+=2;
1144         } else  {
1145             DEBUGLOG(6, "             with offset=%u  (same segment)", (U32)(ip - match));
1146             assert(ip-match <= LZ4_DISTANCE_MAX);
1147             LZ4_writeLE16(op, (U16)(ip - match)); op+=2;
1148         }
1149 
1150         /* Encode MatchLength */
1151         {   unsigned matchCode;
1152 
1153             if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx)
1154               && (lowLimit==dictionary) /* match within extDict */ ) {
1155                 const BYTE* limit = ip + (dictEnd-match);
1156                 assert(dictEnd > match);
1157                 if (limit > matchlimit) limit = matchlimit;
1158                 matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
1159                 ip += (size_t)matchCode + MINMATCH;
1160                 if (ip==limit) {
1161                     unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit);
1162                     matchCode += more;
1163                     ip += more;
1164                 }
1165                 DEBUGLOG(6, "             with matchLength=%u starting in extDict", matchCode+MINMATCH);
1166             } else {
1167                 matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
1168                 ip += (size_t)matchCode + MINMATCH;
1169                 DEBUGLOG(6, "             with matchLength=%u", matchCode+MINMATCH);
1170             }
1171 
1172             if ((outputDirective) &&    /* Check output buffer overflow */
1173                 (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) {
1174                 if (outputDirective == fillOutput) {
1175                     /* Match description too long : reduce it */
1176                     U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255;
1177                     ip -= matchCode - newMatchCode;
1178                     assert(newMatchCode < matchCode);
1179                     matchCode = newMatchCode;
1180                     if (unlikely(ip <= filledIp)) {
1181                         /* We have already filled up to filledIp so if ip ends up less than filledIp
1182                          * we have positions in the hash table beyond the current position. This is
1183                          * a problem if we reuse the hash table. So we have to remove these positions
1184                          * from the hash table.
1185                          */
1186                         const BYTE* ptr;
1187                         DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip));
1188                         for (ptr = ip; ptr <= filledIp; ++ptr) {
1189                             U32 const h = LZ4_hashPosition(ptr, tableType);
1190                             LZ4_clearHash(h, cctx->hashTable, tableType);
1191                         }
1192                     }
1193                 } else {
1194                     assert(outputDirective == limitedOutput);
1195                     return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
1196                 }
1197             }
1198             if (matchCode >= ML_MASK) {
1199                 *token += ML_MASK;
1200                 matchCode -= ML_MASK;
1201                 LZ4_write32(op, 0xFFFFFFFF);
1202                 while (matchCode >= 4*255) {
1203                     op+=4;
1204                     LZ4_write32(op, 0xFFFFFFFF);
1205                     matchCode -= 4*255;
1206                 }
1207                 op += matchCode / 255;
1208                 *op++ = (BYTE)(matchCode % 255);
1209             } else
1210                 *token += (BYTE)(matchCode);
1211         }
1212         /* Ensure we have enough space for the last literals. */
1213         assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit));
1214 
1215         anchor = ip;
1216 
1217         /* Test end of chunk */
1218         if (ip >= mflimitPlusOne) break;
1219 
1220         /* Fill table */
1221         {   U32 const h = LZ4_hashPosition(ip-2, tableType);
1222             if (tableType == byPtr) {
1223                 LZ4_putPositionOnHash(ip-2, h, cctx->hashTable, byPtr);
1224             } else {
1225                 U32 const idx = (U32)((ip-2) - base);
1226                 LZ4_putIndexOnHash(idx, h, cctx->hashTable, tableType);
1227         }   }
1228 
1229         /* Test next position */
1230         if (tableType == byPtr) {
1231 
1232             match = LZ4_getPosition(ip, cctx->hashTable, tableType);
1233             LZ4_putPosition(ip, cctx->hashTable, tableType);
1234             if ( (match+LZ4_DISTANCE_MAX >= ip)
1235               && (LZ4_read32(match) == LZ4_read32(ip)) )
1236             { token=op++; *token=0; goto _next_match; }
1237 
1238         } else {   /* byU32, byU16 */
1239 
1240             U32 const h = LZ4_hashPosition(ip, tableType);
1241             U32 const current = (U32)(ip-base);
1242             U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);
1243             assert(matchIndex < current);
1244             if (dictDirective == usingDictCtx) {
1245                 if (matchIndex < startIndex) {
1246                     /* there was no match, try the dictionary */
1247                     assert(tableType == byU32);
1248                     matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);
1249                     match = dictBase + matchIndex;
1250                     lowLimit = dictionary;   /* required for match length counter */
1251                     matchIndex += dictDelta;
1252                 } else {
1253                     match = base + matchIndex;
1254                     lowLimit = (const BYTE*)source;  /* required for match length counter */
1255                 }
1256             } else if (dictDirective==usingExtDict) {
1257                 if (matchIndex < startIndex) {
1258                     assert(dictBase);
1259                     match = dictBase + matchIndex;
1260                     lowLimit = dictionary;   /* required for match length counter */
1261                 } else {
1262                     match = base + matchIndex;
1263                     lowLimit = (const BYTE*)source;   /* required for match length counter */
1264                 }
1265             } else {   /* single memory segment */
1266                 match = base + matchIndex;
1267             }
1268             LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
1269             assert(matchIndex < current);
1270             if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1)
1271               && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current))
1272               && (LZ4_read32(match) == LZ4_read32(ip)) ) {
1273                 token=op++;
1274                 *token=0;
1275                 if (maybe_extMem) offset = current - matchIndex;
1276                 DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i",
1277                             (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source));
1278                 goto _next_match;
1279             }
1280         }
1281 
1282         /* Prepare next loop */
1283         forwardH = LZ4_hashPosition(++ip, tableType);
1284 
1285     }
1286 
1287 _last_literals:
1288     /* Encode Last Literals */
1289     {   size_t lastRun = (size_t)(iend - anchor);
1290         if ( (outputDirective) &&  /* Check output buffer overflow */
1291             (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) {
1292             if (outputDirective == fillOutput) {
1293                 /* adapt lastRun to fill 'dst' */
1294                 assert(olimit >= op);
1295                 lastRun  = (size_t)(olimit-op) - 1/*token*/;
1296                 lastRun -= (lastRun + 256 - RUN_MASK) / 256;  /*additional length tokens*/
1297             } else {
1298                 assert(outputDirective == limitedOutput);
1299                 return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
1300             }
1301         }
1302         DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun);
1303         if (lastRun >= RUN_MASK) {
1304             size_t accumulator = lastRun - RUN_MASK;
1305             *op++ = RUN_MASK << ML_BITS;
1306             for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
1307             *op++ = (BYTE) accumulator;
1308         } else {
1309             *op++ = (BYTE)(lastRun<<ML_BITS);
1310         }
1311         LZ4_memcpy(op, anchor, lastRun);
1312         ip = anchor + lastRun;
1313         op += lastRun;
1314     }
1315 
1316     if (outputDirective == fillOutput) {
1317         *inputConsumed = (int) (((const char*)ip)-source);
1318     }
1319     result = (int)(((char*)op) - dest);
1320     assert(result > 0);
1321     DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result);
1322     return result;
1323 }
1324 
1325 /** LZ4_compress_generic() :
1326  *  inlined, to ensure branches are decided at compilation time;
1327  *  takes care of src == (NULL, 0)
1328  *  and forward the rest to LZ4_compress_generic_validated */
LZ4_compress_generic(LZ4_stream_t_internal * const cctx,const char * const src,char * const dst,const int srcSize,int * inputConsumed,const int dstCapacity,const limitedOutput_directive outputDirective,const tableType_t tableType,const dict_directive dictDirective,const dictIssue_directive dictIssue,const int acceleration)1329 LZ4_FORCE_INLINE int LZ4_compress_generic(
1330                  LZ4_stream_t_internal* const cctx,
1331                  const char* const src,
1332                  char* const dst,
1333                  const int srcSize,
1334                  int *inputConsumed, /* only written when outputDirective == fillOutput */
1335                  const int dstCapacity,
1336                  const limitedOutput_directive outputDirective,
1337                  const tableType_t tableType,
1338                  const dict_directive dictDirective,
1339                  const dictIssue_directive dictIssue,
1340                  const int acceleration)
1341 {
1342     DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i",
1343                 srcSize, dstCapacity);
1344 
1345     if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; }  /* Unsupported srcSize, too large (or negative) */
1346     if (srcSize == 0) {   /* src == NULL supported if srcSize == 0 */
1347         if (outputDirective != notLimited && dstCapacity <= 0) return 0;  /* no output, can't write anything */
1348         DEBUGLOG(5, "Generating an empty block");
1349         assert(outputDirective == notLimited || dstCapacity >= 1);
1350         assert(dst != NULL);
1351         dst[0] = 0;
1352         if (outputDirective == fillOutput) {
1353             assert (inputConsumed != NULL);
1354             *inputConsumed = 0;
1355         }
1356         return 1;
1357     }
1358     assert(src != NULL);
1359 
1360     return LZ4_compress_generic_validated(cctx, src, dst, srcSize,
1361                 inputConsumed, /* only written into if outputDirective == fillOutput */
1362                 dstCapacity, outputDirective,
1363                 tableType, dictDirective, dictIssue, acceleration);
1364 }
1365 
1366 
LZ4_compress_fast_extState(void * state,const char * source,char * dest,int inputSize,int maxOutputSize,int acceleration)1367 int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
1368 {
1369     LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse;
1370     assert(ctx != NULL);
1371     if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
1372     if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
1373     if (maxOutputSize >= LZ4_compressBound(inputSize)) {
1374         if (inputSize < LZ4_64Klimit) {
1375             return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
1376         } else {
1377             const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
1378             return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
1379         }
1380     } else {
1381         if (inputSize < LZ4_64Klimit) {
1382             return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
1383         } else {
1384             const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
1385             return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration);
1386         }
1387     }
1388 }
1389 
1390 /**
1391  * LZ4_compress_fast_extState_fastReset() :
1392  * A variant of LZ4_compress_fast_extState().
1393  *
1394  * Using this variant avoids an expensive initialization step. It is only safe
1395  * to call if the state buffer is known to be correctly initialized already
1396  * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of
1397  * "correctly initialized").
1398  */
LZ4_compress_fast_extState_fastReset(void * state,const char * src,char * dst,int srcSize,int dstCapacity,int acceleration)1399 int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)
1400 {
1401     LZ4_stream_t_internal* const ctx = &((LZ4_stream_t*)state)->internal_donotuse;
1402     if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
1403     if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
1404     assert(ctx != NULL);
1405 
1406     if (dstCapacity >= LZ4_compressBound(srcSize)) {
1407         if (srcSize < LZ4_64Klimit) {
1408             const tableType_t tableType = byU16;
1409             LZ4_prepareTable(ctx, srcSize, tableType);
1410             if (ctx->currentOffset) {
1411                 return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, dictSmall, acceleration);
1412             } else {
1413                 return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
1414             }
1415         } else {
1416             const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
1417             LZ4_prepareTable(ctx, srcSize, tableType);
1418             return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
1419         }
1420     } else {
1421         if (srcSize < LZ4_64Klimit) {
1422             const tableType_t tableType = byU16;
1423             LZ4_prepareTable(ctx, srcSize, tableType);
1424             if (ctx->currentOffset) {
1425                 return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration);
1426             } else {
1427                 return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);
1428             }
1429         } else {
1430             const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
1431             LZ4_prepareTable(ctx, srcSize, tableType);
1432             return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);
1433         }
1434     }
1435 }
1436 
1437 
LZ4_compress_fast(const char * src,char * dest,int srcSize,int dstCapacity,int acceleration)1438 int LZ4_compress_fast(const char* src, char* dest, int srcSize, int dstCapacity, int acceleration)
1439 {
1440     int result;
1441 #if (LZ4_HEAPMODE)
1442     LZ4_stream_t* const ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
1443     if (ctxPtr == NULL) return 0;
1444 #else
1445     LZ4_stream_t ctx;
1446     LZ4_stream_t* const ctxPtr = &ctx;
1447 #endif
1448     result = LZ4_compress_fast_extState(ctxPtr, src, dest, srcSize, dstCapacity, acceleration);
1449 
1450 #if (LZ4_HEAPMODE)
1451     FREEMEM(ctxPtr);
1452 #endif
1453     return result;
1454 }
1455 
1456 
LZ4_compress_default(const char * src,char * dst,int srcSize,int dstCapacity)1457 int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity)
1458 {
1459     return LZ4_compress_fast(src, dst, srcSize, dstCapacity, 1);
1460 }
1461 
1462 
1463 /* Note!: This function leaves the stream in an unclean/broken state!
1464  * It is not safe to subsequently use the same state with a _fastReset() or
1465  * _continue() call without resetting it. */
LZ4_compress_destSize_extState(LZ4_stream_t * state,const char * src,char * dst,int * srcSizePtr,int targetDstSize)1466 static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
1467 {
1468     void* const s = LZ4_initStream(state, sizeof (*state));
1469     assert(s != NULL); (void)s;
1470 
1471     if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) {  /* compression success is guaranteed */
1472         return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
1473     } else {
1474         if (*srcSizePtr < LZ4_64Klimit) {
1475             return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, 1);
1476         } else {
1477             tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
1478             return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, 1);
1479     }   }
1480 }
1481 
1482 
LZ4_compress_destSize(const char * src,char * dst,int * srcSizePtr,int targetDstSize)1483 int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
1484 {
1485 #if (LZ4_HEAPMODE)
1486     LZ4_stream_t* const ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
1487     if (ctx == NULL) return 0;
1488 #else
1489     LZ4_stream_t ctxBody;
1490     LZ4_stream_t* const ctx = &ctxBody;
1491 #endif
1492 
1493     int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
1494 
1495 #if (LZ4_HEAPMODE)
1496     FREEMEM(ctx);
1497 #endif
1498     return result;
1499 }
1500 
1501 
1502 
1503 /*-******************************
1504 *  Streaming functions
1505 ********************************/
1506 
1507 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_createStream(void)1508 LZ4_stream_t* LZ4_createStream(void)
1509 {
1510     LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
1511     LZ4_STATIC_ASSERT(sizeof(LZ4_stream_t) >= sizeof(LZ4_stream_t_internal));
1512     DEBUGLOG(4, "LZ4_createStream %p", lz4s);
1513     if (lz4s == NULL) return NULL;
1514     LZ4_initStream(lz4s, sizeof(*lz4s));
1515     return lz4s;
1516 }
1517 #endif
1518 
LZ4_stream_t_alignment(void)1519 static size_t LZ4_stream_t_alignment(void)
1520 {
1521 #if LZ4_ALIGN_TEST
1522     typedef struct { char c; LZ4_stream_t t; } t_a;
1523     return sizeof(t_a) - sizeof(LZ4_stream_t);
1524 #else
1525     return 1;  /* effectively disabled */
1526 #endif
1527 }
1528 
LZ4_initStream(void * buffer,size_t size)1529 LZ4_stream_t* LZ4_initStream (void* buffer, size_t size)
1530 {
1531     DEBUGLOG(5, "LZ4_initStream");
1532     if (buffer == NULL) { return NULL; }
1533     if (size < sizeof(LZ4_stream_t)) { return NULL; }
1534     if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL;
1535     MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal));
1536     return (LZ4_stream_t*)buffer;
1537 }
1538 
1539 /* resetStream is now deprecated,
1540  * prefer initStream() which is more general */
LZ4_resetStream(LZ4_stream_t * LZ4_stream)1541 void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
1542 {
1543     DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream);
1544     MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal));
1545 }
1546 
LZ4_resetStream_fast(LZ4_stream_t * ctx)1547 void LZ4_resetStream_fast(LZ4_stream_t* ctx) {
1548     LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32);
1549 }
1550 
1551 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_freeStream(LZ4_stream_t * LZ4_stream)1552 int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
1553 {
1554     if (!LZ4_stream) return 0;   /* support free on NULL */
1555     DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream);
1556     FREEMEM(LZ4_stream);
1557     return (0);
1558 }
1559 #endif
1560 
1561 
1562 #define HASH_UNIT sizeof(reg_t)
LZ4_loadDict(LZ4_stream_t * LZ4_dict,const char * dictionary,int dictSize)1563 int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
1564 {
1565     LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
1566     const tableType_t tableType = byU32;
1567     const BYTE* p = (const BYTE*)dictionary;
1568     const BYTE* const dictEnd = p + dictSize;
1569     U32 idx32;
1570 
1571     DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict);
1572 
1573     /* It's necessary to reset the context,
1574      * and not just continue it with prepareTable()
1575      * to avoid any risk of generating overflowing matchIndex
1576      * when compressing using this dictionary */
1577     LZ4_resetStream(LZ4_dict);
1578 
1579     /* We always increment the offset by 64 KB, since, if the dict is longer,
1580      * we truncate it to the last 64k, and if it's shorter, we still want to
1581      * advance by a whole window length so we can provide the guarantee that
1582      * there are only valid offsets in the window, which allows an optimization
1583      * in LZ4_compress_fast_continue() where it uses noDictIssue even when the
1584      * dictionary isn't a full 64k. */
1585     dict->currentOffset += 64 KB;
1586 
1587     if (dictSize < (int)HASH_UNIT) {
1588         return 0;
1589     }
1590 
1591     if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
1592     dict->dictionary = p;
1593     dict->dictSize = (U32)(dictEnd - p);
1594     dict->tableType = (U32)tableType;
1595     idx32 = dict->currentOffset - dict->dictSize;
1596 
1597     while (p <= dictEnd-HASH_UNIT) {
1598         U32 const h = LZ4_hashPosition(p, tableType);
1599         LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType);
1600         p+=3; idx32+=3;
1601     }
1602 
1603     return (int)dict->dictSize;
1604 }
1605 
LZ4_attach_dictionary(LZ4_stream_t * workingStream,const LZ4_stream_t * dictionaryStream)1606 void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream)
1607 {
1608     const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL :
1609         &(dictionaryStream->internal_donotuse);
1610 
1611     DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)",
1612              workingStream, dictionaryStream,
1613              dictCtx != NULL ? dictCtx->dictSize : 0);
1614 
1615     if (dictCtx != NULL) {
1616         /* If the current offset is zero, we will never look in the
1617          * external dictionary context, since there is no value a table
1618          * entry can take that indicate a miss. In that case, we need
1619          * to bump the offset to something non-zero.
1620          */
1621         if (workingStream->internal_donotuse.currentOffset == 0) {
1622             workingStream->internal_donotuse.currentOffset = 64 KB;
1623         }
1624 
1625         /* Don't actually attach an empty dictionary.
1626          */
1627         if (dictCtx->dictSize == 0) {
1628             dictCtx = NULL;
1629         }
1630     }
1631     workingStream->internal_donotuse.dictCtx = dictCtx;
1632 }
1633 
1634 
LZ4_renormDictT(LZ4_stream_t_internal * LZ4_dict,int nextSize)1635 static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize)
1636 {
1637     assert(nextSize >= 0);
1638     if (LZ4_dict->currentOffset + (unsigned)nextSize > 0x80000000) {   /* potential ptrdiff_t overflow (32-bits mode) */
1639         /* rescale hash table */
1640         U32 const delta = LZ4_dict->currentOffset - 64 KB;
1641         const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
1642         int i;
1643         DEBUGLOG(4, "LZ4_renormDictT");
1644         for (i=0; i<LZ4_HASH_SIZE_U32; i++) {
1645             if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
1646             else LZ4_dict->hashTable[i] -= delta;
1647         }
1648         LZ4_dict->currentOffset = 64 KB;
1649         if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
1650         LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
1651     }
1652 }
1653 
1654 
LZ4_compress_fast_continue(LZ4_stream_t * LZ4_stream,const char * source,char * dest,int inputSize,int maxOutputSize,int acceleration)1655 int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
1656                                 const char* source, char* dest,
1657                                 int inputSize, int maxOutputSize,
1658                                 int acceleration)
1659 {
1660     const tableType_t tableType = byU32;
1661     LZ4_stream_t_internal* const streamPtr = &LZ4_stream->internal_donotuse;
1662     const char* dictEnd = streamPtr->dictSize ? (const char*)streamPtr->dictionary + streamPtr->dictSize : NULL;
1663 
1664     DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i, dictSize=%u)", inputSize, streamPtr->dictSize);
1665 
1666     LZ4_renormDictT(streamPtr, inputSize);   /* fix index overflow */
1667     if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
1668     if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
1669 
1670     /* invalidate tiny dictionaries */
1671     if ( (streamPtr->dictSize < 4)     /* tiny dictionary : not enough for a hash */
1672       && (dictEnd != source)           /* prefix mode */
1673       && (inputSize > 0)               /* tolerance : don't lose history, in case next invocation would use prefix mode */
1674       && (streamPtr->dictCtx == NULL)  /* usingDictCtx */
1675       ) {
1676         DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary);
1677         /* remove dictionary existence from history, to employ faster prefix mode */
1678         streamPtr->dictSize = 0;
1679         streamPtr->dictionary = (const BYTE*)source;
1680         dictEnd = source;
1681     }
1682 
1683     /* Check overlapping input/dictionary space */
1684     {   const char* const sourceEnd = source + inputSize;
1685         if ((sourceEnd > (const char*)streamPtr->dictionary) && (sourceEnd < dictEnd)) {
1686             streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
1687             if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
1688             if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
1689             streamPtr->dictionary = (const BYTE*)dictEnd - streamPtr->dictSize;
1690         }
1691     }
1692 
1693     /* prefix mode : source data follows dictionary */
1694     if (dictEnd == source) {
1695         if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
1696             return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration);
1697         else
1698             return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration);
1699     }
1700 
1701     /* external dictionary mode */
1702     {   int result;
1703         if (streamPtr->dictCtx) {
1704             /* We depend here on the fact that dictCtx'es (produced by
1705              * LZ4_loadDict) guarantee that their tables contain no references
1706              * to offsets between dictCtx->currentOffset - 64 KB and
1707              * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe
1708              * to use noDictIssue even when the dict isn't a full 64 KB.
1709              */
1710             if (inputSize > 4 KB) {
1711                 /* For compressing large blobs, it is faster to pay the setup
1712                  * cost to copy the dictionary's tables into the active context,
1713                  * so that the compression loop is only looking into one table.
1714                  */
1715                 LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr));
1716                 result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
1717             } else {
1718                 result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);
1719             }
1720         } else {  /* small data <= 4 KB */
1721             if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {
1722                 result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration);
1723             } else {
1724                 result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
1725             }
1726         }
1727         streamPtr->dictionary = (const BYTE*)source;
1728         streamPtr->dictSize = (U32)inputSize;
1729         return result;
1730     }
1731 }
1732 
1733 
1734 /* Hidden debug function, to force-test external dictionary mode */
LZ4_compress_forceExtDict(LZ4_stream_t * LZ4_dict,const char * source,char * dest,int srcSize)1735 int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize)
1736 {
1737     LZ4_stream_t_internal* const streamPtr = &LZ4_dict->internal_donotuse;
1738     int result;
1739 
1740     LZ4_renormDictT(streamPtr, srcSize);
1741 
1742     if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {
1743         result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, dictSmall, 1);
1744     } else {
1745         result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
1746     }
1747 
1748     streamPtr->dictionary = (const BYTE*)source;
1749     streamPtr->dictSize = (U32)srcSize;
1750 
1751     return result;
1752 }
1753 
1754 
1755 /*! LZ4_saveDict() :
1756  *  If previously compressed data block is not guaranteed to remain available at its memory location,
1757  *  save it into a safer place (char* safeBuffer).
1758  *  Note : no need to call LZ4_loadDict() afterwards, dictionary is immediately usable,
1759  *         one can therefore call LZ4_compress_fast_continue() right after.
1760  * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
1761  */
LZ4_saveDict(LZ4_stream_t * LZ4_dict,char * safeBuffer,int dictSize)1762 int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
1763 {
1764     LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
1765 
1766     DEBUGLOG(5, "LZ4_saveDict : dictSize=%i, safeBuffer=%p", dictSize, safeBuffer);
1767 
1768     if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
1769     if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
1770 
1771     if (safeBuffer == NULL) assert(dictSize == 0);
1772     if (dictSize > 0) {
1773         const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
1774         assert(dict->dictionary);
1775         LZ4_memmove(safeBuffer, previousDictEnd - dictSize, (size_t)dictSize);
1776     }
1777 
1778     dict->dictionary = (const BYTE*)safeBuffer;
1779     dict->dictSize = (U32)dictSize;
1780 
1781     return dictSize;
1782 }
1783 
1784 
1785 
1786 /*-*******************************
1787  *  Decompression functions
1788  ********************************/
1789 
1790 typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
1791 
1792 #undef MIN
1793 #define MIN(a,b)    ( (a) < (b) ? (a) : (b) )
1794 
1795 
1796 /* variant for decompress_unsafe()
1797  * does not know end of input
1798  * presumes input is well formed
1799  * note : will consume at least one byte */
read_long_length_no_check(const BYTE ** pp)1800 static size_t read_long_length_no_check(const BYTE** pp)
1801 {
1802     size_t b, l = 0;
1803     do { b = **pp; (*pp)++; l += b; } while (b==255);
1804     DEBUGLOG(6, "read_long_length_no_check: +length=%zu using %zu input bytes", l, l/255 + 1)
1805     return l;
1806 }
1807 
1808 /* core decoder variant for LZ4_decompress_fast*()
1809  * for legacy support only : these entry points are deprecated.
1810  * - Presumes input is correctly formed (no defense vs malformed inputs)
1811  * - Does not know input size (presume input buffer is "large enough")
1812  * - Decompress a full block (only)
1813  * @return : nb of bytes read from input.
1814  * Note : this variant is not optimized for speed, just for maintenance.
1815  *        the goal is to remove support of decompress_fast*() variants by v2.0
1816 **/
1817 LZ4_FORCE_INLINE int
LZ4_decompress_unsafe_generic(const BYTE * const istart,BYTE * const ostart,int decompressedSize,size_t prefixSize,const BYTE * const dictStart,const size_t dictSize)1818 LZ4_decompress_unsafe_generic(
1819                  const BYTE* const istart,
1820                  BYTE* const ostart,
1821                  int decompressedSize,
1822 
1823                  size_t prefixSize,
1824                  const BYTE* const dictStart,  /* only if dict==usingExtDict */
1825                  const size_t dictSize         /* note: =0 if dictStart==NULL */
1826                  )
1827 {
1828     const BYTE* ip = istart;
1829     BYTE* op = (BYTE*)ostart;
1830     BYTE* const oend = ostart + decompressedSize;
1831     const BYTE* const prefixStart = ostart - prefixSize;
1832 
1833     DEBUGLOG(5, "LZ4_decompress_unsafe_generic");
1834     if (dictStart == NULL) assert(dictSize == 0);
1835 
1836     while (1) {
1837         /* start new sequence */
1838         unsigned token = *ip++;
1839 
1840         /* literals */
1841         {   size_t ll = token >> ML_BITS;
1842             if (ll==15) {
1843                 /* long literal length */
1844                 ll += read_long_length_no_check(&ip);
1845             }
1846             if ((size_t)(oend-op) < ll) return -1; /* output buffer overflow */
1847             LZ4_memmove(op, ip, ll); /* support in-place decompression */
1848             op += ll;
1849             ip += ll;
1850             if ((size_t)(oend-op) < MFLIMIT) {
1851                 if (op==oend) break;  /* end of block */
1852                 DEBUGLOG(5, "invalid: literals end at distance %zi from end of block", oend-op);
1853                 /* incorrect end of block :
1854                  * last match must start at least MFLIMIT==12 bytes before end of output block */
1855                 return -1;
1856         }   }
1857 
1858         /* match */
1859         {   size_t ml = token & 15;
1860             size_t const offset = LZ4_readLE16(ip);
1861             ip+=2;
1862 
1863             if (ml==15) {
1864                 /* long literal length */
1865                 ml += read_long_length_no_check(&ip);
1866             }
1867             ml += MINMATCH;
1868 
1869             if ((size_t)(oend-op) < ml) return -1; /* output buffer overflow */
1870 
1871             {   const BYTE* match = op - offset;
1872 
1873                 /* out of range */
1874                 if (offset > (size_t)(op - prefixStart) + dictSize) {
1875                     DEBUGLOG(6, "offset out of range");
1876                     return -1;
1877                 }
1878 
1879                 /* check special case : extDict */
1880                 if (offset > (size_t)(op - prefixStart)) {
1881                     /* extDict scenario */
1882                     const BYTE* const dictEnd = dictStart + dictSize;
1883                     const BYTE* extMatch = dictEnd - (offset - (size_t)(op-prefixStart));
1884                     size_t const extml = (size_t)(dictEnd - extMatch);
1885                     if (extml > ml) {
1886                         /* match entirely within extDict */
1887                         LZ4_memmove(op, extMatch, ml);
1888                         op += ml;
1889                         ml = 0;
1890                     } else {
1891                         /* match split between extDict & prefix */
1892                         LZ4_memmove(op, extMatch, extml);
1893                         op += extml;
1894                         ml -= extml;
1895                     }
1896                     match = prefixStart;
1897                 }
1898 
1899                 /* match copy - slow variant, supporting overlap copy */
1900                 {   size_t u;
1901                     for (u=0; u<ml; u++) {
1902                         op[u] = match[u];
1903             }   }   }
1904             op += ml;
1905             if ((size_t)(oend-op) < LASTLITERALS) {
1906                 DEBUGLOG(5, "invalid: match ends at distance %zi from end of block", oend-op);
1907                 /* incorrect end of block :
1908                  * last match must stop at least LASTLITERALS==5 bytes before end of output block */
1909                 return -1;
1910             }
1911         } /* match */
1912     } /* main loop */
1913     return (int)(ip - istart);
1914 }
1915 
1916 
1917 /* Read the variable-length literal or match length.
1918  *
1919  * @ip : input pointer
1920  * @ilimit : position after which if length is not decoded, the input is necessarily corrupted.
1921  * @initial_check - check ip >= ipmax before start of loop.  Returns initial_error if so.
1922  * @error (output) - error code.  Must be set to 0 before call.
1923 **/
1924 typedef size_t Rvl_t;
1925 static const Rvl_t rvl_error = (Rvl_t)(-1);
1926 LZ4_FORCE_INLINE Rvl_t
read_variable_length(const BYTE ** ip,const BYTE * ilimit,int initial_check)1927 read_variable_length(const BYTE** ip, const BYTE* ilimit,
1928                      int initial_check)
1929 {
1930     Rvl_t s, length = 0;
1931     assert(ip != NULL);
1932     assert(*ip !=  NULL);
1933     assert(ilimit != NULL);
1934     if (initial_check && unlikely((*ip) >= ilimit)) {    /* read limit reached */
1935         return rvl_error;
1936     }
1937     do {
1938         s = **ip;
1939         (*ip)++;
1940         length += s;
1941         if (unlikely((*ip) > ilimit)) {    /* read limit reached */
1942             return rvl_error;
1943         }
1944         /* accumulator overflow detection (32-bit mode only) */
1945         if ((sizeof(length)<8) && unlikely(length > ((Rvl_t)(-1)/2)) ) {
1946             return rvl_error;
1947         }
1948     } while (s==255);
1949 
1950     return length;
1951 }
1952 
1953 /*! LZ4_decompress_generic() :
1954  *  This generic decompression function covers all use cases.
1955  *  It shall be instantiated several times, using different sets of directives.
1956  *  Note that it is important for performance that this function really get inlined,
1957  *  in order to remove useless branches during compilation optimization.
1958  */
1959 LZ4_FORCE_INLINE int
LZ4_decompress_generic(const char * const src,char * const dst,int srcSize,int outputSize,earlyEnd_directive partialDecoding,dict_directive dict,const BYTE * const lowPrefix,const BYTE * const dictStart,const size_t dictSize)1960 LZ4_decompress_generic(
1961                  const char* const src,
1962                  char* const dst,
1963                  int srcSize,
1964                  int outputSize,         /* If endOnInput==endOnInputSize, this value is `dstCapacity` */
1965 
1966                  earlyEnd_directive partialDecoding,  /* full, partial */
1967                  dict_directive dict,                 /* noDict, withPrefix64k, usingExtDict */
1968                  const BYTE* const lowPrefix,  /* always <= dst, == dst when no prefix */
1969                  const BYTE* const dictStart,  /* only if dict==usingExtDict */
1970                  const size_t dictSize         /* note : = 0 if noDict */
1971                  )
1972 {
1973     if ((src == NULL) || (outputSize < 0)) { return -1; }
1974 
1975     {   const BYTE* ip = (const BYTE*) src;
1976         const BYTE* const iend = ip + srcSize;
1977 
1978         BYTE* op = (BYTE*) dst;
1979         BYTE* const oend = op + outputSize;
1980         BYTE* cpy;
1981 
1982         const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize;
1983 
1984         const int checkOffset = (dictSize < (int)(64 KB));
1985 
1986 
1987         /* Set up the "end" pointers for the shortcut. */
1988         const BYTE* const shortiend = iend - 14 /*maxLL*/ - 2 /*offset*/;
1989         const BYTE* const shortoend = oend - 14 /*maxLL*/ - 18 /*maxML*/;
1990 
1991         const BYTE* match;
1992         size_t offset;
1993         unsigned token;
1994         size_t length;
1995 
1996 
1997         DEBUGLOG(5, "LZ4_decompress_generic (srcSize:%i, dstSize:%i)", srcSize, outputSize);
1998 
1999         /* Special cases */
2000         assert(lowPrefix <= op);
2001         if (unlikely(outputSize==0)) {
2002             /* Empty output buffer */
2003             if (partialDecoding) return 0;
2004             return ((srcSize==1) && (*ip==0)) ? 0 : -1;
2005         }
2006         if (unlikely(srcSize==0)) { return -1; }
2007 
2008     /* LZ4_FAST_DEC_LOOP:
2009      * designed for modern OoO performance cpus,
2010      * where copying reliably 32-bytes is preferable to an unpredictable branch.
2011      * note : fast loop may show a regression for some client arm chips. */
2012 #if LZ4_FAST_DEC_LOOP
2013         if ((oend - op) < FASTLOOP_SAFE_DISTANCE) {
2014             DEBUGLOG(6, "skip fast decode loop");
2015             goto safe_decode;
2016         }
2017 
2018         /* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */
2019         DEBUGLOG(6, "using fast decode loop");
2020         while (1) {
2021             /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */
2022             assert(oend - op >= FASTLOOP_SAFE_DISTANCE);
2023             assert(ip < iend);
2024             token = *ip++;
2025             length = token >> ML_BITS;  /* literal length */
2026 
2027             /* decode literal length */
2028             if (length == RUN_MASK) {
2029                 size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);
2030                 if (addl == rvl_error) {
2031                     DEBUGLOG(6, "error reading long literal length");
2032                     goto _output_error;
2033                 }
2034                 length += addl;
2035                 if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
2036                 if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
2037 
2038                 /* copy literals */
2039                 LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
2040                 if ((op+length>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }
2041                 LZ4_wildCopy32(op, ip, op+length);
2042                 ip += length; op += length;
2043             } else if (ip <= iend-(16 + 1/*max lit + offset + nextToken*/)) {
2044                 /* We don't need to check oend, since we check it once for each loop below */
2045                 DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length);
2046                 /* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */
2047                 LZ4_memcpy(op, ip, 16);
2048                 ip += length; op += length;
2049             } else {
2050                 goto safe_literal_copy;
2051             }
2052 
2053             /* get offset */
2054             offset = LZ4_readLE16(ip); ip+=2;
2055             DEBUGLOG(6, " offset = %zu", offset);
2056             match = op - offset;
2057             assert(match <= op);  /* overflow check */
2058 
2059             /* get matchlength */
2060             length = token & ML_MASK;
2061 
2062             if (length == ML_MASK) {
2063                 size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);
2064                 if (addl == rvl_error) {
2065                     DEBUGLOG(6, "error reading long match length");
2066                     goto _output_error;
2067                 }
2068                 length += addl;
2069                 length += MINMATCH;
2070                 if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */
2071                 if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
2072                     goto safe_match_copy;
2073                 }
2074             } else {
2075                 length += MINMATCH;
2076                 if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
2077                     goto safe_match_copy;
2078                 }
2079 
2080                 /* Fastpath check: skip LZ4_wildCopy32 when true */
2081                 if ((dict == withPrefix64k) || (match >= lowPrefix)) {
2082                     if (offset >= 8) {
2083                         assert(match >= lowPrefix);
2084                         assert(match <= op);
2085                         assert(op + 18 <= oend);
2086 
2087                         LZ4_memcpy(op, match, 8);
2088                         LZ4_memcpy(op+8, match+8, 8);
2089                         LZ4_memcpy(op+16, match+16, 2);
2090                         op += length;
2091                         continue;
2092             }   }   }
2093 
2094             if ( checkOffset && (unlikely(match + dictSize < lowPrefix)) ) {
2095                 DEBUGLOG(6, "Error : pos=%zi, offset=%zi => outside buffers", op-lowPrefix, op-match);
2096                 goto _output_error;
2097             }
2098             /* match starting within external dictionary */
2099             if ((dict==usingExtDict) && (match < lowPrefix)) {
2100                 assert(dictEnd != NULL);
2101                 if (unlikely(op+length > oend-LASTLITERALS)) {
2102                     if (partialDecoding) {
2103                         DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd");
2104                         length = MIN(length, (size_t)(oend-op));
2105                     } else {
2106                         DEBUGLOG(6, "end-of-block condition violated")
2107                         goto _output_error;
2108                 }   }
2109 
2110                 if (length <= (size_t)(lowPrefix-match)) {
2111                     /* match fits entirely within external dictionary : just copy */
2112                     LZ4_memmove(op, dictEnd - (lowPrefix-match), length);
2113                     op += length;
2114                 } else {
2115                     /* match stretches into both external dictionary and current block */
2116                     size_t const copySize = (size_t)(lowPrefix - match);
2117                     size_t const restSize = length - copySize;
2118                     LZ4_memcpy(op, dictEnd - copySize, copySize);
2119                     op += copySize;
2120                     if (restSize > (size_t)(op - lowPrefix)) {  /* overlap copy */
2121                         BYTE* const endOfMatch = op + restSize;
2122                         const BYTE* copyFrom = lowPrefix;
2123                         while (op < endOfMatch) { *op++ = *copyFrom++; }
2124                     } else {
2125                         LZ4_memcpy(op, lowPrefix, restSize);
2126                         op += restSize;
2127                 }   }
2128                 continue;
2129             }
2130 
2131             /* copy match within block */
2132             cpy = op + length;
2133 
2134             assert((op <= oend) && (oend-op >= 32));
2135             if (unlikely(offset<16)) {
2136                 LZ4_memcpy_using_offset(op, match, cpy, offset);
2137             } else {
2138                 LZ4_wildCopy32(op, match, cpy);
2139             }
2140 
2141             op = cpy;   /* wildcopy correction */
2142         }
2143     safe_decode:
2144 #endif
2145 
2146         /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */
2147         DEBUGLOG(6, "using safe decode loop");
2148         while (1) {
2149             assert(ip < iend);
2150             token = *ip++;
2151             length = token >> ML_BITS;  /* literal length */
2152 
2153             /* A two-stage shortcut for the most common case:
2154              * 1) If the literal length is 0..14, and there is enough space,
2155              * enter the shortcut and copy 16 bytes on behalf of the literals
2156              * (in the fast mode, only 8 bytes can be safely copied this way).
2157              * 2) Further if the match length is 4..18, copy 18 bytes in a similar
2158              * manner; but we ensure that there's enough space in the output for
2159              * those 18 bytes earlier, upon entering the shortcut (in other words,
2160              * there is a combined check for both stages).
2161              */
2162             if ( (length != RUN_MASK)
2163                 /* strictly "less than" on input, to re-enter the loop with at least one byte */
2164               && likely((ip < shortiend) & (op <= shortoend)) ) {
2165                 /* Copy the literals */
2166                 LZ4_memcpy(op, ip, 16);
2167                 op += length; ip += length;
2168 
2169                 /* The second stage: prepare for match copying, decode full info.
2170                  * If it doesn't work out, the info won't be wasted. */
2171                 length = token & ML_MASK; /* match length */
2172                 offset = LZ4_readLE16(ip); ip += 2;
2173                 match = op - offset;
2174                 assert(match <= op); /* check overflow */
2175 
2176                 /* Do not deal with overlapping matches. */
2177                 if ( (length != ML_MASK)
2178                   && (offset >= 8)
2179                   && (dict==withPrefix64k || match >= lowPrefix) ) {
2180                     /* Copy the match. */
2181                     LZ4_memcpy(op + 0, match + 0, 8);
2182                     LZ4_memcpy(op + 8, match + 8, 8);
2183                     LZ4_memcpy(op +16, match +16, 2);
2184                     op += length + MINMATCH;
2185                     /* Both stages worked, load the next token. */
2186                     continue;
2187                 }
2188 
2189                 /* The second stage didn't work out, but the info is ready.
2190                  * Propel it right to the point of match copying. */
2191                 goto _copy_match;
2192             }
2193 
2194             /* decode literal length */
2195             if (length == RUN_MASK) {
2196                 size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);
2197                 if (addl == rvl_error) { goto _output_error; }
2198                 length += addl;
2199                 if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
2200                 if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
2201             }
2202 
2203 #if LZ4_FAST_DEC_LOOP
2204         safe_literal_copy:
2205 #endif
2206             /* copy literals */
2207             cpy = op+length;
2208 
2209             LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
2210             if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) {
2211                 /* We've either hit the input parsing restriction or the output parsing restriction.
2212                  * In the normal scenario, decoding a full block, it must be the last sequence,
2213                  * otherwise it's an error (invalid input or dimensions).
2214                  * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow.
2215                  */
2216                 if (partialDecoding) {
2217                     /* Since we are partial decoding we may be in this block because of the output parsing
2218                      * restriction, which is not valid since the output buffer is allowed to be undersized.
2219                      */
2220                     DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end")
2221                     DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length);
2222                     DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op));
2223                     DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip));
2224                     /* Finishing in the middle of a literals segment,
2225                      * due to lack of input.
2226                      */
2227                     if (ip+length > iend) {
2228                         length = (size_t)(iend-ip);
2229                         cpy = op + length;
2230                     }
2231                     /* Finishing in the middle of a literals segment,
2232                      * due to lack of output space.
2233                      */
2234                     if (cpy > oend) {
2235                         cpy = oend;
2236                         assert(op<=oend);
2237                         length = (size_t)(oend-op);
2238                     }
2239                 } else {
2240                      /* We must be on the last sequence (or invalid) because of the parsing limitations
2241                       * so check that we exactly consume the input and don't overrun the output buffer.
2242                       */
2243                     if ((ip+length != iend) || (cpy > oend)) {
2244                         DEBUGLOG(6, "should have been last run of literals")
2245                         DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend);
2246                         DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);
2247                         goto _output_error;
2248                     }
2249                 }
2250                 LZ4_memmove(op, ip, length);  /* supports overlapping memory regions, for in-place decompression scenarios */
2251                 ip += length;
2252                 op += length;
2253                 /* Necessarily EOF when !partialDecoding.
2254                  * When partialDecoding, it is EOF if we've either
2255                  * filled the output buffer or
2256                  * can't proceed with reading an offset for following match.
2257                  */
2258                 if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) {
2259                     break;
2260                 }
2261             } else {
2262                 LZ4_wildCopy8(op, ip, cpy);   /* can overwrite up to 8 bytes beyond cpy */
2263                 ip += length; op = cpy;
2264             }
2265 
2266             /* get offset */
2267             offset = LZ4_readLE16(ip); ip+=2;
2268             match = op - offset;
2269 
2270             /* get matchlength */
2271             length = token & ML_MASK;
2272 
2273     _copy_match:
2274             if (length == ML_MASK) {
2275                 size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);
2276                 if (addl == rvl_error) { goto _output_error; }
2277                 length += addl;
2278                 if (unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error;   /* overflow detection */
2279             }
2280             length += MINMATCH;
2281 
2282 #if LZ4_FAST_DEC_LOOP
2283         safe_match_copy:
2284 #endif
2285             if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error;   /* Error : offset outside buffers */
2286             /* match starting within external dictionary */
2287             if ((dict==usingExtDict) && (match < lowPrefix)) {
2288                 assert(dictEnd != NULL);
2289                 if (unlikely(op+length > oend-LASTLITERALS)) {
2290                     if (partialDecoding) length = MIN(length, (size_t)(oend-op));
2291                     else goto _output_error;   /* doesn't respect parsing restriction */
2292                 }
2293 
2294                 if (length <= (size_t)(lowPrefix-match)) {
2295                     /* match fits entirely within external dictionary : just copy */
2296                     LZ4_memmove(op, dictEnd - (lowPrefix-match), length);
2297                     op += length;
2298                 } else {
2299                     /* match stretches into both external dictionary and current block */
2300                     size_t const copySize = (size_t)(lowPrefix - match);
2301                     size_t const restSize = length - copySize;
2302                     LZ4_memcpy(op, dictEnd - copySize, copySize);
2303                     op += copySize;
2304                     if (restSize > (size_t)(op - lowPrefix)) {  /* overlap copy */
2305                         BYTE* const endOfMatch = op + restSize;
2306                         const BYTE* copyFrom = lowPrefix;
2307                         while (op < endOfMatch) *op++ = *copyFrom++;
2308                     } else {
2309                         LZ4_memcpy(op, lowPrefix, restSize);
2310                         op += restSize;
2311                 }   }
2312                 continue;
2313             }
2314             assert(match >= lowPrefix);
2315 
2316             /* copy match within block */
2317             cpy = op + length;
2318 
2319             /* partialDecoding : may end anywhere within the block */
2320             assert(op<=oend);
2321             if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {
2322                 size_t const mlen = MIN(length, (size_t)(oend-op));
2323                 const BYTE* const matchEnd = match + mlen;
2324                 BYTE* const copyEnd = op + mlen;
2325                 if (matchEnd > op) {   /* overlap copy */
2326                     while (op < copyEnd) { *op++ = *match++; }
2327                 } else {
2328                     LZ4_memcpy(op, match, mlen);
2329                 }
2330                 op = copyEnd;
2331                 if (op == oend) { break; }
2332                 continue;
2333             }
2334 
2335             if (unlikely(offset<8)) {
2336                 LZ4_write32(op, 0);   /* silence msan warning when offset==0 */
2337                 op[0] = match[0];
2338                 op[1] = match[1];
2339                 op[2] = match[2];
2340                 op[3] = match[3];
2341                 match += inc32table[offset];
2342                 LZ4_memcpy(op+4, match, 4);
2343                 match -= dec64table[offset];
2344             } else {
2345                 LZ4_memcpy(op, match, 8);
2346                 match += 8;
2347             }
2348             op += 8;
2349 
2350             if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {
2351                 BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1);
2352                 if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
2353                 if (op < oCopyLimit) {
2354                     LZ4_wildCopy8(op, match, oCopyLimit);
2355                     match += oCopyLimit - op;
2356                     op = oCopyLimit;
2357                 }
2358                 while (op < cpy) { *op++ = *match++; }
2359             } else {
2360                 LZ4_memcpy(op, match, 8);
2361                 if (length > 16)  { LZ4_wildCopy8(op+8, match+8, cpy); }
2362             }
2363             op = cpy;   /* wildcopy correction */
2364         }
2365 
2366         /* end of decoding */
2367         DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst));
2368         return (int) (((char*)op)-dst);     /* Nb of output bytes decoded */
2369 
2370         /* Overflow error detected */
2371     _output_error:
2372         return (int) (-(((const char*)ip)-src))-1;
2373     }
2374 }
2375 
2376 
2377 /*===== Instantiate the API decoding functions. =====*/
2378 
2379 LZ4_FORCE_O2
LZ4_decompress_safe(const char * source,char * dest,int compressedSize,int maxDecompressedSize)2380 int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
2381 {
2382     return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,
2383                                   decode_full_block, noDict,
2384                                   (BYTE*)dest, NULL, 0);
2385 }
2386 
2387 LZ4_FORCE_O2
LZ4_decompress_safe_partial(const char * src,char * dst,int compressedSize,int targetOutputSize,int dstCapacity)2388 int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity)
2389 {
2390     dstCapacity = MIN(targetOutputSize, dstCapacity);
2391     return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
2392                                   partial_decode,
2393                                   noDict, (BYTE*)dst, NULL, 0);
2394 }
2395 
2396 LZ4_FORCE_O2
LZ4_decompress_fast(const char * source,char * dest,int originalSize)2397 int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
2398 {
2399     DEBUGLOG(5, "LZ4_decompress_fast");
2400     return LZ4_decompress_unsafe_generic(
2401                 (const BYTE*)source, (BYTE*)dest, originalSize,
2402                 0, NULL, 0);
2403 }
2404 
2405 /*===== Instantiate a few more decoding cases, used more than once. =====*/
2406 
2407 LZ4_FORCE_O2 /* Exported, an obsolete API function. */
LZ4_decompress_safe_withPrefix64k(const char * source,char * dest,int compressedSize,int maxOutputSize)2408 int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
2409 {
2410     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
2411                                   decode_full_block, withPrefix64k,
2412                                   (BYTE*)dest - 64 KB, NULL, 0);
2413 }
2414 
2415 LZ4_FORCE_O2
LZ4_decompress_safe_partial_withPrefix64k(const char * source,char * dest,int compressedSize,int targetOutputSize,int dstCapacity)2416 static int LZ4_decompress_safe_partial_withPrefix64k(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity)
2417 {
2418     dstCapacity = MIN(targetOutputSize, dstCapacity);
2419     return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
2420                                   partial_decode, withPrefix64k,
2421                                   (BYTE*)dest - 64 KB, NULL, 0);
2422 }
2423 
2424 /* Another obsolete API function, paired with the previous one. */
LZ4_decompress_fast_withPrefix64k(const char * source,char * dest,int originalSize)2425 int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
2426 {
2427     return LZ4_decompress_unsafe_generic(
2428                 (const BYTE*)source, (BYTE*)dest, originalSize,
2429                 64 KB, NULL, 0);
2430 }
2431 
2432 LZ4_FORCE_O2
LZ4_decompress_safe_withSmallPrefix(const char * source,char * dest,int compressedSize,int maxOutputSize,size_t prefixSize)2433 static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize,
2434                                                size_t prefixSize)
2435 {
2436     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
2437                                   decode_full_block, noDict,
2438                                   (BYTE*)dest-prefixSize, NULL, 0);
2439 }
2440 
2441 LZ4_FORCE_O2
LZ4_decompress_safe_partial_withSmallPrefix(const char * source,char * dest,int compressedSize,int targetOutputSize,int dstCapacity,size_t prefixSize)2442 static int LZ4_decompress_safe_partial_withSmallPrefix(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity,
2443                                                size_t prefixSize)
2444 {
2445     dstCapacity = MIN(targetOutputSize, dstCapacity);
2446     return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
2447                                   partial_decode, noDict,
2448                                   (BYTE*)dest-prefixSize, NULL, 0);
2449 }
2450 
2451 LZ4_FORCE_O2
LZ4_decompress_safe_forceExtDict(const char * source,char * dest,int compressedSize,int maxOutputSize,const void * dictStart,size_t dictSize)2452 int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
2453                                      int compressedSize, int maxOutputSize,
2454                                      const void* dictStart, size_t dictSize)
2455 {
2456     DEBUGLOG(5, "LZ4_decompress_safe_forceExtDict");
2457     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
2458                                   decode_full_block, usingExtDict,
2459                                   (BYTE*)dest, (const BYTE*)dictStart, dictSize);
2460 }
2461 
2462 LZ4_FORCE_O2
LZ4_decompress_safe_partial_forceExtDict(const char * source,char * dest,int compressedSize,int targetOutputSize,int dstCapacity,const void * dictStart,size_t dictSize)2463 int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,
2464                                      int compressedSize, int targetOutputSize, int dstCapacity,
2465                                      const void* dictStart, size_t dictSize)
2466 {
2467     dstCapacity = MIN(targetOutputSize, dstCapacity);
2468     return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
2469                                   partial_decode, usingExtDict,
2470                                   (BYTE*)dest, (const BYTE*)dictStart, dictSize);
2471 }
2472 
2473 LZ4_FORCE_O2
LZ4_decompress_fast_extDict(const char * source,char * dest,int originalSize,const void * dictStart,size_t dictSize)2474 static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize,
2475                                        const void* dictStart, size_t dictSize)
2476 {
2477     return LZ4_decompress_unsafe_generic(
2478                 (const BYTE*)source, (BYTE*)dest, originalSize,
2479                 0, (const BYTE*)dictStart, dictSize);
2480 }
2481 
2482 /* The "double dictionary" mode, for use with e.g. ring buffers: the first part
2483  * of the dictionary is passed as prefix, and the second via dictStart + dictSize.
2484  * These routines are used only once, in LZ4_decompress_*_continue().
2485  */
2486 LZ4_FORCE_INLINE
LZ4_decompress_safe_doubleDict(const char * source,char * dest,int compressedSize,int maxOutputSize,size_t prefixSize,const void * dictStart,size_t dictSize)2487 int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compressedSize, int maxOutputSize,
2488                                    size_t prefixSize, const void* dictStart, size_t dictSize)
2489 {
2490     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
2491                                   decode_full_block, usingExtDict,
2492                                   (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize);
2493 }
2494 
2495 /*===== streaming decompression functions =====*/
2496 
2497 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_createStreamDecode(void)2498 LZ4_streamDecode_t* LZ4_createStreamDecode(void)
2499 {
2500     LZ4_STATIC_ASSERT(sizeof(LZ4_streamDecode_t) >= sizeof(LZ4_streamDecode_t_internal));
2501     return (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));
2502 }
2503 
LZ4_freeStreamDecode(LZ4_streamDecode_t * LZ4_stream)2504 int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
2505 {
2506     if (LZ4_stream == NULL) { return 0; }  /* support free on NULL */
2507     FREEMEM(LZ4_stream);
2508     return 0;
2509 }
2510 #endif
2511 
2512 /*! LZ4_setStreamDecode() :
2513  *  Use this function to instruct where to find the dictionary.
2514  *  This function is not necessary if previous data is still available where it was decoded.
2515  *  Loading a size of 0 is allowed (same effect as no dictionary).
2516  * @return : 1 if OK, 0 if error
2517  */
LZ4_setStreamDecode(LZ4_streamDecode_t * LZ4_streamDecode,const char * dictionary,int dictSize)2518 int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
2519 {
2520     LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
2521     lz4sd->prefixSize = (size_t)dictSize;
2522     if (dictSize) {
2523         assert(dictionary != NULL);
2524         lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
2525     } else {
2526         lz4sd->prefixEnd = (const BYTE*) dictionary;
2527     }
2528     lz4sd->externalDict = NULL;
2529     lz4sd->extDictSize  = 0;
2530     return 1;
2531 }
2532 
2533 /*! LZ4_decoderRingBufferSize() :
2534  *  when setting a ring buffer for streaming decompression (optional scenario),
2535  *  provides the minimum size of this ring buffer
2536  *  to be compatible with any source respecting maxBlockSize condition.
2537  *  Note : in a ring buffer scenario,
2538  *  blocks are presumed decompressed next to each other.
2539  *  When not enough space remains for next block (remainingSize < maxBlockSize),
2540  *  decoding resumes from beginning of ring buffer.
2541  * @return : minimum ring buffer size,
2542  *           or 0 if there is an error (invalid maxBlockSize).
2543  */
LZ4_decoderRingBufferSize(int maxBlockSize)2544 int LZ4_decoderRingBufferSize(int maxBlockSize)
2545 {
2546     if (maxBlockSize < 0) return 0;
2547     if (maxBlockSize > LZ4_MAX_INPUT_SIZE) return 0;
2548     if (maxBlockSize < 16) maxBlockSize = 16;
2549     return LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize);
2550 }
2551 
2552 /*
2553 *_continue() :
2554     These decoding functions allow decompression of multiple blocks in "streaming" mode.
2555     Previously decoded blocks must still be available at the memory position where they were decoded.
2556     If it's not possible, save the relevant part of decoded data into a safe buffer,
2557     and indicate where it stands using LZ4_setStreamDecode()
2558 */
2559 LZ4_FORCE_O2
LZ4_decompress_safe_continue(LZ4_streamDecode_t * LZ4_streamDecode,const char * source,char * dest,int compressedSize,int maxOutputSize)2560 int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
2561 {
2562     LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
2563     int result;
2564 
2565     if (lz4sd->prefixSize == 0) {
2566         /* The first call, no dictionary yet. */
2567         assert(lz4sd->extDictSize == 0);
2568         result = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);
2569         if (result <= 0) return result;
2570         lz4sd->prefixSize = (size_t)result;
2571         lz4sd->prefixEnd = (BYTE*)dest + result;
2572     } else if (lz4sd->prefixEnd == (BYTE*)dest) {
2573         /* They're rolling the current segment. */
2574         if (lz4sd->prefixSize >= 64 KB - 1)
2575             result = LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);
2576         else if (lz4sd->extDictSize == 0)
2577             result = LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize,
2578                                                          lz4sd->prefixSize);
2579         else
2580             result = LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize,
2581                                                     lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
2582         if (result <= 0) return result;
2583         lz4sd->prefixSize += (size_t)result;
2584         lz4sd->prefixEnd  += result;
2585     } else {
2586         /* The buffer wraps around, or they're switching to another buffer. */
2587         lz4sd->extDictSize = lz4sd->prefixSize;
2588         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
2589         result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize,
2590                                                   lz4sd->externalDict, lz4sd->extDictSize);
2591         if (result <= 0) return result;
2592         lz4sd->prefixSize = (size_t)result;
2593         lz4sd->prefixEnd  = (BYTE*)dest + result;
2594     }
2595 
2596     return result;
2597 }
2598 
2599 LZ4_FORCE_O2 int
LZ4_decompress_fast_continue(LZ4_streamDecode_t * LZ4_streamDecode,const char * source,char * dest,int originalSize)2600 LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode,
2601                         const char* source, char* dest, int originalSize)
2602 {
2603     LZ4_streamDecode_t_internal* const lz4sd =
2604         (assert(LZ4_streamDecode!=NULL), &LZ4_streamDecode->internal_donotuse);
2605     int result;
2606 
2607     DEBUGLOG(5, "LZ4_decompress_fast_continue (toDecodeSize=%i)", originalSize);
2608     assert(originalSize >= 0);
2609 
2610     if (lz4sd->prefixSize == 0) {
2611         DEBUGLOG(5, "first invocation : no prefix nor extDict");
2612         assert(lz4sd->extDictSize == 0);
2613         result = LZ4_decompress_fast(source, dest, originalSize);
2614         if (result <= 0) return result;
2615         lz4sd->prefixSize = (size_t)originalSize;
2616         lz4sd->prefixEnd = (BYTE*)dest + originalSize;
2617     } else if (lz4sd->prefixEnd == (BYTE*)dest) {
2618         DEBUGLOG(5, "continue using existing prefix");
2619         result = LZ4_decompress_unsafe_generic(
2620                         (const BYTE*)source, (BYTE*)dest, originalSize,
2621                         lz4sd->prefixSize,
2622                         lz4sd->externalDict, lz4sd->extDictSize);
2623         if (result <= 0) return result;
2624         lz4sd->prefixSize += (size_t)originalSize;
2625         lz4sd->prefixEnd  += originalSize;
2626     } else {
2627         DEBUGLOG(5, "prefix becomes extDict");
2628         lz4sd->extDictSize = lz4sd->prefixSize;
2629         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
2630         result = LZ4_decompress_fast_extDict(source, dest, originalSize,
2631                                              lz4sd->externalDict, lz4sd->extDictSize);
2632         if (result <= 0) return result;
2633         lz4sd->prefixSize = (size_t)originalSize;
2634         lz4sd->prefixEnd  = (BYTE*)dest + originalSize;
2635     }
2636 
2637     return result;
2638 }
2639 
2640 
2641 /*
2642 Advanced decoding functions :
2643 *_usingDict() :
2644     These decoding functions work the same as "_continue" ones,
2645     the dictionary must be explicitly provided within parameters
2646 */
2647 
LZ4_decompress_safe_usingDict(const char * source,char * dest,int compressedSize,int maxOutputSize,const char * dictStart,int dictSize)2648 int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
2649 {
2650     if (dictSize==0)
2651         return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);
2652     if (dictStart+dictSize == dest) {
2653         if (dictSize >= 64 KB - 1) {
2654             return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);
2655         }
2656         assert(dictSize >= 0);
2657         return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize);
2658     }
2659     assert(dictSize >= 0);
2660     return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize);
2661 }
2662 
LZ4_decompress_safe_partial_usingDict(const char * source,char * dest,int compressedSize,int targetOutputSize,int dstCapacity,const char * dictStart,int dictSize)2663 int LZ4_decompress_safe_partial_usingDict(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, const char* dictStart, int dictSize)
2664 {
2665     if (dictSize==0)
2666         return LZ4_decompress_safe_partial(source, dest, compressedSize, targetOutputSize, dstCapacity);
2667     if (dictStart+dictSize == dest) {
2668         if (dictSize >= 64 KB - 1) {
2669             return LZ4_decompress_safe_partial_withPrefix64k(source, dest, compressedSize, targetOutputSize, dstCapacity);
2670         }
2671         assert(dictSize >= 0);
2672         return LZ4_decompress_safe_partial_withSmallPrefix(source, dest, compressedSize, targetOutputSize, dstCapacity, (size_t)dictSize);
2673     }
2674     assert(dictSize >= 0);
2675     return LZ4_decompress_safe_partial_forceExtDict(source, dest, compressedSize, targetOutputSize, dstCapacity, dictStart, (size_t)dictSize);
2676 }
2677 
LZ4_decompress_fast_usingDict(const char * source,char * dest,int originalSize,const char * dictStart,int dictSize)2678 int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
2679 {
2680     if (dictSize==0 || dictStart+dictSize == dest)
2681         return LZ4_decompress_unsafe_generic(
2682                         (const BYTE*)source, (BYTE*)dest, originalSize,
2683                         (size_t)dictSize, NULL, 0);
2684     assert(dictSize >= 0);
2685     return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize);
2686 }
2687 
2688 
2689 /*=*************************************************
2690 *  Obsolete Functions
2691 ***************************************************/
2692 /* obsolete compression functions */
LZ4_compress_limitedOutput(const char * source,char * dest,int inputSize,int maxOutputSize)2693 int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize)
2694 {
2695     return LZ4_compress_default(source, dest, inputSize, maxOutputSize);
2696 }
LZ4_compress(const char * src,char * dest,int srcSize)2697 int LZ4_compress(const char* src, char* dest, int srcSize)
2698 {
2699     return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize));
2700 }
LZ4_compress_limitedOutput_withState(void * state,const char * src,char * dst,int srcSize,int dstSize)2701 int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize)
2702 {
2703     return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1);
2704 }
LZ4_compress_withState(void * state,const char * src,char * dst,int srcSize)2705 int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize)
2706 {
2707     return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1);
2708 }
LZ4_compress_limitedOutput_continue(LZ4_stream_t * LZ4_stream,const char * src,char * dst,int srcSize,int dstCapacity)2709 int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int dstCapacity)
2710 {
2711     return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, dstCapacity, 1);
2712 }
LZ4_compress_continue(LZ4_stream_t * LZ4_stream,const char * source,char * dest,int inputSize)2713 int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize)
2714 {
2715     return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1);
2716 }
2717 
2718 /*
2719 These decompression functions are deprecated and should no longer be used.
2720 They are only provided here for compatibility with older user programs.
2721 - LZ4_uncompress is totally equivalent to LZ4_decompress_fast
2722 - LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
2723 */
LZ4_uncompress(const char * source,char * dest,int outputSize)2724 int LZ4_uncompress (const char* source, char* dest, int outputSize)
2725 {
2726     return LZ4_decompress_fast(source, dest, outputSize);
2727 }
LZ4_uncompress_unknownOutputSize(const char * source,char * dest,int isize,int maxOutputSize)2728 int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize)
2729 {
2730     return LZ4_decompress_safe(source, dest, isize, maxOutputSize);
2731 }
2732 
2733 /* Obsolete Streaming functions */
2734 
LZ4_sizeofStreamState(void)2735 int LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); }
2736 
LZ4_resetStreamState(void * state,char * inputBuffer)2737 int LZ4_resetStreamState(void* state, char* inputBuffer)
2738 {
2739     (void)inputBuffer;
2740     LZ4_resetStream((LZ4_stream_t*)state);
2741     return 0;
2742 }
2743 
2744 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_create(char * inputBuffer)2745 void* LZ4_create (char* inputBuffer)
2746 {
2747     (void)inputBuffer;
2748     return LZ4_createStream();
2749 }
2750 #endif
2751 
LZ4_slideInputBuffer(void * state)2752 char* LZ4_slideInputBuffer (void* state)
2753 {
2754     /* avoid const char * -> char * conversion warning */
2755     return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary;
2756 }
2757 
2758 #endif   /* LZ4_COMMONDEFS_ONLY */
2759 
2760 #endif /* LV_USE_LZ4_INTERNAL */
2761 
2762