178556Sobrien
278556Sobrien/* A test program written to test robustness to decompression of
378556Sobrien   corrupted data.  Usage is
478556Sobrien       unzcrash filename
578556Sobrien   and the program will read the specified file, compress it (in memory),
678556Sobrien   and then repeatedly decompress it, each time with a different bit of
778556Sobrien   the compressed data inverted, so as to test all possible one-bit errors.
878556Sobrien   This should not cause any invalid memory accesses.  If it does,
978556Sobrien   I want to know about it!
1078556Sobrien
11167974Sdelphij   PS.  As you can see from the above description, the process is
1278556Sobrien   incredibly slow.  A file of size eg 5KB will cause it to run for
1378556Sobrien   many hours.
1478556Sobrien*/
1578556Sobrien
16167974Sdelphij/* ------------------------------------------------------------------
17167974Sdelphij   This file is part of bzip2/libbzip2, a program and library for
18167974Sdelphij   lossless, block-sorting data compression.
19167974Sdelphij
20351007Sdelphij   bzip2/libbzip2 version 1.0.8 of 13 July 2019
21351007Sdelphij   Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
22167974Sdelphij
23167974Sdelphij   Please read the WARNING, DISCLAIMER and PATENTS sections in the
24167974Sdelphij   README file.
25167974Sdelphij
26167974Sdelphij   This program is released under the terms of the license contained
27167974Sdelphij   in the file LICENSE.
28167974Sdelphij   ------------------------------------------------------------------ */
29167974Sdelphij
30167974Sdelphij
3178556Sobrien#include <stdio.h>
3278556Sobrien#include <assert.h>
3378556Sobrien#include "bzlib.h"
3478556Sobrien
3578556Sobrien#define M_BLOCK 1000000
3678556Sobrien
3778556Sobrientypedef unsigned char uchar;
3878556Sobrien
3978556Sobrien#define M_BLOCK_OUT (M_BLOCK + 1000000)
4078556Sobrienuchar inbuf[M_BLOCK];
4178556Sobrienuchar outbuf[M_BLOCK_OUT];
4278556Sobrienuchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
4378556Sobrien
4478556Sobrienint nIn, nOut, nZ;
4578556Sobrien
4678556Sobrienstatic char *bzerrorstrings[] = {
4778556Sobrien       "OK"
4878556Sobrien      ,"SEQUENCE_ERROR"
4978556Sobrien      ,"PARAM_ERROR"
5078556Sobrien      ,"MEM_ERROR"
5178556Sobrien      ,"DATA_ERROR"
5278556Sobrien      ,"DATA_ERROR_MAGIC"
5378556Sobrien      ,"IO_ERROR"
5478556Sobrien      ,"UNEXPECTED_EOF"
5578556Sobrien      ,"OUTBUFF_FULL"
5678556Sobrien      ,"???"   /* for future */
5778556Sobrien      ,"???"   /* for future */
5878556Sobrien      ,"???"   /* for future */
5978556Sobrien      ,"???"   /* for future */
6078556Sobrien      ,"???"   /* for future */
6178556Sobrien      ,"???"   /* for future */
6278556Sobrien};
6378556Sobrien
6478556Sobrienvoid flip_bit ( int bit )
6578556Sobrien{
6678556Sobrien   int byteno = bit / 8;
6778556Sobrien   int bitno  = bit % 8;
6878556Sobrien   uchar mask = 1 << bitno;
6978556Sobrien   //fprintf ( stderr, "(byte %d  bit %d  mask %d)",
7078556Sobrien   //          byteno, bitno, (int)mask );
7178556Sobrien   zbuf[byteno] ^= mask;
7278556Sobrien}
7378556Sobrien
7478556Sobrienint main ( int argc, char** argv )
7578556Sobrien{
7678556Sobrien   FILE* f;
7778556Sobrien   int   r;
7878556Sobrien   int   bit;
7978556Sobrien   int   i;
8078556Sobrien
8178556Sobrien   if (argc != 2) {
8278556Sobrien      fprintf ( stderr, "usage: unzcrash filename\n" );
8378556Sobrien      return 1;
8478556Sobrien   }
8578556Sobrien
8678556Sobrien   f = fopen ( argv[1], "r" );
8778556Sobrien   if (!f) {
8878556Sobrien      fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] );
8978556Sobrien      return 1;
9078556Sobrien   }
9178556Sobrien
9278556Sobrien   nIn = fread ( inbuf, 1, M_BLOCK, f );
9378556Sobrien   fprintf ( stderr, "%d bytes read\n", nIn );
9478556Sobrien
9578556Sobrien   nZ = M_BLOCK;
9678556Sobrien   r = BZ2_bzBuffToBuffCompress (
9778556Sobrien         zbuf, &nZ, inbuf, nIn, 9, 0, 30 );
9878556Sobrien
9978556Sobrien   assert (r == BZ_OK);
10078556Sobrien   fprintf ( stderr, "%d after compression\n", nZ );
10178556Sobrien
10278556Sobrien   for (bit = 0; bit < nZ*8; bit++) {
10378556Sobrien      fprintf ( stderr, "bit %d  ", bit );
10478556Sobrien      flip_bit ( bit );
10578556Sobrien      nOut = M_BLOCK_OUT;
10678556Sobrien      r = BZ2_bzBuffToBuffDecompress (
10778556Sobrien            outbuf, &nOut, zbuf, nZ, 0, 0 );
10878556Sobrien      fprintf ( stderr, " %d  %s ", r, bzerrorstrings[-r] );
10978556Sobrien
11078556Sobrien      if (r != BZ_OK) {
11178556Sobrien         fprintf ( stderr, "\n" );
11278556Sobrien      } else {
11378556Sobrien         if (nOut != nIn) {
11478556Sobrien           fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut );
11578556Sobrien           return 1;
11678556Sobrien         } else {
11778556Sobrien           for (i = 0; i < nOut; i++)
11878556Sobrien             if (inbuf[i] != outbuf[i]) {
11978556Sobrien                fprintf(stderr, "mismatch at %d\n", i );
12078556Sobrien                return 1;
12178556Sobrien           }
12278556Sobrien           if (i == nOut) fprintf(stderr, "really ok!\n" );
12378556Sobrien         }
12478556Sobrien      }
12578556Sobrien
12678556Sobrien      flip_bit ( bit );
12778556Sobrien   }
12878556Sobrien
12978556Sobrien#if 0
13078556Sobrien   assert (nOut == nIn);
13178556Sobrien   for (i = 0; i < nOut; i++) {
13278556Sobrien     if (inbuf[i] != outbuf[i]) {
13378556Sobrien        fprintf ( stderr, "difference at %d !\n", i );
13478556Sobrien        return 1;
13578556Sobrien     }
13678556Sobrien   }
13778556Sobrien#endif
13878556Sobrien
13978556Sobrien   fprintf ( stderr, "all ok\n" );
14078556Sobrien   return 0;
14178556Sobrien}
142