/ Check-in [f60657c2]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add the fuzzoomtest target to the makefiles. Invoke fuzzoomtest from releasetest.tcl.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f60657c2ae8a11f1e546c953bca07d9396142f73
User & Date: drh 2015-04-25 13:39:29
Context
2015-04-25
16:39
Fuzzershell: change the error summary output to work with releasetest.tcl. Reduce the maximum number of OOM interations. check-in: f5e6c4b2 user: drh tags: trunk
13:39
Add the fuzzoomtest target to the makefiles. Invoke fuzzoomtest from releasetest.tcl. check-in: f60657c2 user: drh tags: trunk
12:20
Fix an obscure memory leak that could follow an OOM in where.c. check-in: 08ec9f2f user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968



969
970
971
972
973
974
975
		-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)

# A very detailed test running most or all test cases
fulltest:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
	./testfixture$(TEXE) $(TOP)/test/all.test

# Really really long testing
soaktest:	testfixture$(TEXE) sqlite3$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/all.test -soak=1

# Do extra testing but not aeverything.
fulltestonly:	testfixture$(TEXE) sqlite3$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/full.test

# Fuzz testing
fuzztest:	fuzzershell$(TEXE)
	./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt




# This is the common case.  Run many tests but not those that take
# a really long time.
#
test:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
	./testfixture$(TEXE) $(TOP)/test/veryquick.test

# Run a test using valgrind.  This can take a really long time







|










>
>
>







951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
		-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)

# A very detailed test running most or all test cases
fulltest:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
	./testfixture$(TEXE) $(TOP)/test/all.test

# Really really long testing
soaktest:	testfixture$(TEXE) sqlite3$(TEXE) fuzzoomtest
	./testfixture$(TEXE) $(TOP)/test/all.test -soak=1

# Do extra testing but not aeverything.
fulltestonly:	testfixture$(TEXE) sqlite3$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/full.test

# Fuzz testing
fuzztest:	fuzzershell$(TEXE)
	./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt

fuzzoomtest:	fuzzershell$(TEXE)
	./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt --oom

# This is the common case.  Run many tests but not those that take
# a really long time.
#
test:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
	./testfixture$(TEXE) $(TOP)/test/veryquick.test

# Run a test using valgrind.  This can take a really long time

Changes to Makefile.msc.

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641



1642
1643
1644
1645
1646
1647
1648

extensiontest: testfixture.exe testloadext.dll
	.\testfixture.exe $(TOP)\test\loadext.test

fulltest:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\all.test

soaktest:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\all.test -soak=1

fulltestonly:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\full.test

queryplantest:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\permutations.test queryplanner

fuzztest:	fuzzershell.exe
	.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt




test:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\veryquick.test

smoketest:	testfixture.exe
	.\testfixture.exe $(TOP)\test\main.test

sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl







|











>
>
>







1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

extensiontest: testfixture.exe testloadext.dll
	.\testfixture.exe $(TOP)\test\loadext.test

fulltest:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\all.test

soaktest:	testfixture.exe sqlite3.exe fuzzoomtest
	.\testfixture.exe $(TOP)\test\all.test -soak=1

fulltestonly:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\full.test

queryplantest:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\permutations.test queryplanner

fuzztest:	fuzzershell.exe
	.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt

fuzzoomtest:	fuzzershell.exe
	.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom

test:	testfixture.exe sqlite3.exe fuzztest
	.\testfixture.exe $(TOP)\test\veryquick.test

smoketest:	testfixture.exe
	.\testfixture.exe $(TOP)\test\main.test

sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl

Changes to main.mk.

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650



651
652
653
654
655
656
657
	-DSQLITE_ENABLE_FTS3=1                                               \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c       \
		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)

fulltest:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/all.test

soaktest:	testfixture$(EXE) sqlite3$(EXE)
	./testfixture$(EXE) $(TOP)/test/all.test -soak=1

fulltestonly:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/full.test

queryplantest:	testfixture$(EXE) sqlite3$(EXE)
	./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner

fuzztest:	fuzzershell$(EXE)
	./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt




test:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/veryquick.test

# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	testfixture$(EXE) sqlite3$(EXE) fuzzershell$(EXE)







|











>
>
>







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
	-DSQLITE_ENABLE_FTS3=1                                               \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c       \
		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)

