VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Boot/Windows/BootCommon.h2
-rw-r--r--src/Boot/Windows/BootSector.asm4
-rw-r--r--src/Boot/Windows/Decompressor.c66
3 files changed, 54 insertions, 18 deletions
diff --git a/src/Boot/Windows/BootCommon.h b/src/Boot/Windows/BootCommon.h
index 75346da7..50031cfe 100644
--- a/src/Boot/Windows/BootCommon.h
+++ b/src/Boot/Windows/BootCommon.h
@@ -13,7 +13,7 @@
#include "BootDefs.h"
// The user will be advised to upgrade the rescue disk if upgrading from the following or any previous version
-#define TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION 0x010a
+#define TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION 0x010d
#define TC_BOOT_LOADER_AREA_SIZE (TC_BOOT_LOADER_AREA_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS)
diff --git a/src/Boot/Windows/BootSector.asm b/src/Boot/Windows/BootSector.asm
index 74e8381b..1daaadac 100644
--- a/src/Boot/Windows/BootSector.asm
+++ b/src/Boot/Windows/BootSector.asm
@@ -134,6 +134,8 @@ checksum_ok:
push dx
; Decompress boot loader
+ mov cx, word ptr [start + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET]
+ push cx ; Compressed data size
push TC_BOOT_LOADER_COMPRESSED_BUFFER_OFFSET + TC_GZIP_HEADER_SIZE ; Compressed data
push TC_MAX_BOOT_LOADER_DECOMPRESSED_SIZE ; Output buffer size
push TC_BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE + TC_COM_EXECUTABLE_OFFSET ; Output buffer
@@ -145,7 +147,7 @@ checksum_ok:
retf
decompressor_ret:
- add sp, 6
+ add sp, 8
pop dx
; Restore boot sector segment
diff --git a/src/Boot/Windows/Decompressor.c b/src/Boot/Windows/Decompressor.c
index efdbed91..c3883352 100644
--- a/src/Boot/Windows/Decompressor.c
+++ b/src/Boot/Windows/Decompressor.c
@@ -47,6 +47,7 @@ struct state {
/* input state */
unsigned char *in; /* input buffer */
+ unsigned int inlen; /* available input at in */
unsigned int incnt; /* bytes read so far */
int bitbuf; /* bit buffer */
int bitcnt; /* number of bits in bit buffer */
@@ -80,6 +81,9 @@ local int stored(struct state *s)
/* discard leftover bits from current byte (assumes s->bitcnt < 8) */
s->bitbuf = 0;
s->bitcnt = 0;
+
+ if (s->incnt + 4 > s->inlen)
+ return 2; /* not enough input */
/* get length and check against its one's complement */
len = s->in[s->incnt++];
@@ -87,6 +91,9 @@ local int stored(struct state *s)
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2; /* didn't match complement! */
+
+ if (s->incnt + len > s->inlen)
+ return 2; /* not enough input */
/* copy len bytes from in to out */
if (s->out != NIL) {
@@ -110,6 +117,8 @@ struct huffman {
short *symbol; /* canonically ordered symbols */
};
+/* use slow version of decode to save code space */
+#define SLOW
#ifdef SLOW
local int decode(struct state *s, struct huffman *h)
@@ -363,28 +372,39 @@ local int dynamic(struct state *s)
int len; /* last length to repeat */
symbol = decode(s, &lencode);
+ if (symbol < 0) return symbol;
if (symbol < 16) /* length in 0..15 */
lengths[index++] = symbol;
else { /* repeat instruction */
len = 0; /* assume repeating zeros */
- if (symbol == 16) { /* repeat last length 3..6 times */
- if (index == 0) return -5; /* no last length! */
- len = lengths[index - 1]; /* last length */
- symbol = 3 + bits(s, 2);
- }
- else if (symbol == 17) /* repeat zero 3..10 times */
- symbol = 3 + bits(s, 3);
- else /* == 18, repeat zero 11..138 times */
- symbol = 11 + bits(s, 7);
- if (index + symbol > nlen + ndist)
+ switch(symbol)
+ {
+ case 16: { /* repeat last length 3..6 times */
+ if (index == 0) return -5; /* no last length! */
+ len = lengths[index - 1]; /* last length */
+ symbol = 3 + bits(s, 2);
+ break;
+ }
+ case 17: /* repeat zero 3..10 times */
+ symbol = 3 + bits(s, 3);
+ break;
+ default: /* == 18, repeat zero 11..138 times */
+ symbol = 11 + bits(s, 7);
+ break;
+ }
+ if ((index + symbol > nlen + ndist))
return -6; /* too many lengths! */
while (symbol--) /* repeat last or zero symbol times */
lengths[index++] = len;
}
}
+ /* check for end-of-block code -- there better be one! */
+ if (lengths[256] == 0)
+ return -9;
+
/* build huffman table for literal/length codes */
- err = construct(&lencode, lengths, nlen);
+ err = construct(&lencode, lengths, nlen);
if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
return -7; /* only allow incomplete codes if just one code */
@@ -404,7 +424,8 @@ void _acrtused () { }
int far main (
unsigned char *dest, /* pointer to destination pointer */
unsigned int destlen, /* amount of output space */
- unsigned char *source) /* pointer to source data pointer */
+ unsigned char *source, /* pointer to source data pointer */
+ unsigned int sourcelen)
{
struct state s; /* input/output state */
int last, type; /* block information */
@@ -417,6 +438,7 @@ int far main (
/* initialize input state */
s.in = source;
+ s.inlen = sourcelen;
s.incnt = 0;
s.bitbuf = 0;
s.bitcnt = 0;
@@ -425,10 +447,22 @@ int far main (
do {
last = bits(&s, 1); /* one if last block */
type = bits(&s, 2); /* block type 0..3 */
- err = type == 0 ? stored(&s) :
- (type == 1 ? fixed(&s) :
- (type == 2 ? dynamic(&s) :
- -1)); /* type == 3, invalid */
+ switch(type)
+ {
+ case 0:
+ err = stored(&s);
+ break;
+ case 1:
+ err = fixed(&s);
+ break;
+ case 2:
+ err = dynamic(&s);
+ break;
+ default:
+ err = -1; /* type == 3, invalid */
+ break;
+ }
+
if (err != 0) break; /* return with error */
} while (!last);