/ Check-in [13b786da]
Login

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

Overview
Comment:Add tests cases for the zipfile extension.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 13b786dafd308b7aef42328f26fe64981c83d524e4bf82ceb7d58afc7146c7d3
User & Date: dan 2018-01-30 17:43:22
Context
2018-01-30
18:33
If a virtual table xColumn method sets an error message using sqlite3_result_error(), use that message in preference to any error message left in the sqlite3_vtab object. check-in: 71e3b715 user: dan tags: trunk
17:43
Add tests cases for the zipfile extension. check-in: 13b786da user: dan tags: trunk
14:07
Prevent users from creating zipfile() virtual tables without an argument. check-in: 81fdbe0c user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

    44     44   #include <errno.h>
    45     45   
    46     46   #include <zlib.h>
    47     47   
    48     48   #ifndef SQLITE_OMIT_VIRTUALTABLE
    49     49   
    50     50   #ifndef SQLITE_AMALGAMATION
           51  +
    51     52   typedef sqlite3_int64 i64;
    52     53   typedef unsigned char u8;
    53     54   typedef unsigned short u16;
    54     55   typedef unsigned long u32;
    55     56   #define MIN(a,b) ((a)<(b) ? (a) : (b))
           57  +
           58  +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
           59  +# define ALWAYS(X)      (1)
           60  +# define NEVER(X)       (0)
           61  +#elif !defined(NDEBUG)
           62  +# define ALWAYS(X)      ((X)?1:(assert(0),0))
           63  +# define NEVER(X)       ((X)?(assert(0),1):0)
           64  +#else
           65  +# define ALWAYS(X)      (X)
           66  +# define NEVER(X)       (X)
    56     67   #endif
           68  +
           69  +#endif   /* SQLITE_AMALGAMATION */
    57     70   
    58     71   static const char ZIPFILE_SCHEMA[] = 
    59     72     "CREATE TABLE y("
    60     73       "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
    61     74       "mode,"              /* 1: POSIX mode for file */
    62     75       "mtime,"             /* 2: Last modification time (secs since 1970)*/
    63     76       "sz,"                /* 3: Size of object */
