xref: /sqlite-3.40.0/ext/session/changesetfuzz.c (revision 067b92ba)
1 /*
2 ** 2018-11-01
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 ** This file contains code to implement the "changesetfuzz" command
13 ** line utility for fuzzing changeset blobs without corrupting them.
14 */
15 
16 
17 /************************************************************************
18 ** USAGE:
19 **
20 ** This program may be invoked in two ways:
21 **
22 **   changesetfuzz INPUT
23 **   changesetfuzz INPUT SEED N
24 **
25 ** Argument INPUT must be the name of a file containing a binary changeset.
26 ** In the first form above, this program outputs a human-readable version
27 ** of the same changeset. This is chiefly for debugging.
28 **
29 ** As well as changesets, this program can also dump and fuzz patchsets.
30 ** The term "changeset" is used for both patchsets and changesets from this
31 ** point on.
32 **
33 ** In the second form, arguments SEED and N must both be integers. In this
34 ** case, this program writes N binary changesets to disk. Each output
35 ** changeset is a slightly modified - "fuzzed" - version of the input.
36 ** The output changesets are written to files name "INPUT-$n", where $n is
37 ** an integer between 0 and N-1, inclusive. Output changesets are always
38 ** well-formed. Parameter SEED is used to seed the PRNG - any two
39 ** invocations of this program with the same SEED and input changeset create
40 ** the same N output changesets.
41 **
42 ** The ways in which an input changeset may be fuzzed are as follows:
43 **
44 **   1. Any two values within the changeset may be exchanged.
45 **
46 **   2. Any TEXT, BLOB, INTEGER or REAL value within the changeset
47 **      may have a single bit of its content flipped.
48 **
49 **   3. Any value within a changeset may be replaced by a pseudo-randomly
50 **      generated value.
51 **
52 ** The above operations never set a PRIMARY KEY column to NULL. Nor do they
53 ** set any value to "undefined", or replace any "undefined" value with
54 ** another. Any such operation risks producing a changeset that is not
55 ** well-formed.
56 **
57 **   4. A single change may be duplicated.
58 **
59 **   5. A single change may be removed, so long as this does not mean that
60 **      there are zero changes following a table-header within the changeset.
61 **
62 **   6. A single change may have its type (INSERT, DELETE, UPDATE) changed.
63 **      If an INSERT is changed to a DELETE (or vice versa), the type is
64 **      simply changed - no other modifications are required. If an INSERT
65 **      or DELETE is changed to an UPDATE, then the single record is duplicated
66 **      (as both the old.* and new.* records of the new UPDATE change). If an
67 **      UPDATE is changed to a DELETE or INSERT, the new.* record is discarded
68 **      and any "undefined" fields replaced with pseudo-randomly generated
69 **      values.
70 **
71 **   7. An UPDATE change that modifies N table columns may be modified so
72 **      that it updates N-1 columns, so long as (N>1).
73 **
74 **   8. The "indirect" flag may be toggled for any change.
75 **
76 ** Entire group of changes may also be operated on:
77 **
78 **   9. Duplicate an existing group.
79 **
80 **  10. Remove an existing group.
81 **
82 **  11. The positions of two groups may be exchanged.
83 **
84 ** There are also schema changes:
85 **
86 **  12. A non-PK column may be added to a table. In this case a NULL
87 **      value is appended to all records.
88 **
89 **  13. A PK column may be added to a table. In this case a non-NULL
90 **      value is appended to all INSERT, DELETE and UPDATE old.* records.
91 **      An "undefined" is appended to new.* UPDATE records.
92 **
93 **  14. A column may be removed from a table, provided that it is not the
94 **      only PRIMARY KEY column in the table. In this case the corresponding
95 **      field is removed from all records. In cases where this leaves an UPDATE
96 **      with no non-PK, non-undefined fields, the entire change is removed.
97 */
98 
99 #include "sqlite3.h"
100 #include <stdio.h>
101 #include <stdlib.h>
102 #include <string.h>
103 #include <assert.h>
104 #include <ctype.h>
105 
106 #define FUZZ_VALUE_SUB       1    /* Replace one value with a copy of another */
107 #define FUZZ_VALUE_MOD       2    /* Modify content by 1 bit */
108 #define FUZZ_VALUE_RND       3    /* Replace with pseudo-random value */
109 
110 #define FUZZ_CHANGE_DUP      4    /* Duplicate an existing change */
111 #define FUZZ_CHANGE_DEL      5    /* Completely remove one change */
112 #define FUZZ_CHANGE_TYPE     6    /* Change the type of one change */
113 #define FUZZ_CHANGE_FIELD    7    /* Change an UPDATE to modify fewer columns */
114 #define FUZZ_CHANGE_INDIRECT 8    /* Toggle the "indirect" flag of a change */
115 
116 #define FUZZ_GROUP_DUP       9    /* Duplicate a change group */
117 #define FUZZ_GROUP_DEL      10    /* Delete an entire change group */
118 #define FUZZ_GROUP_SWAP     11    /* Exchange the position of two groups */
119 
120 #define FUZZ_COLUMN_ADD     12     /* Add column to table definition */
121 #define FUZZ_COLUMN_ADDPK   13     /* Add PK column to table definition */
122 #define FUZZ_COLUMN_DEL     14     /* Remove column from table definition */
123 
124 
125 
126 typedef unsigned char u8;
127 typedef sqlite3_uint64 u64;
128 typedef sqlite3_int64 i64;
129 typedef unsigned int u32;
130 
131 /*
132 ** Show a usage message on stderr then quit.
133 */
134 static void usage(const char *argv0){
135   fprintf(stderr, "Usage: %s FILENAME ?SEED N?\n", argv0);
136   exit(1);
137 }
138 
139 /*
140 ** Read the content of a disk file into an in-memory buffer
141 */
142 static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
143   FILE *f;
144   sqlite3_int64 sz;
145   void *pBuf;
146   f = fopen(zFilename, "rb");
147   if( f==0 ){
148     fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
149     exit(1);
150   }
151   fseek(f, 0, SEEK_END);
152   sz = ftell(f);
153   rewind(f);
154   pBuf = sqlite3_malloc64( sz ? sz : 1 );
155   if( pBuf==0 ){
156     fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
157             (int)sz, zFilename);
158     exit(1);
159   }
160   if( sz>0 ){
161     if( fread(pBuf, (size_t)sz, 1, f)!=1 ){
162       fprintf(stderr, "cannot read all %d bytes of \"%s\"\n",
163               (int)sz, zFilename);
164       exit(1);
165     }
166     fclose(f);
167   }
168   *pSz = (int)sz;
169   *ppBuf = pBuf;
170 }
171 
172 /*
173 ** Write the contents of buffer pBuf, size nBuf bytes, into file zFilename
174 ** on disk. zFilename, if it already exists, is clobbered.
175 */
176 static void fuzzWriteFile(const char *zFilename, void *pBuf, int nBuf){
177   FILE *f;
178   f = fopen(zFilename, "wb");
179   if( f==0 ){
180     fprintf(stderr, "cannot open \"%s\" for writing\n", zFilename);
181     exit(1);
182   }
183   if( fwrite(pBuf, nBuf, 1, f)!=1 ){
184     fprintf(stderr, "cannot write to \"%s\"\n", zFilename);
185     exit(1);
186   }
187   fclose(f);
188 }
189 
190 static int fuzzCorrupt(){
191   return SQLITE_CORRUPT;
192 }
193 
194 /*************************************************************************
195 ** The following block is a copy of the implementation of SQLite function
196 ** sqlite3_randomness. This version has two important differences:
197 **
198 **   1. It always uses the same seed. So the sequence of random data output
199 **      is the same for every run of the program.
200 **
201 **   2. It is not threadsafe.
202 */
203 static struct sqlite3PrngType {
204   unsigned char i, j;             /* State variables */
205   unsigned char s[256];           /* State variables */
206 } sqlite3Prng = {
207     0xAF, 0x28,
208   {
209     0x71, 0xF5, 0xB4, 0x6E, 0x80, 0xAB, 0x1D, 0xB8,
210     0xFB, 0xB7, 0x49, 0xBF, 0xFF, 0x72, 0x2D, 0x14,
211     0x79, 0x09, 0xE3, 0x78, 0x76, 0xB0, 0x2C, 0x0A,
212     0x8E, 0x23, 0xEE, 0xDF, 0xE0, 0x9A, 0x2F, 0x67,
213     0xE1, 0xBE, 0x0E, 0xA7, 0x08, 0x97, 0xEB, 0x77,
214     0x78, 0xBA, 0x9D, 0xCA, 0x49, 0x4C, 0x60, 0x9A,
215     0xF6, 0xBD, 0xDA, 0x7F, 0xBC, 0x48, 0x58, 0x52,
216     0xE5, 0xCD, 0x83, 0x72, 0x23, 0x52, 0xFF, 0x6D,
217     0xEF, 0x0F, 0x82, 0x29, 0xA0, 0x83, 0x3F, 0x7D,
218     0xA4, 0x88, 0x31, 0xE7, 0x88, 0x92, 0x3B, 0x9B,
219     0x3B, 0x2C, 0xC2, 0x4C, 0x71, 0xA2, 0xB0, 0xEA,
220     0x36, 0xD0, 0x00, 0xF1, 0xD3, 0x39, 0x17, 0x5D,
221     0x2A, 0x7A, 0xE4, 0xAD, 0xE1, 0x64, 0xCE, 0x0F,
222     0x9C, 0xD9, 0xF5, 0xED, 0xB0, 0x22, 0x5E, 0x62,
223     0x97, 0x02, 0xA3, 0x8C, 0x67, 0x80, 0xFC, 0x88,
224     0x14, 0x0B, 0x15, 0x10, 0x0F, 0xC7, 0x40, 0xD4,
225     0xF1, 0xF9, 0x0E, 0x1A, 0xCE, 0xB9, 0x1E, 0xA1,
226     0x72, 0x8E, 0xD7, 0x78, 0x39, 0xCD, 0xF4, 0x5D,
227     0x2A, 0x59, 0x26, 0x34, 0xF2, 0x73, 0x0B, 0xA0,
228     0x02, 0x51, 0x2C, 0x03, 0xA3, 0xA7, 0x43, 0x13,
229     0xE8, 0x98, 0x2B, 0xD2, 0x53, 0xF8, 0xEE, 0x91,
230     0x7D, 0xE7, 0xE3, 0xDA, 0xD5, 0xBB, 0xC0, 0x92,
231     0x9D, 0x98, 0x01, 0x2C, 0xF9, 0xB9, 0xA0, 0xEB,
232     0xCF, 0x32, 0xFA, 0x01, 0x49, 0xA5, 0x1D, 0x9A,
233     0x76, 0x86, 0x3F, 0x40, 0xD4, 0x89, 0x8F, 0x9C,
234     0xE2, 0xE3, 0x11, 0x31, 0x37, 0xB2, 0x49, 0x28,
235     0x35, 0xC0, 0x99, 0xB6, 0xD0, 0xBC, 0x66, 0x35,
236     0xF7, 0x83, 0x5B, 0xD7, 0x37, 0x1A, 0x2B, 0x18,
237     0xA6, 0xFF, 0x8D, 0x7C, 0x81, 0xA8, 0xFC, 0x9E,
238     0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC,
239     0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90,
240     0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7
241   }
242 };
243 
244 /*
245 ** Generate and return single random byte
246 */
247 static unsigned char fuzzRandomByte(void){
248   unsigned char t;
249   sqlite3Prng.i++;
250   t = sqlite3Prng.s[sqlite3Prng.i];
251   sqlite3Prng.j += t;
252   sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
253   sqlite3Prng.s[sqlite3Prng.j] = t;
254   t += sqlite3Prng.s[sqlite3Prng.i];
255   return sqlite3Prng.s[t];
256 }
257 
258 /*
259 ** Return N random bytes.
260 */
261 static void fuzzRandomBlob(int nBuf, unsigned char *zBuf){
262   int i;
263   for(i=0; i<nBuf; i++){
264     zBuf[i] = fuzzRandomByte();
265   }
266 }
267 
268 /*
269 ** Return a random integer between 0 and nRange (not inclusive).
270 */
271 static unsigned int fuzzRandomInt(unsigned int nRange){
272   unsigned int ret;
273   assert( nRange>0 );
274   fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret);
275   return (ret % nRange);
276 }
277 
278 static u64 fuzzRandomU64(){
279   u64 ret;
280   fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret);
281   return ret;
282 }
283 
284 static void fuzzRandomSeed(unsigned int iSeed){
285   int i;
286   for(i=0; i<256; i+=4){
287     sqlite3Prng.s[i] ^= ((iSeed >> 24) & 0xFF);
288     sqlite3Prng.s[i+1] ^= ((iSeed >> 16) & 0xFF);
289     sqlite3Prng.s[i+2] ^= ((iSeed >>  8) & 0xFF);
290     sqlite3Prng.s[i+3] ^= ((iSeed >>  0) & 0xFF);
291   }
292 }
293 /*
294 ** End of code for generating pseudo-random values.
295 *************************************************************************/
296 
297 typedef struct FuzzChangeset FuzzChangeset;
298 typedef struct FuzzChangesetGroup FuzzChangesetGroup;
299 typedef struct FuzzChange FuzzChange;
300 
301 /*
302 ** Object containing partially parsed changeset.
303 */
304 struct FuzzChangeset {
305   int bPatchset;                  /* True for a patchset */
306   FuzzChangesetGroup **apGroup;   /* Array of groups in changeset */
307   int nGroup;                     /* Number of items in list pGroup */
308   u8 **apVal;                     /* Array of all values in changeset */
309   int nVal;                       /* Number of used slots in apVal[] */
310   int nChange;                    /* Number of changes in changeset */
311   int nUpdate;                    /* Number of UPDATE changes in changeset */
312 };
313 
314 /*
315 ** There is one object of this type for each change-group (table header)
316 ** in the input changeset.
317 */
318 struct FuzzChangesetGroup {
319   const char *zTab;               /* Name of table */
320   int nCol;                       /* Number of columns in table */
321   u8 *aPK;                        /* PK array for this table */
322   u8 *aChange;                    /* Buffer containing array of changes */
323   int szChange;                   /* Size of buffer aChange[] in bytes */
324   int nChange;                    /* Number of changes in buffer aChange[] */
325 };
326 
327 /*
328 ** Description of a fuzz change to be applied to a changeset.
329 */
330 struct FuzzChange {
331   int eType;                      /* One of the FUZZ_* constants above */
332   int iChange;                    /* Change or UPDATE to modify */
333   int iGroup;                     /* Group to modify */
334   int iDelete;                    /* Field to remove (FUZZ_COLUMN_DEL) */
335   u8 *pSub1;                      /* Replace this value with pSub2 */
336   u8 *pSub2;                      /* And this one with pSub1 */
337   u8 aSub[128];                   /* Buffer for substitute value */
338   int iCurrent;                   /* Current change number */
339 };
340 
341 /*
342 ** Allocate and return nByte bytes of zeroed memory.
343 */
344 static void *fuzzMalloc(sqlite3_int64 nByte){
345   void *pRet = sqlite3_malloc64(nByte);
346   if( pRet ){
347     memset(pRet, 0, (size_t)nByte);
348   }
349   return pRet;
350 }
351 
352 /*
353 ** Free the buffer indicated by the first argument. This function is used
354 ** to free buffers allocated by fuzzMalloc().
355 */
356 static void fuzzFree(void *p){
357   sqlite3_free(p);
358 }
359 
360 /*
361 ** Argument p points to a buffer containing an SQLite varint that, assuming the
362 ** input is not corrupt, may be between 0 and 0x7FFFFFFF, inclusive. Before
363 ** returning, this function sets (*pnVal) to the value of that varint, and
364 ** returns the number of bytes of space that it takes up.
365 */
366 static int fuzzGetVarint(u8 *p, int *pnVal){
367   int i;
368   sqlite3_uint64 nVal = 0;
369   for(i=0; i<9; i++){
370     nVal = (nVal<<7) + (p[i] & 0x7F);
371     if( (p[i] & 0x80)==0 ){
372       i++;
373       break;
374     }
375   }
376   *pnVal = (int)nVal;
377   return i;
378 }
379 
380 /*
381 ** Write value nVal into the buffer indicated by argument p as an SQLite
382 ** varint. nVal is guaranteed to be between 0 and (2^21-1), inclusive.
383 ** Return the number of bytes written to buffer p.
384 */
385 static int fuzzPutVarint(u8 *p, int nVal){
386   assert( nVal>0 && nVal<2097152 );
387   if( nVal<128 ){
388     p[0] = (u8)nVal;
389     return 1;
390   }
391   if( nVal<16384 ){
392     p[0] = ((nVal >> 7) & 0x7F) | 0x80;
393     p[1] = (nVal & 0x7F);
394     return 2;
395   }
396 
397   p[0] = ((nVal >> 14) & 0x7F) | 0x80;
398   p[1] = ((nVal >> 7) & 0x7F) | 0x80;
399   p[2] = (nVal & 0x7F);
400   return 3;
401 }
402 
403 /*
404 ** Read a 64-bit big-endian integer value from buffer aRec[]. Return
405 ** the value read.
406 */
407 static i64 fuzzGetI64(u8 *aRec){
408   return (i64)(
409       (((u64)aRec[0]) << 56)
410     + (((u64)aRec[1]) << 48)
411     + (((u64)aRec[2]) << 40)
412     + (((u64)aRec[3]) << 32)
413     + (((u64)aRec[4]) << 24)
414     + (((u64)aRec[5]) << 16)
415     + (((u64)aRec[6]) <<  8)
416     + (((u64)aRec[7]) <<  0)
417   );
418 }
419 
420 /*
421 ** Write value iVal to buffer aRec[] as an unsigned 64-bit big-endian integer.
422 */
423 static void fuzzPutU64(u8 *aRec, u64 iVal){
424   aRec[0] = (iVal>>56) & 0xFF;
425   aRec[1] = (iVal>>48) & 0xFF;
426   aRec[2] = (iVal>>40) & 0xFF;
427   aRec[3] = (iVal>>32) & 0xFF;
428   aRec[4] = (iVal>>24) & 0xFF;
429   aRec[5] = (iVal>>16) & 0xFF;
430   aRec[6] = (iVal>> 8) & 0xFF;
431   aRec[7] = (iVal)     & 0xFF;
432 }
433 
434 /*
435 ** Parse a single table-header from the input. Allocate a new change-group
436 ** object with the results. Return SQLITE_OK if successful, or an error code
437 ** otherwise.
438 */
439 static int fuzzParseHeader(
440   FuzzChangeset *pParse,          /* Changeset parse object */
441   u8 **ppHdr,                     /* IN/OUT: Iterator */
442   u8 *pEnd,                       /* 1 byte past EOF */
443   FuzzChangesetGroup **ppGrp      /* OUT: New change-group object */
444 ){
445   int rc = SQLITE_OK;
446   FuzzChangesetGroup *pGrp;
447   u8 cHdr = (pParse->bPatchset ? 'P' : 'T');
448 
449   assert( pEnd>(*ppHdr) );
450   pGrp = (FuzzChangesetGroup*)fuzzMalloc(sizeof(FuzzChangesetGroup));
451   if( !pGrp ){
452     rc = SQLITE_NOMEM;
453   }else{
454     u8 *p = *ppHdr;
455     if( p[0]!=cHdr ){
456       rc = fuzzCorrupt();
457     }else{
458       p++;
459       p += fuzzGetVarint(p, &pGrp->nCol);
460       pGrp->aPK = p;
461       p += pGrp->nCol;
462       pGrp->zTab = (const char*)p;
463       p = &p[strlen((const char*)p)+1];
464 
465       if( p>=pEnd ){
466         rc = fuzzCorrupt();
467       }
468     }
469     *ppHdr = p;
470   }
471 
472   if( rc!=SQLITE_OK ){
473     fuzzFree(pGrp);
474     pGrp = 0;
475   }
476 
477   *ppGrp = pGrp;
478   return rc;
479 }
480 
481 /*
482 ** Argument p points to a buffer containing a single changeset-record value.
483 ** This function attempts to determine the size of the value in bytes. If
484 ** successful, it sets (*pSz) to the size and returns SQLITE_OK. Or, if the
485 ** buffer does not contain a valid value, SQLITE_CORRUPT is returned and
486 ** the final value of (*pSz) is undefined.
487 */
488 static int fuzzChangeSize(u8 *p, int *pSz){
489   u8 eType = p[0];
490   switch( eType ){
491     case 0x00:                    /* undefined */
492     case 0x05:                    /* null */
493       *pSz = 1;
494       break;
495 
496     case 0x01:                    /* integer */
497     case 0x02:                    /* real */
498       *pSz = 9;
499       break;
500 
501     case 0x03:                    /* text */
502     case 0x04: {                  /* blob */
503       int nTxt;
504       int sz;
505       sz = fuzzGetVarint(&p[1], &nTxt);
506       *pSz = 1 + sz + nTxt;
507       break;
508     }
509 
510     default:
511       return fuzzCorrupt();
512   }
513   return SQLITE_OK;
514 }
515 
516 /*
517 ** When this function is called, (*ppRec) points to the start of a
518 ** record in a changeset being parsed. This function adds entries
519 ** to the pParse->apVal[] array for all values and advances (*ppRec)
520 ** to one byte past the end of the record. Argument pEnd points to
521 ** one byte past the end of the input changeset.
522 **
523 ** Argument bPkOnly is true if the record being parsed is part of
524 ** a DELETE record in a patchset. In this case, all non-primary-key
525 ** fields have been omitted from the record.
526 **
527 ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
528 */
529 static int fuzzParseRecord(
530   u8 **ppRec,                     /* IN/OUT: Iterator */
531   u8 *pEnd,                       /* One byte after end of input data */
532   FuzzChangeset *pParse,          /* Changeset parse context */
533   int bPkOnly                     /* True if non-PK fields omitted */
534 ){
535   int rc = SQLITE_OK;
536   FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1];
537   int i;
538   u8 *p = *ppRec;
539 
540   for(i=0; rc==SQLITE_OK && i<pGrp->nCol; i++){
541     if( bPkOnly==0 || pGrp->aPK[i] ){
542       int sz;
543       if( p>=pEnd ) break;
544       if( (pParse->nVal & (pParse->nVal-1))==0 ){
545         int nNew = pParse->nVal ? pParse->nVal*2 : 4;
546         u8 **apNew = (u8**)sqlite3_realloc(pParse->apVal, nNew*sizeof(u8*));
547         if( apNew==0 ) return SQLITE_NOMEM;
548         pParse->apVal = apNew;
549       }
550       pParse->apVal[pParse->nVal++] = p;
551       rc = fuzzChangeSize(p, &sz);
552       p += sz;
553     }
554   }
555 
556   if( rc==SQLITE_OK && i<pGrp->nCol ){
557     rc = fuzzCorrupt();
558   }
559 
560   *ppRec = p;
561   return rc;
562 }
563 
564 /*
565 ** Parse the array of changes starting at (*ppData) and add entries for
566 ** all values to the pParse->apVal[] array. Argument pEnd points to one byte
567 ** past the end of the input changeset. If successful, set (*ppData) to point
568 ** to one byte past the end of the change array and return SQLITE_OK.
569 ** Otherwise, return an SQLite error code. The final value of (*ppData) is
570 ** undefined in this case.
571 */
572 static int fuzzParseChanges(u8 **ppData, u8 *pEnd, FuzzChangeset *pParse){
573   u8 cHdr = (pParse->bPatchset ? 'P' : 'T');
574   FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1];
575   int rc = SQLITE_OK;
576   u8 *p = *ppData;
577 
578   pGrp->aChange = p;
579   while( rc==SQLITE_OK && p<pEnd && p[0]!=cHdr ){
580     u8 eOp = p[0];
581     u8 bIndirect = p[1];
582 
583     p += 2;
584     if( eOp==SQLITE_UPDATE ){
585       pParse->nUpdate++;
586       if( pParse->bPatchset==0 ){
587         rc = fuzzParseRecord(&p, pEnd, pParse, 0);
588       }
589     }else if( eOp!=SQLITE_INSERT && eOp!=SQLITE_DELETE ){
590       rc = fuzzCorrupt();
591     }
592     if( rc==SQLITE_OK ){
593       int bPkOnly = (eOp==SQLITE_DELETE && pParse->bPatchset);
594       rc = fuzzParseRecord(&p, pEnd, pParse, bPkOnly);
595     }
596     pGrp->nChange++;
597     pParse->nChange++;
598   }
599   pGrp->szChange = p - pGrp->aChange;
600 
601   *ppData = p;
602   return rc;
603 }
604 
605 /*
606 ** Parse the changeset stored in buffer pChangeset (nChangeset bytes in
607 ** size). If successful, write the results into (*pParse) and return
608 ** SQLITE_OK. Or, if an error occurs, return an SQLite error code. The
609 ** final state of (*pParse) is undefined in this case.
610 */
611 static int fuzzParseChangeset(
612   u8 *pChangeset,                 /* Buffer containing changeset */
613   int nChangeset,                 /* Size of buffer in bytes */
614   FuzzChangeset *pParse           /* OUT: Results of parse */
615 ){
616   u8 *pEnd = &pChangeset[nChangeset];
617   u8 *p = pChangeset;
618   int rc = SQLITE_OK;
619 
620   memset(pParse, 0, sizeof(FuzzChangeset));
621   if( nChangeset>0 ){
622     pParse->bPatchset = (pChangeset[0]=='P');
623   }
624 
625   while( rc==SQLITE_OK && p<pEnd ){
626     FuzzChangesetGroup *pGrp = 0;
627 
628     /* Read a table-header from the changeset */
629     rc = fuzzParseHeader(pParse, &p, pEnd, &pGrp);
630     assert( (rc==SQLITE_OK)==(pGrp!=0) );
631 
632     /* If the table-header was successfully parsed, add the new change-group
633     ** to the array and parse the associated changes. */
634     if( rc==SQLITE_OK ){
635       FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc64(
636           pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1)
637       );
638       if( apNew==0 ){
639         rc = SQLITE_NOMEM;
640       }else{
641         apNew[pParse->nGroup] = pGrp;
642         pParse->apGroup = apNew;
643         pParse->nGroup++;
644       }
645       rc = fuzzParseChanges(&p, pEnd, pParse);
646     }
647   }
648 
649   return rc;
650 }
651 
652 /*
653 ** When this function is called, (*ppRec) points to the first byte of
654 ** a record that is part of change-group pGrp. This function attempts
655 ** to output a human-readable version of the record to stdout and advance
656 ** (*ppRec) to point to the first byte past the end of the record before
657 ** returning. If successful, SQLITE_OK is returned. Otherwise, an SQLite
658 ** error code.
659 **
660 ** If parameter bPkOnly is non-zero, then all non-primary-key fields have
661 ** been omitted from the record. This occurs for records that are part
662 ** of DELETE changes in patchsets.
663 */
664 static int fuzzPrintRecord(FuzzChangesetGroup *pGrp, u8 **ppRec, int bPKOnly){
665   int rc = SQLITE_OK;
666   u8 *p = *ppRec;
667   int i;
668   const char *zPre = " (";
669 
670   for(i=0; i<pGrp->nCol; i++){
671     if( bPKOnly==0 || pGrp->aPK[i] ){
672       u8 eType = p++[0];
673       switch( eType ){
674         case 0x00:                    /* undefined */
675           printf("%sn/a", zPre);
676           break;
677 
678         case 0x01: {                  /* integer */
679           sqlite3_int64 iVal = 0;
680           iVal = fuzzGetI64(p);
681           printf("%s%lld", zPre, iVal);
682           p += 8;
683           break;
684         }
685 
686         case 0x02: {                  /* real */
687           sqlite3_int64 iVal = 0;
688           double fVal = 0.0;
689           iVal = fuzzGetI64(p);
690           memcpy(&fVal, &iVal, 8);
691           printf("%s%f", zPre, fVal);
692           p += 8;
693           break;
694         }
695 
696         case 0x03:                    /* text */
697         case 0x04: {                  /* blob */
698           int nTxt;
699           p += fuzzGetVarint(p, &nTxt);
700           printf("%s%s", zPre, eType==0x03 ? "'" : "X'");
701           for(i=0; i<nTxt; i++){
702             if( eType==0x03 ){
703               printf("%c", p[i]);
704             }else{
705               char aHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
706                                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
707               };
708               printf("%c", aHex[ p[i]>>4 ]);
709               printf("%c", aHex[ p[i] & 0x0F ]);
710             }
711           }
712           printf("'");
713           p += nTxt;
714           break;
715         }
716 
717         case 0x05:                    /* null */
718           printf("%sNULL", zPre);
719           break;
720       }
721       zPre = ", ";
722     }
723   }
724   printf(")");
725 
726   *ppRec = p;
727   return rc;
728 }
729 
730 /*
731 ** Print a human-readable version of the table-header and all changes in the
732 ** change-group passed as the second argument.
733 */
734 static void fuzzPrintGroup(FuzzChangeset *pParse, FuzzChangesetGroup *pGrp){
735   int i;
736   u8 *p;
737 
738   /* The table header */
739   printf("TABLE:  %s nCol=%d aPK=", pGrp->zTab, pGrp->nCol);
740   for(i=0; i<pGrp->nCol; i++){
741     printf("%d", (int)pGrp->aPK[i]);
742   }
743   printf("\n");
744 
745   /* The array of changes */
746   p = pGrp->aChange;
747   for(i=0; i<pGrp->nChange; i++){
748     u8 eType = p[0];
749     u8 bIndirect = p[1];
750     printf("%s (ind=%d):",
751         (eType==SQLITE_INSERT) ? "INSERT" :
752         (eType==SQLITE_DELETE ? "DELETE" : "UPDATE"),
753         bIndirect
754     );
755     p += 2;
756 
757     if( pParse->bPatchset==0 && eType==SQLITE_UPDATE ){
758       fuzzPrintRecord(pGrp, &p, 0);
759     }
760     fuzzPrintRecord(pGrp, &p, eType==SQLITE_DELETE && pParse->bPatchset);
761     printf("\n");
762   }
763 }
764 
765 /*
766 ** Initialize the object passed as the second parameter with details
767 ** of the change that will be attempted (type of change, to which part of the
768 ** changeset it applies etc.). If successful, return SQLITE_OK. Or, if an
769 ** error occurs, return an SQLite error code.
770 **
771 ** If a negative value is returned, then the selected change would have
772 ** produced a non-well-formed changeset. In this case the caller should
773 ** call this function again.
774 */
775 static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){
776   int iSub;
777 
778   memset(pChange, 0, sizeof(FuzzChange));
779   pChange->eType = fuzzRandomInt(FUZZ_COLUMN_DEL) + 1;
780 
781   assert( pChange->eType==FUZZ_VALUE_SUB
782        || pChange->eType==FUZZ_VALUE_MOD
783        || pChange->eType==FUZZ_VALUE_RND
784        || pChange->eType==FUZZ_CHANGE_DUP
785        || pChange->eType==FUZZ_CHANGE_DEL
786        || pChange->eType==FUZZ_CHANGE_TYPE
787        || pChange->eType==FUZZ_CHANGE_FIELD
788        || pChange->eType==FUZZ_CHANGE_INDIRECT
789        || pChange->eType==FUZZ_GROUP_DUP
790        || pChange->eType==FUZZ_GROUP_DEL
791        || pChange->eType==FUZZ_GROUP_SWAP
792        || pChange->eType==FUZZ_COLUMN_ADD
793        || pChange->eType==FUZZ_COLUMN_ADDPK
794        || pChange->eType==FUZZ_COLUMN_DEL
795   );
796 
797   pChange->iGroup = fuzzRandomInt(pParse->nGroup);
798   pChange->iChange = fuzzRandomInt(pParse->nChange);
799   if( pChange->eType==FUZZ_CHANGE_FIELD ){
800     if( pParse->nUpdate==0 ) return -1;
801     pChange->iChange = fuzzRandomInt(pParse->nUpdate);
802   }
803 
804   pChange->iDelete = -1;
805   if( pChange->eType==FUZZ_COLUMN_DEL ){
806     FuzzChangesetGroup *pGrp = pParse->apGroup[pChange->iGroup];
807     int i;
808     pChange->iDelete = fuzzRandomInt(pGrp->nCol);
809     for(i=pGrp->nCol-1; i>=0; i--){
810       if( pGrp->aPK[i] && pChange->iDelete!=i ) break;
811     }
812     if( i<0 ) return -1;
813   }
814 
815   if( pChange->eType==FUZZ_GROUP_SWAP ){
816     FuzzChangesetGroup *pGrp;
817     int iGrp = pChange->iGroup;
818     if( pParse->nGroup==1 ) return -1;
819     while( iGrp==pChange->iGroup ){
820       iGrp = fuzzRandomInt(pParse->nGroup);
821     }
822     pGrp = pParse->apGroup[pChange->iGroup];
823     pParse->apGroup[pChange->iGroup] = pParse->apGroup[iGrp];
824     pParse->apGroup[iGrp] = pGrp;
825   }
826 
827   if( pChange->eType==FUZZ_VALUE_SUB
828    || pChange->eType==FUZZ_VALUE_MOD
829    || pChange->eType==FUZZ_VALUE_RND
830   ){
831     iSub = fuzzRandomInt(pParse->nVal);
832     pChange->pSub1 = pParse->apVal[iSub];
833     if( pChange->eType==FUZZ_VALUE_SUB ){
834       iSub = fuzzRandomInt(pParse->nVal);
835       pChange->pSub2 = pParse->apVal[iSub];
836     }else{
837       pChange->pSub2 = pChange->aSub;
838     }
839 
840     if( pChange->eType==FUZZ_VALUE_RND ){
841       pChange->aSub[0] = (u8)(fuzzRandomInt(5) + 1);
842       switch( pChange->aSub[0] ){
843         case 0x01: {                  /* integer */
844           u64 iVal = fuzzRandomU64();
845           fuzzPutU64(&pChange->aSub[1], iVal);
846           break;
847         }
848 
849         case 0x02: {                  /* real */
850           u64 iVal1 = fuzzRandomU64();
851           u64 iVal2 = fuzzRandomU64();
852           double d = (double)iVal1 / (double)iVal2;
853           memcpy(&iVal1, &d, sizeof(iVal1));
854           fuzzPutU64(&pChange->aSub[1], iVal1);
855           break;
856         }
857 
858         case 0x03:                    /* text */
859         case 0x04: {                  /* blob */
860           int nByte = fuzzRandomInt(48);
861           pChange->aSub[1] = (u8)nByte;
862           fuzzRandomBlob(nByte, &pChange->aSub[2]);
863           if( pChange->aSub[0]==0x03 ){
864             int i;
865             for(i=0; i<nByte; i++){
866               pChange->aSub[2+i] &= 0x7F;
867             }
868           }
869           break;
870         }
871       }
872     }
873     if( pChange->eType==FUZZ_VALUE_MOD ){
874       int sz;
875       int iMod = -1;
876       fuzzChangeSize(pChange->pSub1, &sz);
877       memcpy(pChange->aSub, pChange->pSub1, sz);
878       switch( pChange->aSub[0] ){
879         case 0x01:
880         case 0x02:
881           iMod = fuzzRandomInt(8) + 1;
882           break;
883 
884         case 0x03:                    /* text */
885         case 0x04: {                  /* blob */
886           int nByte;
887           int iFirst = 1 + fuzzGetVarint(&pChange->aSub[1], &nByte);
888           if( nByte>0 ){
889             iMod = fuzzRandomInt(nByte) + iFirst;
890           }
891           break;
892         }
893       }
894 
895       if( iMod>=0 ){
896         u8 mask = (1 << fuzzRandomInt(8 - (pChange->aSub[0]==0x03)));
897         pChange->aSub[iMod] ^= mask;
898       }
899     }
900   }
901 
902   return SQLITE_OK;
903 }
904 
905 /*
906 ** Copy a single change from the input to the output changeset, making
907 ** any modifications specified by (*pFuzz).
908 */
909 static int fuzzCopyChange(
910   FuzzChangeset *pParse,
911   int iGrp,
912   FuzzChange *pFuzz,
913   u8 **pp, u8 **ppOut             /* IN/OUT: Input and output pointers */
914 ){
915   int bPS = pParse->bPatchset;
916   FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
917   u8 *p = *pp;
918   u8 *pOut = *ppOut;
919   u8 eType = p++[0];
920   int iRec;
921   int nRec = ((eType==SQLITE_UPDATE && !bPS) ? 2 : 1);
922   int iUndef = -1;
923   int nUpdate = 0;
924 
925   u8 eNew = eType;
926   if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_TYPE ){
927     switch( eType ){
928       case SQLITE_INSERT:
929         eNew = SQLITE_DELETE;
930         break;
931       case SQLITE_DELETE:
932         eNew = SQLITE_UPDATE;
933         break;
934       case SQLITE_UPDATE:
935         eNew = SQLITE_INSERT;
936         break;
937     }
938   }
939 
940   if( pFuzz->iCurrent==pFuzz->iChange
941    && pFuzz->eType==FUZZ_CHANGE_FIELD && eType==SQLITE_UPDATE
942   ){
943     int sz;
944     int i;
945     int nDef = 0;
946     u8 *pCsr = p+1;
947     for(i=0; i<pGrp->nCol; i++){
948       if( pCsr[0] && pGrp->aPK[i]==0 ) nDef++;
949       fuzzChangeSize(pCsr, &sz);
950       pCsr += sz;
951     }
952     if( nDef<=1 ) return -1;
953     nDef = fuzzRandomInt(nDef);
954     pCsr = p+1;
955     for(i=0; i<pGrp->nCol; i++){
956       if( pCsr[0] && pGrp->aPK[i]==0 ){
957         if( nDef==0 ) iUndef = i;
958         nDef--;
959       }
960       fuzzChangeSize(pCsr, &sz);
961       pCsr += sz;
962     }
963   }
964 
965   /* Copy the change type and indirect flag. If the fuzz mode is
966   ** FUZZ_CHANGE_INDIRECT, and the current change is the one selected for
967   ** fuzzing, invert the indirect flag.  */
968   *(pOut++) = eNew;
969   if( pFuzz->eType==FUZZ_CHANGE_INDIRECT && pFuzz->iCurrent==pFuzz->iChange ){
970     *(pOut++) = !(*(p++));
971   }else{
972     *(pOut++) = *(p++);
973   }
974 
975   for(iRec=0; iRec<nRec; iRec++){
976     int i;
977 
978     /* Copy the next record from the output to the input.
979     */
980     for(i=0; i<pGrp->nCol; i++){
981       int sz;
982       u8 *pCopy = p;
983 
984       /* If this is a patchset, and the input is a DELETE, then the only
985       ** fields present are the PK fields. So, if this is not a PK, skip to
986       ** the next column. If the current fuzz is FUZZ_CHANGE_TYPE, then
987       ** write a randomly selected value to the output.  */
988       if( bPS && eType==SQLITE_DELETE && pGrp->aPK[i]==0 ){
989         if( eType!=eNew ){
990           assert( eNew==SQLITE_UPDATE );
991           do {
992             pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
993           }while( pCopy[0]==0x00 );
994           fuzzChangeSize(pCopy, &sz);
995           memcpy(pOut, pCopy, sz);
996           pOut += sz;
997         }
998         continue;
999       }
1000 
1001       if( p==pFuzz->pSub1 ){
1002         pCopy = pFuzz->pSub2;
1003       }else if( p==pFuzz->pSub2 ){
1004         pCopy = pFuzz->pSub1;
1005       }else if( i==iUndef ){
1006         pCopy = (u8*)"\0";
1007       }
1008 
1009       if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){
1010         while( pCopy[0]==0x00 ){
1011           pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
1012         }
1013       }else if( p[0]==0x00 && pCopy[0]!=0x00 ){
1014         return -1;
1015       }else{
1016         if( pGrp->aPK[i]>0 && pCopy[0]==0x05 ) return -1;
1017       }
1018 
1019       if( (pFuzz->iGroup!=iGrp || i!=pFuzz->iDelete)
1020        && (eNew==eType || eType!=SQLITE_UPDATE || iRec==0)
1021        && (eNew==eType || eNew!=SQLITE_DELETE || !bPS || pGrp->aPK[i])
1022       ){
1023         fuzzChangeSize(pCopy, &sz);
1024         memcpy(pOut, pCopy, sz);
1025         pOut += sz;
1026         nUpdate += (pGrp->aPK[i]==0 && pCopy[0]!=0x00);
1027       }
1028 
1029       fuzzChangeSize(p, &sz);
1030       p += sz;
1031     }
1032 
1033     if( iGrp==pFuzz->iGroup ){
1034       if( pFuzz->eType==FUZZ_COLUMN_ADD ){
1035         if( !bPS || eType!=SQLITE_DELETE ) *(pOut++) = 0x05;
1036       }else if( pFuzz->eType==FUZZ_COLUMN_ADDPK ){
1037         if( iRec==1 ){
1038           *(pOut++) = 0x00;
1039         }else{
1040           u8 *pNew;
1041           int szNew;
1042           do {
1043             pNew = pParse->apVal[fuzzRandomInt(pParse->nVal)];
1044           }while( pNew[0]==0x00 || pNew[0]==0x05 );
1045           fuzzChangeSize(pNew, &szNew);
1046           memcpy(pOut, pNew, szNew);
1047           pOut += szNew;
1048         }
1049       }
1050     }
1051   }
1052 
1053   if( pFuzz->iCurrent==pFuzz->iChange ){
1054     if( pFuzz->eType==FUZZ_CHANGE_DUP ){
1055       int nByte = pOut - (*ppOut);
1056       memcpy(pOut, *ppOut, nByte);
1057       pOut += nByte;
1058     }
1059 
1060     if( pFuzz->eType==FUZZ_CHANGE_DEL ){
1061       pOut = *ppOut;
1062     }
1063     if( eNew!=eType && eNew==SQLITE_UPDATE && !bPS ){
1064       int i;
1065       u8 *pCsr = (*ppOut) + 2;
1066       for(i=0; i<pGrp->nCol; i++){
1067         int sz;
1068         u8 *pCopy = pCsr;
1069         if( pGrp->aPK[i] ) pCopy = (u8*)"\0";
1070         fuzzChangeSize(pCopy, &sz);
1071         memcpy(pOut, pCopy, sz);
1072         pOut += sz;
1073         fuzzChangeSize(pCsr, &sz);
1074         pCsr += sz;
1075       }
1076     }
1077   }
1078 
1079   /* If a column is being deleted from this group, and this change was an
1080   ** UPDATE, and there are now no non-PK, non-undefined columns in the
1081   ** change, remove it altogether. */
1082   if( pFuzz->eType==FUZZ_COLUMN_DEL && pFuzz->iGroup==iGrp
1083    && eType==SQLITE_UPDATE && nUpdate==0
1084   ){
1085     pOut = *ppOut;
1086   }
1087 
1088   *pp = p;
1089   *ppOut = pOut;
1090   pFuzz->iCurrent += (eType==SQLITE_UPDATE || pFuzz->eType!=FUZZ_CHANGE_FIELD);
1091   return SQLITE_OK;
1092 }
1093 
1094 /*
1095 ** Fuzz the changeset parsed into object pParse and write the results
1096 ** to file zOut on disk. Argument pBuf points to a buffer that is guaranteed
1097 ** to be large enough to hold the fuzzed changeset.
1098 **
1099 ** Return SQLITE_OK if successful, or an SQLite error code if an error occurs.
1100 */
1101 static int fuzzDoOneFuzz(
1102   const char *zOut,               /* Filename to write modified changeset to */
1103   u8 *pBuf,                       /* Buffer to use for modified changeset */
1104   FuzzChangeset *pParse           /* Parse of input changeset */
1105 ){
1106   FuzzChange change;
1107   int iGrp;
1108   int rc = -1;
1109 
1110   while( rc<0 ){
1111     u8 *pOut = pBuf;
1112     rc = fuzzSelectChange(pParse, &change);
1113     for(iGrp=0; rc==SQLITE_OK && iGrp<pParse->nGroup; iGrp++){
1114       FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
1115       int nTab = strlen(pGrp->zTab) + 1;
1116       int j;
1117       int nRep = 1;
1118 
1119       /* If this is the group to delete for a FUZZ_GROUP_DEL change, jump to
1120       ** the next group. Unless this is the only group in the changeset - in
1121       ** that case this change cannot be applied.
1122       **
1123       ** Or, if this is a FUZZ_GROUP_DUP, set nRep to 2 to output two
1124       ** copies of the group. */
1125       if( change.iGroup==iGrp ){
1126         if( change.eType==FUZZ_GROUP_DEL ){
1127           if( pParse->nGroup==1 ) rc = -1;
1128           continue;
1129         }
1130         else if( change.eType==FUZZ_GROUP_DUP ){
1131           nRep = 2;
1132         }
1133       }
1134 
1135       for(j=0; j<nRep; j++){
1136         int i;
1137         u8 *pSaved;
1138         u8 *p = pGrp->aChange;
1139         int nCol = pGrp->nCol;
1140         int iPKDel = 0;
1141         if( iGrp==change.iGroup ){
1142           if( change.eType==FUZZ_COLUMN_ADD
1143            || change.eType==FUZZ_COLUMN_ADDPK
1144           ){
1145             nCol++;
1146           }else if( change.eType==FUZZ_COLUMN_DEL ){
1147             nCol--;
1148             iPKDel = pGrp->aPK[change.iDelete];
1149           }
1150         }
1151 
1152         /* Output a table header */
1153         pOut++[0] = pParse->bPatchset ? 'P' : 'T';
1154         pOut += fuzzPutVarint(pOut, nCol);
1155 
1156         for(i=0; i<pGrp->nCol; i++){
1157           if( iGrp!=change.iGroup || i!=change.iDelete ){
1158             u8 v = pGrp->aPK[i];
1159             if( iPKDel && v>iPKDel ) v--;
1160             *(pOut++) = v;
1161           }
1162         }
1163         if( nCol>pGrp->nCol ){
1164           if( change.eType==FUZZ_COLUMN_ADD ){
1165             *(pOut++) = 0x00;
1166           }else{
1167             u8 max = 0;
1168             for(i=0; i<pGrp->nCol; i++){
1169               if( pGrp->aPK[i]>max ) max = pGrp->aPK[i];
1170             }
1171             *(pOut++) = max+1;
1172           }
1173         }
1174         memcpy(pOut, pGrp->zTab, nTab);
1175         pOut += nTab;
1176 
1177         /* Output the change array. */
1178         pSaved = pOut;
1179         for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){
1180           rc = fuzzCopyChange(pParse, iGrp, &change, &p, &pOut);
1181         }
1182         if( pOut==pSaved ) rc = -1;
1183       }
1184     }
1185     if( rc==SQLITE_OK ){
1186       fuzzWriteFile(zOut, pBuf, pOut-pBuf);
1187     }
1188   }
1189 
1190   return rc;
1191 }
1192 
1193 int main(int argc, char **argv){
1194   int nRepeat = 0;                /* Number of output files */
1195   int iSeed = 0;                  /* Value of PRNG seed */
1196   const char *zInput;             /* Name of input file */
1197   void *pChangeset = 0;           /* Input changeset */
1198   int nChangeset = 0;             /* Size of input changeset in bytes */
1199   int i;                          /* Current output file */
1200   FuzzChangeset changeset;        /* Partially parsed changeset */
1201   int rc;
1202   u8 *pBuf = 0;
1203 
1204   if( argc!=4 && argc!=2 ) usage(argv[0]);
1205   zInput = argv[1];
1206 
1207   fuzzReadFile(zInput, &nChangeset, &pChangeset);
1208   rc = fuzzParseChangeset(pChangeset, nChangeset, &changeset);
1209 
1210   if( rc==SQLITE_OK ){
1211     if( argc==2 ){
1212       for(i=0; i<changeset.nGroup; i++){
1213         fuzzPrintGroup(&changeset, changeset.apGroup[i]);
1214       }
1215     }else{
1216       pBuf = (u8*)fuzzMalloc((sqlite3_int64)nChangeset*2 + 1024);
1217       if( pBuf==0 ){
1218         rc = SQLITE_NOMEM;
1219       }else{
1220         iSeed = atoi(argv[2]);
1221         nRepeat = atoi(argv[3]);
1222         fuzzRandomSeed((unsigned int)iSeed);
1223         for(i=0; rc==SQLITE_OK && i<nRepeat; i++){
1224           char *zOut = sqlite3_mprintf("%s-%d", zInput, i);
1225           rc = fuzzDoOneFuzz(zOut, pBuf, &changeset);
1226           sqlite3_free(zOut);
1227         }
1228         fuzzFree(pBuf);
1229       }
1230     }
1231   }
1232 
1233   if( rc!=SQLITE_OK ){
1234     fprintf(stderr, "error while processing changeset: %d\n", rc);
1235   }
1236 
1237   return rc;
1238 }
1239