SQLite

Check-in [b7394755fa]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In fuzzershell: (1) comment fixes. (2) Set and clear g.zTestName[] correctly. (3) Use the value in g.zTestName[] in error messages.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b7394755fab81329d56bad1b506e536b2fcbe8cd
User & Date: drh 2015-04-25 11:35:48.066
Context
2015-04-25
12:20
Fix an obscure memory leak that could follow an OOM in where.c. (check-in: 08ec9f2f5a user: dan tags: trunk)
11:35
In fuzzershell: (1) comment fixes. (2) Set and clear g.zTestName[] correctly. (3) Use the value in g.zTestName[] in error messages. (check-in: b7394755fa user: drh tags: trunk)
11:19
In the fuzzershell, always invoke the trace and log callbacks even if output is suppressed. Keep track of the current test name in a global variable for simplified debugging. (check-in: 3045f45481 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to tool/fuzzershell.c.
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
**    (3)  The main in-memory database can be initialized from a template
**         disk database so that the fuzzer starts with a database containing
**         content.
**
**    (4)  The eval() SQL function is added, allowing the fuzzer to do 
**         interesting recursive operations.
**


** 2015-04-20: The input text can be divided into separate SQL chunks using
** lines of the form:
**
**       |****<...>****|
**
** where the "..." is arbitrary text, except the "|" should really be "/".
** ("|" is used here to avoid compiler warnings about nested comments.)
** A separate in-memory SQLite database is created to run each chunk of SQL.
** This feature allows the "queue" of AFL to be captured into a single big
** file using a command like this:
**
**    (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
**
** (Once again, change the "|" to "/") Then all elements of the AFL queue
** can be run in a single go (for regression testing, for example) by typing:
**
**    fuzzershell -f ~/all-queue.txt
**
** After running each chunk of SQL, the database connection is closed.  The
** program aborts if the close fails or if there is any unfreed memory after
** the close.
**
** New cases can be appended to all-queue.txt at any time.  If redundant cases
** are added, that can be eliminated by running:
**
**    fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>







>
>
|
|




|
|














|
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
**    (3)  The main in-memory database can be initialized from a template
**         disk database so that the fuzzer starts with a database containing
**         content.
**
**    (4)  The eval() SQL function is added, allowing the fuzzer to do 
**         interesting recursive operations.
**
**    (5)  An error is raised if there is a memory leak.
**
** The input text can be divided into separate test cases using comments
** of the form:
**
**       |****<...>****|
**
** where the "..." is arbitrary text, except the "|" should really be "/".
** ("|" is used here to avoid compiler errors about nested comments.)
** A separate in-memory SQLite database is created to run each test case.
** This feature allows the "queue" of AFL to be captured into a single big
** file using a command like this:
**
**    (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
**
** (Once again, change the "|" to "/") Then all elements of the AFL queue
** can be run in a single go (for regression testing, for example) by typing:
**
**    fuzzershell -f ~/all-queue.txt
**
** After running each chunk of SQL, the database connection is closed.  The
** program aborts if the close fails or if there is any unfreed memory after
** the close.
**
** New test cases can be appended to all-queue.txt at any time.  If redundant
** test cases are added, they can be eliminated by running:
**
**    fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
} g;

/*
** This routine is called when a simulated OOM occurs.  It exists as a
** convenient place to set a debugger breakpoint.
*/
static void oomFault(void){
  g.nOomBrkpt++;
}


/* Versions of malloc() and realloc() that simulate OOM conditions */
static void *oomMalloc(int nByte){
  if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
    g.iOomCntdown--;







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
} g;

/*
** This routine is called when a simulated OOM occurs.  It exists as a
** convenient place to set a debugger breakpoint.
*/
static void oomFault(void){
  g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */
}


/* Versions of malloc() and realloc() that simulate OOM conditions */
static void *oomMalloc(int nByte){
  if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
    g.iOomCntdown--;
119
120
121
122
123
124
125



126

127
128
129
130
131
132
133
134
135
136
137
138



139

140
141
142
143
144
145
146

/*
** Print an error message and abort in such a way to indicate to the
** fuzzer that this counts as a crash.
*/
static void abendError(const char *zFormat, ...){
  va_list ap;



  fprintf(stderr, "%s: ", g.zArgv0);

  va_start(ap, zFormat);
  vfprintf(stderr, zFormat, ap);
  va_end(ap);
  fprintf(stderr, "\n");
  abort();
}
/*
** Print an error message and quit, but not in a way that would look
** like a crash.
*/
static void fatalError(const char *zFormat, ...){
  va_list ap;



  fprintf(stderr, "%s: ", g.zArgv0);

  va_start(ap, zFormat);
  vfprintf(stderr, zFormat, ap);
  va_end(ap);
  fprintf(stderr, "\n");
  exit(1);
}








>
>
>
|
>












>
>
>
|
>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

/*
** Print an error message and abort in such a way to indicate to the
** fuzzer that this counts as a crash.
*/
static void abendError(const char *zFormat, ...){
  va_list ap;
  if( g.zTestName[0] ){
    fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
  }else{
    fprintf(stderr, "%s: ", g.zArgv0);
  }
  va_start(ap, zFormat);
  vfprintf(stderr, zFormat, ap);
  va_end(ap);
  fprintf(stderr, "\n");
  abort();
}
/*
** Print an error message and quit, but not in a way that would look
** like a crash.
*/
static void fatalError(const char *zFormat, ...){
  va_list ap;
  if( g.zTestName[0] ){
    fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
  }else{
    fprintf(stderr, "%s: ", g.zArgv0);
  }
  va_start(ap, zFormat);
  vfprintf(stderr, zFormat, ap);
  va_end(ap);
  fprintf(stderr, "\n");
  exit(1);
}

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
    }
  }
  for(i=0; i<nIn; i=iNext+1){   /* Skip initial lines beginning with '#' */
    if( zIn[i]!='#' ) break;
    for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
  }
  nHeader = i;
  for(nTest=0; i<nIn; i=iNext, nTest++){
    char cSaved;
    if( strncmp(&zIn[i], "/****<",6)==0 ){
      char *z = strstr(&zIn[i], ">****/");
      if( z ){
        z += 6;
        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*", 
                         (int)(z-&zIn[i]), &zIn[i]);
        if( verboseFlag ){
          printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
          fflush(stdout);
        }
        i += (int)(z-&zIn[i]);
        multiTest = 1;







|





|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
    }
  }
  for(i=0; i<nIn; i=iNext+1){   /* Skip initial lines beginning with '#' */
    if( zIn[i]!='#' ) break;
    for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
  }
  nHeader = i;
  for(nTest=0; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
    char cSaved;
    if( strncmp(&zIn[i], "/****<",6)==0 ){
      char *z = strstr(&zIn[i], ">****/");
      if( z ){
        z += 6;
        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s", 
                         (int)(z-&zIn[i]), &zIn[i]);
        if( verboseFlag ){
          printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
          fflush(stdout);
        }
        i += (int)(z-&zIn[i]);
        multiTest = 1;