:: commit b0569fed9520fe9cf3beae22b5c7231bf89ecc85

Mintsuki <mintsuki@protonmail.com> — 2026-03-31 12:08

parents: ca6d469dc2

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;
- }
tab: 248 wrap: offon