................................................................................
   279    292   /*
   280    293   ** If string zIn is quoted, dequote it in place. Otherwise, if the string
   281    294   ** is not quoted, do nothing.
   282    295   */
   283    296   static void zipfileDequote(char *zIn){
   284    297     char q = zIn[0];
   285    298     if( q=='"' || q=='\'' || q=='`' || q=='[' ){
   286         -    char c;
   287    299       int iIn = 1;
   288    300       int iOut = 0;
   289    301       if( q=='[' ) q = ']';
   290         -    while( (c = zIn[iIn++]) ){
   291         -      if( c==q ){
   292         -        if( zIn[iIn++]!=q ) break;
   293         -      }
          302  +    while( ALWAYS(zIn[iIn]) ){
          303  +      char c = zIn[iIn++];
          304  +      if( c==q && zIn[iIn++]!=q ) break;
   294    305         zIn[iOut++] = c;
   295    306       }
   296    307       zIn[iOut] = '\0';
   297    308     }
   298    309   }
   299    310   
   300    311   /*
................................................................................
   441    452   static int zipfileClose(sqlite3_vtab_cursor *cur){
   442    453     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
   443    454     ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
   444    455     ZipfileCsr **pp;
   445    456     zipfileResetCursor(pCsr);
   446    457   
   447    458     /* Remove this cursor from the ZipfileTab.pCsrList list. */
   448         -  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
   449         -    if( *pp==pCsr ){ 
   450         -      *pp = pCsr->pCsrNext;
   451         -      break;
   452         -    }
   453         -  }
          459  +  for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
          460  +  *pp = pCsr->pCsrNext;
   454    461   
   455    462     sqlite3_free(pCsr);
   456    463     return SQLITE_OK;
   457    464   }
   458    465   
   459    466   /*
   460    467   ** Set the error message for the virtual table associated with cursor
................................................................................
   869    876   ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
   870    877   ** size is nOut bytes. This function uncompresses the data and sets the
   871    878   ** return value in context pCtx to the result (a blob).
   872    879   **
   873    880   ** If an error occurs, an error code is left in pCtx instead.
   874    881   */
   875    882   static void zipfileInflate(
   876         -  sqlite3_context *pCtx,          /* Store error here, if any */
          883  +  sqlite3_context *pCtx,          /* Store result here */
   877    884     const u8 *aIn,                  /* Compressed data */
   878    885     int nIn,                        /* Size of buffer aIn[] in bytes */
   879    886     int nOut                        /* Expected output size */
   880    887   ){
   881    888     u8 *aRes = sqlite3_malloc(nOut);
   882    889     if( aRes==0 ){
   883    890       sqlite3_result_error_nomem(pCtx);
................................................................................
  1115   1122       pEOCD->iFirstDisk = zipfileRead16(aRead);
  1116   1123       pEOCD->nEntry = zipfileRead16(aRead);
  1117   1124       pEOCD->nEntryTotal = zipfileRead16(aRead);
  1118   1125       pEOCD->nSize = zipfileRead32(aRead);
  1119   1126       pEOCD->iOffset = zipfileRead32(aRead);
  1120   1127     }
  1121   1128   
  1122         -  return SQLITE_OK;
         1129  +  return rc;
  1123   1130   }
  1124   1131   
  1125   1132   /*
  1126   1133   ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry 
  1127   1134   ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
  1128   1135   ** to the end of the list. Otherwise, it is added to the list immediately
  1129   1136   ** before pBefore (which is guaranteed to be a part of said list).

Added test/zipfile2.test.

            1  +# 2018 January 30
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +set testprefix zipfile2
           16  +
           17  +ifcapable !vtab {
           18  +  finish_test; return
           19  +}
           20  +if {[catch {load_static_extension db zipfile} error]} {
           21  +  puts "Skipping zipfile2 tests, hit load error: $error"
           22  +  finish_test; return
           23  +}
           24  +
           25  +proc blobliteral {str} {
           26  +  set concat [string map {" " "" "\n" ""} $str]
           27  +  return "X'$concat'"
           28  +}
           29  +
           30  +proc blob {str} {
           31  +  binary decode hex $str
           32  +}
           33  +
           34  +proc findall {needle haystack} {
           35  +  set L [list]
           36  +  set start 0
           37  +  while { [set idx [string first $needle $haystack $start]]>=0 } {
           38  +    lappend L $idx
           39  +    set start [expr $idx+1]
           40  +  }
           41  +  set L
           42  +}
           43  +
           44  +do_execsql_test 1.0 {
           45  +  CREATE VIRTUAL TABLE aaa USING zipfile('testzip');
           46  +  CREATE VIRTUAL TABLE bbb USING zipfile("testzip");
           47  +  CREATE VIRTUAL TABLE ccc USING zipfile(`testzip`);
           48  +  CREATE VIRTUAL TABLE ddd USING zipfile([testzip]);
           49  +  CREATE VIRTUAL TABLE eee USING zipfile(testzip);
           50  +  CREATE VIRTUAL TABLE fff USING zipfile('test''zip');
           51  +}
           52  +
           53  +do_test 2.0 {
           54  +  forcedelete testdir
           55  +  file mkdir testdir
           56  +  execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') }
           57  +  catchsql { SELECT * FROM hhh } 
           58  +} {1 {error in fread()}}
           59  +
           60  +
           61  +set archive {
           62  +  504B0304140000080000D4A52BEC09F3B6E0110000001100000005000900612E
           63  +  747874555405000140420F00636F6E74656E7473206F6620612E747874504B03
           64  +  04140000080000D4A52BECD98916A7110000001100000005000900622E747874
           65  +  555405000140420F00636F6E74656E7473206F6620622E747874504B01021E03
           66  +  140000080000D4A52BEC09F3B6E0110000001100000005000900000000000000
           67  +  0000A48100000000612E747874555405000140420F00504B01021E0314000008
           68  +  0000D4A52BECD98916A71100000011000000050009000000000000000000A481
           69  +  3D000000622E747874555405000140420F00504B050600000000020002007800
           70  +  00007A0000000000
           71  +}
           72  +
           73  +do_execsql_test 3.1 {
           74  +  WITH contents(name,mtime,data) AS (
           75  +    VALUES('a.txt', 1000000, 'contents of a.txt') UNION ALL
           76  +    VALUES('b.txt', 1000000, 'contents of b.txt')
           77  +  ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
           78  +} [blobliteral $archive]
           79  +
           80  +set blob [blob $archive]
           81  +do_execsql_test 3.2 {
           82  +  SELECT name,mtime,data FROM zipfile($blob)
           83  +} {
           84  +  a.txt 1000000 {contents of a.txt} 
           85  +  b.txt 1000000 {contents of b.txt}
           86  +}
           87  +
           88  +# Corrupt each of the 0x50 0x4B (ascii "PK") headers in the file
           89  +# Test that in each case this causes an error.
           90  +#
           91  +set L [findall 504B $archive]
           92  +for {set i 0} {$i < [llength $L]} {incr i} {
           93  +  set idx [lindex $L $i]
           94  +  set a [string replace $archive $idx [expr $idx+3] 0000]
           95  +  set blob [blob $a]
           96  +  do_catchsql_test 3.3.$i {
           97  +    SELECT name,mtime,data FROM zipfile($blob)
           98  +  } {/1 .*/}
           99  +}
          100  +
          101  +set L [findall 5554 $archive]
          102  +for {set i 0} {$i < [llength $L]} {incr i} {
          103  +  set idx [lindex $L $i]
          104  +  set a [string replace $archive $idx [expr $idx+3] 1234]
          105  +  set blob [blob $a]
          106  +  do_execsql_test 3.4.$i {
          107  +    SELECT name,data FROM zipfile($blob)
          108  +  } {
          109  +    a.txt {contents of a.txt} 
          110  +    b.txt {contents of b.txt}
          111  +  }
          112  +}
          113  +
          114  +for {set i 0} {$i < [llength $L]} {incr i} {
          115  +  set idx [lindex $L $i]
          116  +  set a [string replace $archive [expr $idx+8] [expr $idx+9] 00]
          117  +  set blob [blob $a]
          118  +  do_execsql_test 3.5.$i {
          119  +    SELECT name,data FROM zipfile($blob)
          120  +  } {
          121  +    a.txt {contents of a.txt} 
          122  +    b.txt {contents of b.txt}
          123  +  }
          124  +}
          125  +
          126  +if 0 {
          127  +set blob [db one {
          128  +  WITH contents(name,mtime,data) AS (
          129  +    VALUES('a.txt', 1000000, 'aaaaaaaaaaaaaaaaaaaaaaa')
          130  +  ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
          131  +}]
          132  +set blob [string range $blob 2 end]
          133  +set blob [string range $blob 0 end-1]
          134  +while {[string length $blob]>0} {
          135  +  puts [string range $blob 0 63]
          136  +  set blob [string range $blob 64 end]
          137  +}
          138  +exit
          139  +}
          140  +
          141  +set archive2 {
          142  +  504B0304140000080800D4A52BEC08F54C6E050000001700000005000900612E
          143  +  747874555405000140420F004B4CC40A00504B01021E03140000080800D4A52B
          144  +  EC08F54C6E0500000017000000050009000000000000000000A4810000000061
          145  +  2E747874555405000140420F00504B050600000000010001003C000000310000
          146  +  000000
          147  +}
          148  +set blob [blob $archive2]
          149  +do_execsql_test 4.0 {
          150  +  SELECT name,mtime,data,method FROM zipfile($blob)
          151  +} {
          152  +  a.txt 1000000 aaaaaaaaaaaaaaaaaaaaaaa 8
          153  +}
          154  +
          155  +breakpoint
          156  +set L [findall 17000000 $archive2]
          157  +set a $archive2
          158  +foreach i $L { set a [string replace $a $i [expr $i+7] 16000000] }
          159  +set blob [blob $a]
          160  +do_catchsql_test 4.1 {
          161  +  SELECT name,mtime,data,method FROM zipfile($blob)
          162  +} {1 {SQL logic error}}
          163  +
          164  +
          165  +
          166  +finish_test
          167  +

Added test/zipfilefault.test.

            1  +# 2018 January 30
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +source $testdir/malloc_common.tcl
           16  +set testprefix zipfilefault
           17  +
           18  +ifcapable !vtab {
           19  +  finish_test; return
           20  +}
           21  +if {[catch {load_static_extension db zipfile} error]} {
           22  +  puts "Skipping zipfile2 tests, hit load error: $error"
           23  +  finish_test; return
           24  +}
           25  +
           26  +faultsim_save_and_close
           27  +do_faultsim_test 1 -prep {
           28  +  faultsim_restore_and_reopen
           29  +  load_static_extension db zipfile
           30  +  execsql { DROP TABLE IF EXISTS aaa }
           31  +} -body {
           32  +  execsql { CREATE VIRTUAL TABLE aaa USING zipfile('test.zip') }
           33  +} -test {
           34  +  faultsim_test_result {0 {}} 
           35  +}
           36  +
           37  +forcedelete test.zip
           38  +sqlite3 db test.db
           39  +load_static_extension db zipfile
           40  +do_execsql_test 2.0 {
           41  +  CREATE VIRTUAL TABLE setup USING zipfile('test.zip');
           42  +  INSERT INTO setup(name, data) VALUES('a.txt', '1234567890');
           43  +}
           44  +
           45  +do_faultsim_test 2 -faults oom* -body {
           46  +  execsql { SELECT name,data FROM zipfile('test.zip') }
           47  +} -test {
           48  +  faultsim_test_result {0 {a.txt 1234567890}} 
           49  +}
           50  +
           51  +forcedelete test.zip
           52  +reset_db
           53  +load_static_extension db zipfile
           54  +do_execsql_test 3.0 {
           55  +  CREATE VIRTUAL TABLE setup USING zipfile('test.zip');
           56  +  INSERT INTO setup(name, data) VALUES('a.txt', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa');
           57  +}
           58  +
           59  +do_faultsim_test 2 -faults oom* -body {
           60  +  execsql { SELECT name,data FROM zipfile('test.zip') }
           61  +} -test {
           62  +  faultsim_test_result {0 {a.txt aaaaaaaaaaaaaaaaaaaaaaaaaaaa}} 
           63  +}
           64  +
           65  +
           66  +finish_test
           67  +