summaryrefslogtreecommitdiffstats
path: root/lib/lz4.c
diff options
context:
space:
mode:
authorDave Watson <davejwatson@fb.com>2019-01-24 21:07:57 (GMT)
committerDave Watson <davejwatson@fb.com>2019-02-08 21:42:42 (GMT)
commit4da336062e5b295c0a54bb3683cdc6ca9ba23ca3 (patch)
tree183176f25695c512aaf37a419af8145cd51676cc /lib/lz4.c
parentc3f0753d30b600fee46c1a64a2600b1f5fc7e93b (diff)
downloadlz4-4da336062e5b295c0a54bb3683cdc6ca9ba23ca3.zip
lz4-4da336062e5b295c0a54bb3683cdc6ca9ba23ca3.tar.gz
lz4-4da336062e5b295c0a54bb3683cdc6ca9ba23ca3.tar.bz2
decompress_generic: Refactor variable length fields
Make a helper function to read variable lengths for literals and match length.
Diffstat (limited to 'lib/lz4.c')
-rw-r--r--lib/lz4.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/lib/lz4.c b/lib/lz4.c
index 53eff2e..4a063eb 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -1434,6 +1434,35 @@ typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
#undef MIN
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
+/* Read the variable-length literal or match length.
+ *
+ * ip - pointer to use as input.
+ * lencheck - end ip. Return an error if ip advances >= lencheck.
+ * loop_check - check ip >= lencheck in body of loop. Returns loop_error if so.
+ * initial_check - check ip >= lencheck before start of loop. Returns initial_error if so.
+ * error (output) - error code. Should be set to 0 before call.
+ */
+typedef enum { loop_error = -2, initial_error = -1, ok = 0} variable_length_error;
+LZ4_FORCE_INLINE unsigned read_variable_length(const BYTE**ip, const BYTE* lencheck, int loop_check, int initial_check, variable_length_error* error) {
+ unsigned length = 0;
+ unsigned s;
+ if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
+ *error = initial_error;
+ return length;
+ }
+ do {
+ s = **ip;
+ (*ip)++;
+ length += s;
+ if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
+ *error = loop_error;
+ return length;
+ }
+ } while (s==255);
+
+ return length;
+}
+
/*! LZ4_decompress_generic() :
* This generic decompression function covers all use cases.
* It shall be instantiated several times, using different sets of directives.
@@ -1536,12 +1565,9 @@ LZ4_decompress_generic(
/* decode literal length */
if (length == RUN_MASK) {
- unsigned s;
- if (unlikely(endOnInput ? ip >= iend-RUN_MASK : 0)) goto _output_error; /* overflow detection */
- do {
- s = *ip++;
- length += s;
- } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) );
+ variable_length_error error = ok;
+ length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);
+ if (error == initial_error) goto _output_error;
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */
}
@@ -1588,12 +1614,9 @@ LZ4_decompress_generic(
} /* note : when partialDecoding, there is no guarantee that at least 4 bytes remain available in output buffer */
if (length == ML_MASK) {
- unsigned s;
- do {
- s = *ip++;
- if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
- length += s;
- } while (s==255);
+ variable_length_error error = ok;
+ length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);
+ if (error != ok) goto _output_error;
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */
}
length += MINMATCH;