decompressor: Re-enable tinf bounds checks, CRC32, and length validation
diff --git a/bootstrap b/bootstrap
index 79c82e48..90965858 100755
--- a/bootstrap
+++ b/bootstrap
@@ -97,7 +97,7 @@ if ! test -f version; then
tinf \
57ffa1f1d5e3dde19011b2127bd26d01689b694b
mkdir -p decompressor/tinf
- cp tinf/src/tinf.h tinf/src/tinflate.c tinf/src/tinfgzip.c decompressor/tinf/
+ cp tinf/src/tinf.h tinf/src/tinflate.c tinf/src/tinfgzip.c tinf/src/crc32.c decompressor/tinf/
patch -p0 < decompressor/tinf.patch
rm -f decompressor/tinf/*.orig
diff --git a/decompressor/main.c b/decompressor/main.c
index 94e8214d..4bea9300 100644
--- a/decompressor/main.c
+++ b/decompressor/main.c
@@ -5,9 +5,20 @@
noreturn void entry(uint8_t *compressed_stage2, size_t stage2_size, uint8_t boot_drive, int pxe) {
// The decompressor should decompress compressed_stage2 to address 0xf000.
+ // The output buffer extends up to 0x70000 where the decompressor itself lives.
uint8_t *dest = (uint8_t *)0xf000;
+ unsigned int destLen = 0x70000 - 0xf000;
- tinf_gzip_uncompress(dest, compressed_stage2, stage2_size);
+ if (tinf_gzip_uncompress(dest, &destLen, compressed_stage2, stage2_size) != 0) {
+ const char *msg = "Limine decomp error";
+ volatile uint16_t *vga = (volatile uint16_t *)0xB8000;
+ for (size_t i = 0; msg[i]; i++) {
+ vga[i] = 0x4F00 | (uint8_t)msg[i];
+ }
+ for (;;) {
+ asm volatile ("cli; hlt");
+ }
+ }
asm volatile (
"movl $0xf000, %%esp\n\t"
diff --git a/decompressor/tinf.patch b/decompressor/tinf.patch
index 3f87e8e8..d955918e 100644
--- a/decompressor/tinf.patch
+++ b/decompressor/tinf.patch
@@ -1,97 +1,6 @@
-diff '--color=auto' -urN tinf-clean/tinf.h decompressor/tinf/tinf.h
---- tinf-clean/tinf.h 2023-06-06 00:57:04.683481827 +0200
-+++ decompressor/tinf/tinf.h 2023-06-06 00:56:14.485629430 +0200
-@@ -59,7 +59,9 @@
- *
- * @deprecated No longer required, may be removed in a future version.
- */
-+/*
- void TINFCC tinf_init(void);
-+*/
-
- /**
- * Decompress `sourceLen` bytes of deflate data from `source` to `dest`.
-@@ -76,7 +78,7 @@
- * @param sourceLen size of compressed data
- * @return `TINF_OK` on success, error code on error
- */
--int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
-+int TINFCC tinf_uncompress(void *dest,
- const void *source, unsigned int sourceLen);
-
- /**
-@@ -94,7 +96,7 @@
- * @param sourceLen size of compressed data
- * @return `TINF_OK` on success, error code on error
- */
--int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
-+int TINFCC tinf_gzip_uncompress(void *dest,
- const void *source, unsigned int sourceLen);
-
- /**
-@@ -112,8 +114,10 @@
- * @param sourceLen size of compressed data
- * @return `TINF_OK` on success, error code on error
- */
-+/*
- int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
- const void *source, unsigned int sourceLen);
-+*/
-
- /**
- * Compute Adler-32 checksum of `length` bytes starting at `data`.
-@@ -122,7 +126,9 @@
- * @param length size of data
- * @return Adler-32 checksum
- */
-+/*
- unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
-+*/
-
- /**
- * Compute CRC32 checksum of `length` bytes starting at `data`.
-@@ -131,7 +137,9 @@
- * @param length size of data
- * @return CRC32 checksum
- */
-+/*
- unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
-+*/
-
- #ifdef __cplusplus
- } /* extern "C" */
-diff '--color=auto' -urN tinf-clean/tinfgzip.c decompressor/tinf/tinfgzip.c
---- tinf-clean/tinfgzip.c 2023-06-06 00:57:16.983772372 +0200
-+++ decompressor/tinf/tinfgzip.c 2023-06-06 01:09:39.119942087 +0200
-@@ -39,6 +39,8 @@
- | ((unsigned int) p[1] << 8);
- }
-
-+/*
-+
- static unsigned int read_le32(const unsigned char *p)
- {
- return ((unsigned int) p[0])
-@@ -47,13 +49,17 @@
- | ((unsigned int) p[3] << 24);
- }
-
--int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
-+*/
-+
-+int tinf_gzip_uncompress(void *dest,
- const void *source, unsigned int sourceLen)
- {
- const unsigned char *src = (const unsigned char *) source;
- unsigned char *dst = (unsigned char *) dest;
- const unsigned char *start;
-+/*
- unsigned int dlen, crc32;
-+*/
- int res;
- unsigned char flg;
-
-@@ -101,7 +107,7 @@
+--- tinf-clean/tinfgzip.c 2026-03-31 13:52:17.360241095 +0200
++++ decompressor/tinf/tinfgzip.c 2026-03-31 14:00:21.885490126 +0200
+@@ -101,7 +101,7 @@
/* Skip file name if present */
if (flg & FNAME) {
do {
@@ -100,7 +9,7 @@ diff '--color=auto' -urN tinf-clean/tinfgzip.c decompressor/tinf/tinfgzip.c
return TINF_DATA_ERROR;
}
} while (*start++);
-@@ -110,7 +116,7 @@
+@@ -110,7 +110,7 @@
/* Skip file comment if present */
if (flg & FCOMMENT) {
do {
@@ -109,62 +18,17 @@ diff '--color=auto' -urN tinf-clean/tinfgzip.c decompressor/tinf/tinfgzip.c
return TINF_DATA_ERROR;
}
} while (*start++);
-@@ -118,6 +124,7 @@
-
- /* Check header crc if present */
+@@ -120,7 +120,7 @@
if (flg & FHCRC) {
-+/*
unsigned int hcrc;
- if (start - src > sourceLen - 2) {
-@@ -129,10 +136,12 @@
- if (hcrc != (tinf_crc32(src, start - src) & 0x0000FFFF)) {
+- if (start - src > sourceLen - 2) {
++ if ((unsigned int)(start - src) > sourceLen - 2) {
return TINF_DATA_ERROR;
}
-+*/
-
- start += 2;
- }
-
-+#if 0
- /* -- Get decompressed length -- */
-
- dlen = read_le32(&src[sourceLen - 4]);
-@@ -144,6 +153,7 @@
- /* -- Get CRC32 checksum of original data -- */
-
- crc32 = read_le32(&src[sourceLen - 8]);
-+#endif
-
- /* -- Decompress data -- */
-
-@@ -151,13 +161,14 @@
- return TINF_DATA_ERROR;
- }
-
-- res = tinf_uncompress(dst, destLen, start,
-+ res = tinf_uncompress(dst, start,
- (src + sourceLen) - start - 8);
-
- if (res != TINF_OK) {
- return TINF_DATA_ERROR;
- }
-
-+#if 0
- if (*destLen != dlen) {
- return TINF_DATA_ERROR;
- }
-@@ -167,6 +178,7 @@
- if (crc32 != tinf_crc32(dst, dlen)) {
- return TINF_DATA_ERROR;
- }
-+#endif
- return TINF_OK;
- }
-diff '--color=auto' -urN tinf-clean/tinflate.c decompressor/tinf/tinflate.c
---- tinf-clean/tinflate.c 2023-06-06 00:57:10.746958386 +0200
-+++ decompressor/tinf/tinflate.c 2023-06-06 01:12:19.629674294 +0200
+--- tinf-clean/tinflate.c 2026-03-31 13:52:17.360241095 +0200
++++ decompressor/tinf/tinflate.c 2026-03-31 14:03:04.603900859 +0200
@@ -25,7 +25,7 @@
#include "tinf.h"
@@ -174,91 +38,17 @@ diff '--color=auto' -urN tinf-clean/tinflate.c decompressor/tinf/tinflate.c
#include <limits.h>
#if defined(UINT_MAX) && (UINT_MAX) < 0xFFFFFFFFUL
-@@ -49,7 +49,9 @@
-
- unsigned char *dest_start;
- unsigned char *dest;
-+/*
- unsigned char *dest_end;
-+*/
-
- struct tinf_tree ltree; /* Literal/length tree */
- struct tinf_tree dtree; /* Distance tree */
-@@ -425,9 +427,12 @@
- }
-
- if (sym < 256) {
-+/*
- if (d->dest == d->dest_end) {
- return TINF_BUF_ERROR;
- }
-+*/
-+
- *d->dest++ = sym;
- }
- else {
-@@ -465,9 +470,11 @@
- return TINF_DATA_ERROR;
- }
-
-+/*
- if (d->dest_end - d->dest < length) {
- return TINF_BUF_ERROR;
- }
-+*/
-
- /* Copy match */
- for (i = 0; i < length; ++i) {
-@@ -501,6 +508,7 @@
+@@ -501,11 +501,11 @@
d->source += 4;
-+/*
- if (d->source_end - d->source < length) {
+- if (d->source_end - d->source < length) {
++ if ((unsigned int)(d->source_end - d->source) < length) {
return TINF_DATA_ERROR;
}
-@@ -508,6 +516,7 @@
- if (d->dest_end - d->dest < length) {
- return TINF_BUF_ERROR;
- }
-+*/
-
- /* Copy block */
- while (length--) {
-@@ -548,13 +557,15 @@
- /* -- Public functions -- */
- /* Initialize global (static) data */
-+/*
- void tinf_init(void)
- {
- return;
- }
-+*/
-
- /* Inflate stream from source to dest */
--int tinf_uncompress(void *dest, unsigned int *destLen,
-+int tinf_uncompress(void *dest,
- const void *source, unsigned int sourceLen)
- {
- struct tinf_data d;
-@@ -569,7 +580,9 @@
-
- d.dest = (unsigned char *) dest;
- d.dest_start = d.dest;
-+/*
- d.dest_end = d.dest + *destLen;
-+*/
-
- do {
- unsigned int btype;
-@@ -610,7 +623,9 @@
- return TINF_DATA_ERROR;
+- if (d->dest_end - d->dest < length) {
++ if ((unsigned int)(d->dest_end - d->dest) < length) {
+ return TINF_BUF_ERROR;
}
-+/*
- *destLen = d.dest - d.dest_start;
-+*/
-
- return TINF_OK;
- }
