]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Check DMS input buffer under/overflow. Improved encrypted DMS support, some DMS files...
authorToni Wilen <twilen@winuae.net>
Sun, 5 Nov 2023 15:26:37 +0000 (17:26 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 5 Nov 2023 15:26:37 +0000 (17:26 +0200)
archivers/dms/pfile.cpp
archivers/dms/u_deep.cpp
archivers/dms/u_deep.h
archivers/dms/u_heavy.cpp
archivers/dms/u_heavy.h
archivers/dms/u_medium.cpp
archivers/dms/u_medium.h
archivers/dms/u_quick.cpp
archivers/dms/u_quick.h
archivers/dms/u_rle.cpp
archivers/dms/u_rle.h

index 1cf18a7cdd3cff447b3bc166f9ed94cff0ef33ee..56ef99548cc3c6caff7ee539fb97cffe56dd8a05 100644 (file)
@@ -422,7 +422,7 @@ static USHORT Process_Track(struct zfile *fi, struct zfile *fo, UCHAR *b1, UCHAR
 
 
 
-static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen, UCHAR cmode, UCHAR flags){
+static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen1, USHORT pklen2, USHORT unpklen, UCHAR cmode, UCHAR flags){
        switch (cmode){
                case 0:
                        /*   No Compression   */
@@ -430,24 +430,24 @@ static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen
                        break;
                case 1:
                        /*   Simple Compression   */
-                       if (Unpack_RLE(b1,b2,unpklen)) return ERR_BADDECR;
+                       if (Unpack_RLE(b1,b2, pklen1,unpklen)) return ERR_BADDECR;
                        break;
                case 2:
                        /*   Quick Compression   */
-                       if (Unpack_QUICK(b1,b2,pklen2)) return ERR_BADDECR;
-                       if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
+                       if (Unpack_QUICK(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
+                       if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
                        memcpy(b2,b1,(size_t)unpklen);
                        break;
                case 3:
                        /*   Medium Compression   */
-                       if (Unpack_MEDIUM(b1,b2,pklen2)) return ERR_BADDECR;
-                       if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
+                       if (Unpack_MEDIUM(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
+                       if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
                        memcpy(b2,b1,(size_t)unpklen);
                        break;
                case 4:
                        /*   Deep Compression   */
-                       if (Unpack_DEEP(b1,b2,pklen2)) return ERR_BADDECR;
-                       if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
+                       if (Unpack_DEEP(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
+                       if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
                        memcpy(b2,b1,(size_t)unpklen);
                        break;
                case 5:
@@ -455,15 +455,15 @@ static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen
                        /*   Heavy Compression   */
                        if (cmode==5) {
                                /*   Heavy 1   */
-                               if (Unpack_HEAVY(b1,b2,flags & 7,pklen2)) return ERR_BADDECR;
+                               if (Unpack_HEAVY(b1,b2,flags & 7,pklen1,pklen2)) return ERR_BADDECR;
                        } else {
                                /*   Heavy 2   */
-                               if (Unpack_HEAVY(b1,b2,flags | 8,pklen2)) return ERR_BADDECR;
+                               if (Unpack_HEAVY(b1,b2,flags | 8,pklen1,pklen2)) return ERR_BADDECR;
                        }
                        if (flags & 4) {
                                memset(b1,0,unpklen);
                                /*  Unpack with RLE only if this flag is set  */
-                               if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
+                               if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
                                memcpy(b2,b1,(size_t)unpklen);
                        }
                        break;
@@ -494,13 +494,14 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
        static USHORT pass;
        int maybeencrypted;
        int pwrounds;
-       UCHAR *tmp;
-       USHORT prevpass = 0;
+       int firstpass = -1;
+       UCHAR *tmp, *tmp_dms_text;
+       USHORT prevpass = pass;
 
        if (passfound) {
                if (number != 80)
                        dms_decrypt(b1, pklen1, b1);
-               r = Unpack_Track_2(b1, b2, pklen2, unpklen, cmode, flags);
+               r = Unpack_Track_2(b1, b2, pklen1, pklen2, unpklen, cmode, flags);
                if (r == NO_PROBLEM) {
                        if (usum1 == dms_Calc_CheckSum(b2,(ULONG)unpklen))
                                return NO_PROBLEM;
@@ -513,19 +514,27 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
        passretries--;
        pwrounds = 0;
        maybeencrypted = 0;
-       tmp = (unsigned char*)malloc (pklen1);
+       tmp = xmalloc(UCHAR, pklen1);
+       tmp_dms_text = xmalloc(UCHAR, 0x3fc8);
        memcpy (tmp, b1, pklen1);
        memset(b2, 0, unpklen);
+       memcpy(tmp_dms_text, dms_text, 0x3fc8);
        for (;;) {
-               r = Unpack_Track_2(b1, b2, pklen2, unpklen, cmode, flags);
+               r = Unpack_Track_2(b1, b2, pklen1, pklen2, unpklen, cmode, flags);
                if (r == NO_PROBLEM) {
                        if (usum1 == dms_Calc_CheckSum(b2,(ULONG)unpklen)) {
                                passfound = maybeencrypted;
                                if (passfound)
                                        write_log (_T("DMS: decryption key = 0x%04X\n"), prevpass);
-                               err = NO_PROBLEM;
-                               pass = prevpass;
-                               break;
+                               // if bootblock does not have "DOS", check other keys too
+                               if (number > 0 || firstpass == pass || (b2[0] == 'D' && b2[1] == 'O' && b2[2] == 'S')) {
+                                       err = NO_PROBLEM;
+                                       pass = prevpass;
+                                       break;
+                               }
+                               if (firstpass < 0) {
+                                       firstpass = pass;
+                               }
                        }
                }
                if (number == 80 || !enc) {
@@ -538,13 +547,20 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
                pass++;
                dms_decrypt(b1, pklen1, tmp);
                pwrounds++;
-               if (pwrounds == 65536) {
-                       err = ERR_CSUM;
-                       passfound = 0;
-                       break;
+               if (pwrounds >= 65536) {
+                       if (firstpass < 0) {
+                               err = ERR_CSUM;
+                               passfound = 0;
+                               break;
+                       }
+                       pass = firstpass;
+                       PWDCRC = pass;
+                       dms_decrypt(b1, pklen1, tmp);
                }
+               memcpy(dms_text, tmp_dms_text, 0x3fc8);
        }
-       free (tmp);
+       xfree(tmp_dms_text);
+       xfree(tmp);
        return err;
 }
 
index 95245f89bb57fe352496e5ab562a3678eca87f5e..3079612718f654032f6e7854526b101f58a412fb 100644 (file)
 #include "u_deep.h"
 #include "getbits.h"
 
-
-INLINE USHORT DecodeChar(void);
-INLINE USHORT DecodePosition(void);
-INLINE void update(USHORT c);
+static USHORT DecodeChar(void);
+static USHORT DecodePosition(void);
+static void update(USHORT c);
 static void reconst(void);
 
-
 USHORT dms_deep_text_loc;
 int dms_init_deep_tabs=1;
 
-
-
 #define DBITMASK 0x3fff   /*  uses 16Kb dictionary  */
 
 #define F       60  /* lookahead buffer size */
@@ -37,7 +33,6 @@ int dms_init_deep_tabs=1;
 #define R       (T - 1)         /* position of root */
 #define MAX_FREQ    0x8000      /* updates tree when the */
 
-
 static USHORT freq[T + 1]; /* frequency table */
 
 static USHORT prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
@@ -46,8 +41,6 @@ static USHORT prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
 
 static USHORT son[T];   /* pointers to child nodes (son[], son[] + 1) */
 
-
-
 static void Init_DEEP_Tabs(void){
        USHORT i, j;
 
@@ -69,9 +62,7 @@ static void Init_DEEP_Tabs(void){
        dms_init_deep_tabs = 0;
 }
 
-
-
-USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT origsize){
+USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
        USHORT i, j, c;
        UCHAR *outend;
 
@@ -93,12 +84,13 @@ USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT origsize){
 
        dms_deep_text_loc = (USHORT)((dms_deep_text_loc+60) & DBITMASK);
 
-       return 0;
-}
-
+       in += pklen1;
+       if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;
 
+       return 1;
+}
 
-INLINE USHORT DecodeChar(void){
+static USHORT DecodeChar(void){
        USHORT c;
 
        c = son[R];
@@ -115,9 +107,7 @@ INLINE USHORT DecodeChar(void){
        return c;
 }
 
-
-
-INLINE USHORT DecodePosition(void){
+static USHORT DecodePosition(void){
        USHORT i, j, c;
 
        i = GETBITS(8);  DROPBITS(8);
@@ -128,8 +118,6 @@ INLINE USHORT DecodePosition(void){
        return (USHORT) (c | i) ;
 }
 
-
-
 /* reconstruction of tree */
 
 static void reconst(void){
@@ -167,11 +155,9 @@ static void reconst(void){
        }
 }
 
-
-
 /* increment frequency of given code by one, and update tree */
 
-INLINE void update(USHORT c){
+static void update(USHORT c){
        USHORT i, j, k, l;
 
        if (freq[R] == MAX_FREQ) {
@@ -203,5 +189,3 @@ INLINE void update(USHORT c){
                }
        } while ((c = prnt[c]) != 0); /* repeat up to root */
 }
-
-
index ae542ee9a2f5b70e3b93449d3878e76e04b30dfc..21164054186ac62e9421626323cf14781b8fb511 100644 (file)
@@ -1,6 +1,6 @@
 
 
-USHORT Unpack_DEEP(UCHAR *, UCHAR *, USHORT);
+USHORT Unpack_DEEP(UCHAR *, UCHAR *, USHORT, USHORT);
 
 extern int dms_init_deep_tabs;
 extern USHORT dms_deep_text_loc;
index 6ce06c49c3616c1f490e819789b8e6b2da25fdd1..9ebae455a160c01d7900ed5813b61f740c0c5f14 100644 (file)
@@ -9,13 +9,11 @@
 *
 */
 
-
 #include "cdata.h"
 #include "u_heavy.h"
 #include "getbits.h"
 #include "maketbl.h"
 
-
 #define NC 510
 #define NPT 20
 #define N1 510
@@ -27,15 +25,12 @@ static USHORT c_table[4096], pt_table[256];
 USHORT dms_lastlen, dms_np;
 USHORT dms_heavy_text_loc;
 
-
 static USHORT read_tree_c(void);
 static USHORT read_tree_p(void);
-INLINE USHORT decode_c(void);
-INLINE USHORT decode_p(void);
-
+static USHORT decode_c(void);
+static USHORT decode_p(void);
 
-
-USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
+USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT pklen1, USHORT origsize){
        USHORT j, i, c, bitmask;
        UCHAR *outend;
 
@@ -69,12 +64,13 @@ USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
                }
        }
 
-       return 0;
-}
-
+       in += pklen1;
+       if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;
 
+       return 1;
+}
 
-INLINE USHORT decode_c(void){
+static USHORT decode_c(void){
        USHORT i, j, m;
 
        j = c_table[GETBITS(12)];
@@ -94,9 +90,7 @@ INLINE USHORT decode_c(void){
        return j;
 }
 
-
-
-INLINE USHORT decode_p(void){
+static USHORT decode_p(void){
        USHORT i, j, m;
 
        j = pt_table[GETBITS(8)];
@@ -126,8 +120,6 @@ INLINE USHORT decode_p(void){
 
 }
 
-
-
 static USHORT read_tree_c(void){
        USHORT i,n;
 
@@ -149,8 +141,6 @@ static USHORT read_tree_c(void){
        return 0;
 }
 
-
-
 static USHORT read_tree_p(void){
        USHORT i,n;
 
index 80f1be83975a94ef2b020a3383442d7d94969040..243ee1cbfc438ee27d56e9af05c36c372e95fe1a 100644 (file)
@@ -1,6 +1,6 @@
 
 
-USHORT Unpack_HEAVY(UCHAR *, UCHAR *, UCHAR, USHORT);
+USHORT Unpack_HEAVY(UCHAR *, UCHAR *, UCHAR, USHORT, USHORT);
 
 extern USHORT dms_heavy_text_loc;
 
index e0a771c17254d4155c922ae9b554b901c1b9c16b..8cefd20a5f454fca912623ac2f3626446cfe1bdf 100644 (file)
@@ -7,7 +7,6 @@
  *
  */
 
-
 #include <string.h>
 
 #include "cdata.h"
 #include "getbits.h"
 #include "tables.h"
 
-
 #define MBITMASK 0x3fff
 
-
 USHORT dms_medium_text_loc;
 
-
-
-USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT origsize){
+USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
        USHORT i, j, c;
        UCHAR u, *outend;
 
-
        initbitbuf(in);
 
        outend = out+origsize;
@@ -52,7 +46,8 @@ USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT origsize){
        }
        dms_medium_text_loc = (USHORT)((dms_medium_text_loc+66) & MBITMASK);
 
-       return 0;
-}
-
+       in += pklen1;
+       if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;
 
+       return 1;
+}
index 18c0ce8590ed660b33e9496626d42442ddee5ea0..9e8aac1e371ed0ada724c063e17a7ea047ef5116 100644 (file)
@@ -1,5 +1,5 @@
 
-USHORT Unpack_MEDIUM(UCHAR *, UCHAR *, USHORT);
+USHORT Unpack_MEDIUM(UCHAR *, UCHAR *, USHORT, USHORT);
 
 extern USHORT dms_medium_text_loc;
 
index 1cc08cccab7d49a0136dbffcfdf10a04b5962ee4..e8e782bc9b57f110b85e307146d619fe35c60ae1 100644 (file)
@@ -6,21 +6,17 @@
  *
  */
 
-
 #include <string.h>
 
 #include "cdata.h"
 #include "u_quick.h"
 #include "getbits.h"
 
-
 #define QBITMASK 0xff
 
-
 USHORT dms_quick_text_loc;
 
-
-USHORT Unpack_QUICK(UCHAR *in, UCHAR *out, USHORT origsize){
+USHORT Unpack_QUICK(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
        USHORT i, j;
        UCHAR *outend;
 
@@ -42,6 +38,8 @@ USHORT Unpack_QUICK(UCHAR *in, UCHAR *out, USHORT origsize){
        }
        dms_quick_text_loc = (USHORT)((dms_quick_text_loc+5) & QBITMASK);
 
-       return 0;
-}
+       in += pklen1;
+       if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;
 
+       return 1;
+}
index 2cfdf4afcb054ef1c6ece3f1532c8bb990498265..7397e0d61b33160bd489f23a54c3cfe768899190 100644 (file)
@@ -1,5 +1,5 @@
 
-USHORT Unpack_QUICK(UCHAR *, UCHAR *, USHORT);
+USHORT Unpack_QUICK(UCHAR *, UCHAR *, USHORT, USHORT);
 
 extern USHORT dms_quick_text_loc;
 
index ff46c561e15f5ae1f6bfc7d0efe7179a716dceb0..ac53f5559b25909ef210be70ede6b67083e37f27 100644 (file)
 #include "cdata.h"
 #include "u_rle.h"
 
-
-
-USHORT Unpack_RLE(UCHAR *in, UCHAR *out, USHORT origsize){
+USHORT Unpack_RLE(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
        USHORT n;
        UCHAR a,b, *outend;
+       UCHAR *inp = in + pklen1;
 
        outend = out+origsize;
        while (out<outend){
@@ -26,6 +25,7 @@ USHORT Unpack_RLE(UCHAR *in, UCHAR *out, USHORT origsize){
                        *out++ = a;
                else {
                        a = *in++;
+                       if (in > inp) return 1;
                        if (b == 0xff) {
                                n = *in++;
                                n = (USHORT)((n<<8) + *in++);
@@ -36,7 +36,6 @@ USHORT Unpack_RLE(UCHAR *in, UCHAR *out, USHORT origsize){
                        out += n;
                }
        }
+
        return 0;
 }
-
-
index 0cf24938ad51a68e4df7e0777f332f8b3317c792..2aa83054585e9f00923ffb917a555982d4a0328a 100644 (file)
@@ -1,3 +1,3 @@
 
-USHORT Unpack_RLE(UCHAR *, UCHAR *, USHORT);
+USHORT Unpack_RLE(UCHAR *, UCHAR *, USHORT, USHORT);