unzcrash.c revision 167974
1214571Sdim
2214571Sdim/* A test program written to test robustness to decompression of
3214571Sdim   corrupted data.  Usage is
4214571Sdim       unzcrash filename
5214571Sdim   and the program will read the specified file, compress it (in memory),
6214571Sdim   and then repeatedly decompress it, each time with a different bit of
7214571Sdim   the compressed data inverted, so as to test all possible one-bit errors.
8214571Sdim   This should not cause any invalid memory accesses.  If it does,
9214571Sdim   I want to know about it!
10214571Sdim
11214571Sdim   PS.  As you can see from the above description, the process is
12214571Sdim   incredibly slow.  A file of size eg 5KB will cause it to run for
13214571Sdim   many hours.
14214571Sdim*/
15214571Sdim
16214571Sdim/* ------------------------------------------------------------------
17214571Sdim   This file is part of bzip2/libbzip2, a program and library for
18214571Sdim   lossless, block-sorting data compression.
19214571Sdim
20214571Sdim   bzip2/libbzip2 version 1.0.4 of 20 December 2006
21214571Sdim   Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
22214571Sdim
23214571Sdim   Please read the WARNING, DISCLAIMER and PATENTS sections in the
24214571Sdim   README file.
25214571Sdim
26214571Sdim   This program is released under the terms of the license contained
27214571Sdim   in the file LICENSE.
28214571Sdim   ------------------------------------------------------------------ */
29214571Sdim
30214571Sdim
31214571Sdim#include <stdio.h>
32214571Sdim#include <assert.h>
33214571Sdim#include "bzlib.h"
34214571Sdim
35214571Sdim#define M_BLOCK 1000000
36214571Sdim
37214571Sdimtypedef unsigned char uchar;
38214571Sdim
39214571Sdim#define M_BLOCK_OUT (M_BLOCK + 1000000)
40214571Sdimuchar inbuf[M_BLOCK];
41214571Sdimuchar outbuf[M_BLOCK_OUT];
42214571Sdimuchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
43214571Sdim
44214571Sdimint nIn, nOut, nZ;
45214571Sdim
46214571Sdimstatic char *bzerrorstrings[] = {
47214571Sdim       "OK"
48214571Sdim      ,"SEQUENCE_ERROR"
49214571Sdim      ,"PARAM_ERROR"
50214571Sdim      ,"MEM_ERROR"
51214571Sdim      ,"DATA_ERROR"
52214571Sdim      ,"DATA_ERROR_MAGIC"
53214571Sdim      ,"IO_ERROR"
54214571Sdim      ,"UNEXPECTED_EOF"
55214571Sdim      ,"OUTBUFF_FULL"
56214571Sdim      ,"???"   /* for future */
57214571Sdim      ,"???"   /* for future */
58214571Sdim      ,"???"   /* for future */
59214571Sdim      ,"???"   /* for future */
60214571Sdim      ,"???"   /* for future */
61214571Sdim      ,"???"   /* for future */
62214571Sdim};
63214571Sdim
64214571Sdimvoid flip_bit ( int bit )
65214571Sdim{
66214571Sdim   int byteno = bit / 8;
67214571Sdim   int bitno  = bit % 8;
68214571Sdim   uchar mask = 1 << bitno;
69214571Sdim   //fprintf ( stderr, "(byte %d  bit %d  mask %d)",
70214571Sdim   //          byteno, bitno, (int)mask );
71214571Sdim   zbuf[byteno] ^= mask;
72214571Sdim}
73214571Sdim
74214571Sdimint main ( int argc, char** argv )
75214571Sdim{
76214571Sdim   FILE* f;
77214571Sdim   int   r;
78214571Sdim   int   bit;
79214571Sdim   int   i;
80214571Sdim
81214571Sdim   if (argc != 2) {
82214571Sdim      fprintf ( stderr, "usage: unzcrash filename\n" );
83214571Sdim      return 1;
84214571Sdim   }
85214571Sdim
86214571Sdim   f = fopen ( argv[1], "r" );
87214571Sdim   if (!f) {
88214571Sdim      fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] );
89214571Sdim      return 1;
90214571Sdim   }
91214571Sdim
92214571Sdim   nIn = fread ( inbuf, 1, M_BLOCK, f );
93214571Sdim   fprintf ( stderr, "%d bytes read\n", nIn );
94214571Sdim
95214571Sdim   nZ = M_BLOCK;
96214571Sdim   r = BZ2_bzBuffToBuffCompress (
97214571Sdim         zbuf, &nZ, inbuf, nIn, 9, 0, 30 );
98214571Sdim
99214571Sdim   assert (r == BZ_OK);
100214571Sdim   fprintf ( stderr, "%d after compression\n", nZ );
101214571Sdim
102214571Sdim   for (bit = 0; bit < nZ*8; bit++) {
103214571Sdim      fprintf ( stderr, "bit %d  ", bit );
104214571Sdim      flip_bit ( bit );
105214571Sdim      nOut = M_BLOCK_OUT;
106214571Sdim      r = BZ2_bzBuffToBuffDecompress (
107214571Sdim            outbuf, &nOut, zbuf, nZ, 0, 0 );
108214571Sdim      fprintf ( stderr, " %d  %s ", r, bzerrorstrings[-r] );
109214571Sdim
110214571Sdim      if (r != BZ_OK) {
111214571Sdim         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