|
18 | 18 | */
|
19 | 19 |
|
20 | 20 | #include "libbz3.h"
|
21 |
| - |
22 | 21 | #include <stdlib.h>
|
23 | 22 | #include <string.h>
|
24 |
| - |
25 | 23 | #include "libsais.h"
|
26 | 24 |
|
| 25 | +#if defined(__GNUC__) || defined(__clang__) |
| 26 | + #define LIKELY(x) __builtin_expect(!!(x), 1) |
| 27 | + #define UNLIKELY(x) __builtin_expect(!!(x), 0) |
| 28 | +#else |
| 29 | + #define LIKELY(x) (x) |
| 30 | + #define UNLIKELY(x) (x) |
| 31 | +#endif |
| 32 | + |
27 | 33 | /* CRC32 implementation. Since CRC32 generally takes less than 1% of the runtime on real-world data (e.g. the
|
28 | 34 | Silesia corpus), I decided against using hardware CRC32. This implementation is simple, fast, fool-proof and
|
29 | 35 | good enough to be used with bzip3. */
|
@@ -201,21 +207,23 @@ static s32 lzp_decode_block(const u8 * RESTRICT in, const u8 * in_end, s32 * RES
|
201 | 207 |
|
202 | 208 | while (in < in_end && out < out_end) {
|
203 | 209 | u32 idx = (ctx >> 15 ^ ctx ^ ctx >> 3) & ((s32)(1 << LZP_DICTIONARY) - 1);
|
204 |
| - s32 val = lut[idx]; |
| 210 | + s32 val = lut[idx]; // SAFETY: guaranteed to be in-bounds by & mask. |
205 | 211 | lut[idx] = (s32)(out - outs);
|
206 | 212 | if (*in == MATCH && val > 0) {
|
207 | 213 | in++;
|
| 214 | + // SAFETY: 'in' is advanced here, but it may have been at last index in the case of untrusted bad data. |
| 215 | + if (UNLIKELY(in == in_end)) return -1; |
208 | 216 | if (*in != 255) {
|
209 | 217 | s32 len = LZP_MIN_MATCH;
|
210 | 218 | while (1) {
|
211 |
| - if (in == in_end) return -1; |
| 219 | + if (UNLIKELY(in == in_end)) return -1; |
212 | 220 | len += *in;
|
213 | 221 | if (*in++ != 254) break;
|
214 | 222 | }
|
215 | 223 |
|
216 | 224 | const u8 * ref = outs + val;
|
217 | 225 | const u8 * oe = out + len;
|
218 |
| - if (oe > out_end) oe = out_end; |
| 226 | + if (UNLIKELY(oe > out_end)) oe = out_end; |
219 | 227 |
|
220 | 228 | while (out < oe) *out++ = *ref++;
|
221 | 229 |
|
|
0 commit comments