// SPDX-License-Identifiler: WTFPL #include #include #include #include "bzcomp.h" int32_t bz_uncompress(uint8_t *dst, uint8_t *src, int32_t dlen, int32_t slen) { uint32_t i, c, n, spos, dpos, xpos, xlen; if (dst == NULL) dlen = 1U << 31; for (spos = dpos = 0; spos < slen && dpos < dlen; spos += n, dpos += xlen) { c = src[spos] & 0xf0; if (c == 0x00 || c == 0x10) { xlen = (src[spos] & 0x1f) + 1; n = xlen + 1; if (slen - spos < n) goto error; if (dst != NULL) { if (dlen - dpos < xlen) goto error; memcpy(dst + dpos, src + spos + 1, xlen); } } else { n = (c == 0xf0) ? 3 : 2; if (slen - spos < n) goto error; if (c == 0xf0) { xlen = (((src[spos] & 0x0f) << 4) | ((src[spos + 1] & 0xf0) >> 4)) + 1; xpos = ((src[spos + 1] & 0x0f) << 8) | src[spos + 2]; } else { xlen = ((src[spos] & 0xf0) >> 4) + 1; xpos = ((src[spos] & 0x0f) << 8) | src[spos + 1]; } if (!xpos || xpos > dpos) goto error; if (dst != NULL) { if (dlen - dpos < xlen) goto error; /* do not use memcpy() and memmove() */ for (i = 0; i < xlen; i++) dst[dpos + i] = dst[dpos - xpos + i]; } } } return (int32_t)dpos; error: return -1; }