decompress_generic: Refactor variable length fields

Make a helper function to read variable lengths for literals and
match length.
This commit is contained in:
Dave Watson 2019-01-24 13:07:57 -08:00
parent c3f0753d30
commit 4da336062e

View File

@ -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;