fulltest:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/all.test

soaktest:	testfixture$(EXE) sqlite3$(EXE) fuzzoomtest
	./testfixture$(EXE) $(TOP)/test/all.test -soak=1

fulltestonly:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/full.test

queryplantest:	testfixture$(EXE) sqlite3$(EXE)
	./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner

fuzztest:	fuzzershell$(EXE)
	./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt

fuzzoomtest:	fuzzershell$(EXE)
	./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom

test:	testfixture$(EXE) sqlite3$(EXE) fuzztest
	./testfixture$(EXE) $(TOP)/test/veryquick.test

# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	testfixture$(EXE) sqlite3$(EXE) fuzzershell$(EXE)

Changes to test/releasetest.tcl.

107
108
109
110
111
112
113







114
115
116
117
118
119
120
...
213
214
215
216
217
218
219

220
221
222
223
224
225
226
...
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_MAX_ATTACHED=125
  }







  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
................................................................................
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Extra-Robustness"        test
    "Device-Two"              test
    "No-lookaside"            test
    "Devkit"                  test
    "Sanitize"                {QUICKTEST_OMIT=func4.test,nan.test test}

    "Valgrind"                valgrindtest
    "Default"                 "threadtest fulltest"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Devkit"                  test
    "Have-Not"                test
................................................................................
    incr NTEST
    run_test_suite $zConfig $target $config_options

    # If the configuration included the SQLITE_DEBUG option, then remove
    # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
    # add it and run veryquick.test.
    if {$target!="checksymbols" && $target!="valgrindtest"
           && !$::BUILDONLY && $::QUICK<2} {
      set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
      set xtarget $target
      regsub -all {fulltest[a-z]*} $xtarget test xtarget

      if {$debug_idx < 0} {
        incr NTEST
        append config_options " -DSQLITE_DEBUG=1"
        run_test_suite "${zConfig}_debug" $xtarget $config_options
      } else {
        incr NTEST
        regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options







>
>
>
>
>
>
>







 







>







 







|



>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_MAX_ATTACHED=125
  }
  "Fast-One" {
    -O6
    -DSQLITE_ENABLE_FTS4=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_MAX_ATTACHED=125
  }
  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
................................................................................
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Extra-Robustness"        test
    "Device-Two"              test
    "No-lookaside"            test
    "Devkit"                  test
    "Sanitize"                {QUICKTEST_OMIT=func4.test,nan.test test}
    "Fast-One"                fuzzoomtest
    "Valgrind"                valgrindtest
    "Default"                 "threadtest fulltest"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Devkit"                  test
    "Have-Not"                test
................................................................................
    incr NTEST
    run_test_suite $zConfig $target $config_options

    # If the configuration included the SQLITE_DEBUG option, then remove
    # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
    # add it and run veryquick.test.
    if {$target!="checksymbols" && $target!="valgrindtest"
           && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
      set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
      set xtarget $target
      regsub -all {fulltest[a-z]*} $xtarget test xtarget
      regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
      if {$debug_idx < 0} {
        incr NTEST
        append config_options " -DSQLITE_DEBUG=1"
        run_test_suite "${zConfig}_debug" $xtarget $config_options
      } else {
        incr NTEST
        regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options

Changes to tool/fuzzershell.c.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
80
81
82
83
84
85
86







87
88
89
90
91
92
93
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
...
638
639
640
641
642
643
644
645
646

647


648
649
650
651
652
653
654


655
656
657
658
659
660
661
...
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
**    (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
................................................................................
** 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>
#include <stdarg.h>
#include <ctype.h>
#include "sqlite3.h"
................................................................................
  int nOomFault;                   /* Increments for each OOM fault */
  int bOomOnce;                    /* Fail just once if true */
  int bOomEnable;                  /* True to enable OOM simulation */
  int nOomBrkpt;                   /* Number of calls to oomFault() */
  char zTestName[100];             /* Name of current test */
} 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 */
}
................................................................................
  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;
      }
................................................................................
      zIn[iNext] = cSaved;
      continue;
    }
    zSql = &zIn[i];
    if( verboseFlag ){
      printf("INPUT (offset: %d, size: %d): [%s]\n",
              i, (int)strlen(&zIn[i]), &zIn[i]);
      fflush(stdout);
    }else if( multiTest && !quietFlag ){

      int pct = oomFlag ? 100*iNext/nIn : ((10*iNext)/nIn)*10;


      if( pct!=lastPct ){
        if( lastPct<0 ) printf("fuzz test:");
        printf(" %d%%", pct);
        fflush(stdout);
        lastPct = pct;
      }
    }


    switch( iMode ){
      case FZMODE_Glob:
        zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
        break;
      case FZMODE_Printf:
        zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
        break;
................................................................................
      if( rc ){
        abendError("sqlite3_close() failed with rc=%d", rc);
      }
      if( sqlite3_memory_used()>0 ){
        abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
      }
      if( oomFlag ){
        if( g.nOomFault==0 || oomCnt>2000 ){
          if( g.bOomOnce ){
            oomCnt = g.iOomCntdown = 1;
            g.bOomOnce = 0;
          }else{
            oomCnt = 0;
          }
        }else{
................................................................................
        /* If TEST_FAILURE is something other than 5, just exit the test
        ** early */
        printf("\nExit early due to TEST_FAILURE being set");
        break;
      }
    }
  }
  if( !verboseFlag && multiTest && !quietFlag ) printf("\n");
  if( nTest>1 && !quietFlag ){
    printf("%d fuzz tests with no errors\nSQLite %s %s\n",
           nTest, sqlite3_libversion(), sqlite3_sourceid());
  }
  if( zDataOut ){
    int n = 0;
    FILE *out = fopen(zDataOut, "wb");







|
|







 







<







 







>
>
>
>
>
>
>







 







|







 







<

>
|
>
>
|
|
|
<
|
|
|
>
>







 







|







 







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
56
57
58
59
60
61
62

63
64
65
66
67
68
69
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
...
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669
670
...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
**    (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
................................................................................
** 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>
#include <stdarg.h>
#include <ctype.h>
#include "sqlite3.h"
................................................................................
  int nOomFault;                   /* Increments for each OOM fault */
  int bOomOnce;                    /* Fail just once if true */
  int bOomEnable;                  /* True to enable OOM simulation */
  int nOomBrkpt;                   /* Number of calls to oomFault() */
  char zTestName[100];             /* Name of current test */
} g;

/*
** Maximum number of iterations for an OOM test
*/
#ifndef OOM_MAX
# define OOM_MAX 1000
#endif

/*
** 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 */
}
................................................................................
  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]) - 12, &zIn[i+6]);
        if( verboseFlag ){
          printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
          fflush(stdout);
        }
        i += (int)(z-&zIn[i]);
        multiTest = 1;
      }
