1
2/* A test program written to test robustness to decompression of
3   corrupted data.  Usage is
4       unzcrash filename
5   and the program will read the specified file, compress it (in memory),
6   and then repeatedly decompress it, each time with a different bit of
7   the compressed data inverted, so as to test all possible one-bit errors.
8   This should not cause any invalid memory accesses.  If it does,
9   I want to know about it!
10
11   PS.  As you can see from the above description, the process is
12   incredibly slow.  A file of size eg 5KB will cause it to run for
13   many hours.
14*/
15
16/* ------------------------------------------------------------------
17   This file is part of bzip2/libbzip2, a program and library for
18   lossless, block-sorting data compression.
19
20   bzip2/libbzip2 version 1.0.6 of 6 September 2010
21   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
22
23   Please read the WARNING, DISCLAIMER and PATENTS sections in the
24   README file.
25
26   This program is released under the terms of the license contained
27   in the file LICENSE.
28   ------------------------------------------------------------------ */
29
30
31#include <stdio.h>
32#include <assert.h>
33#include "bzlib.h"
34
35#define M_BLOCK 1000000
36
37typedef unsigned char uchar;
38
39#define M_BLOCK_OUT (M_BLOCK + 1000000)
40uchar inbuf[M_BLOCK];
41uchar outbuf[M_BLOCK_OUT];
42uchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
43
44int nIn, nOut, nZ;
45
46static char *bzerrorstrings[] = {
47       "OK"
48      ,"SEQUENCE_ERROR"
49      ,"PARAM_ERROR"
50      ,"MEM_ERROR"
51      ,"DATA_ERROR"
52      ,"DATA_ERROR_MAGIC"
53      ,"IO_ERROR"
54      ,"UNEXPECTED_EOF"
55      ,"OUTBUFF_FULL"
56      ,"???"   /* for future */
57      ,"???"   /* for future */
58      ,"???"   /* for future */
59      ,"???"   /* for future */
60      ,"???"   /* for future */
61      ,"???"   /* for future */
62};
63
64void flip_bit ( int bit )
65{
66   int byteno = bit / 8;
67   int bitno  = bit % 8;
68   uchar mask = 1 << bitno;
69   //fprintf ( stderr, "(byte %d  bit %d  mask %d)",
70   //          byteno, bitno, (int)mask );
71   zbuf[byteno] ^= mask;
72}
73
74int main ( int argc, char** argv )
75{
76   FILE* f;
77   int   r;
78   int   bit;
79   int   i;
80
81   if (argc != 2) {
82      fprintf ( stderr, "usage: unzcrash filename\n" );
83      return 1;
84   }
85
86   f = fopen ( argv[1], "r" );
87   if (!f) {
88      fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] );
89      return 1;
90   }
91
92   nIn = fread ( inbuf, 1, M_BLOCK, f );
93   fprintf ( stderr, "%d bytes read\n", nIn );
94
95   nZ = M_BLOCK;
96   r = BZ2_bzBuffToBuffCompress (
97         zbuf, &nZ, inbuf, nIn, 9, 0, 30 );
98
99   assert (r == BZ_OK);
100   fprintf ( stderr, "%d after compression\n", nZ );
101
102   for (bit = 0; bit < nZ*8; bit++) {
103      fprintf ( stderr, "bit %d  ", bit );
104      flip_bit ( bit );
105      nOut = M_BLOCK_OUT;
106      r = BZ2_bzBuffToBuffDecompress (
107            outbuf, &nOut, zbuf, nZ, 0, 0 );
108      fprintf ( stderr, " %d  %s ", r, bzerrorstrings[-r] );
109
110      if (r != BZ_OK) {
111         fprintf ( stderr, "\n" );
112      } else {
113         if (nOut != nIn) {
114           fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut );
115           return 1;
116         } else {
117           for (i = 0; i < nOut; i++)
118             if (inbuf[i] != outbuf[i]) {
119                fprintf(stderr, "mismatch at %d\n", i );
120                return 1;
121           }
122           if (i == nOut) fprintf(stderr, "really ok!\n" );
123         }
124      }
125
126      flip_bit ( bit );
127   }
128
129#if 0
130   assert (nOut == nIn);
131   for (i = 0; i < nOut; i++) {
132     if (inbuf[i] != outbuf[i]) {
133        fprintf ( stderr, "difference at %d !\n", i );
134        return 1;
135     }
136   }
137#endif
138
139   fprintf ( stderr, "all ok\n" );
140   return 0;
141}
142