................................................................................
      zIn[iNext] = cSaved;
      continue;
    }
    zSql = &zIn[i];
    if( verboseFlag ){
      printf("INPUT (offset: %d, size: %d): [%s]\n",
              i, (int)strlen(&zIn[i]), &zIn[i]);

    }else if( multiTest && !quietFlag ){
      if( oomFlag ){
        printf("%s\n", g.zTestName);
      }else{
        int pct = (10*iNext)/nIn;
        if( pct!=lastPct ){
          if( lastPct<0 ) printf("fuzz test:");
          printf(" %d%%", pct*10);

          lastPct = pct;
        }
      }
    }
    fflush(stdout);
    switch( iMode ){
      case FZMODE_Glob:
        zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
        break;
      case FZMODE_Printf:
        zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
        break;
................................................................................
      if( rc ){
        abendError("sqlite3_close() failed with rc=%d", rc);
      }
      if( sqlite3_memory_used()>0 ){
        abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
      }
      if( oomFlag ){
        if( g.nOomFault==0 || oomCnt>OOM_MAX ){
          if( g.bOomOnce ){
            oomCnt = g.iOomCntdown = 1;
            g.bOomOnce = 0;
          }else{
            oomCnt = 0;
          }
        }else{
................................................................................
        /* If TEST_FAILURE is something other than 5, just exit the test
        ** early */
        printf("\nExit early due to TEST_FAILURE being set");
        break;
      }
    }
  }
  if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
  if( nTest>1 && !quietFlag ){
    printf("%d fuzz tests with no errors\nSQLite %s %s\n",
           nTest, sqlite3_libversion(), sqlite3_sourceid());
  }
  if( zDataOut ){
    int n = 0;
    FILE *out = fopen(zDataOut, "wb");