u32 iHash = zonefileKeyHash(zDb, zTab, iFileid);
for(pKey=pGlobal->aHash[iHash%pGlobal->nHash]; pKey; pKey=pKey->pHashNext){
if( pKey->iFileid==iFileid
- && 0==sqlite3_stricmp(zDb, pKey->zDb)
&& 0==sqlite3_stricmp(zTab, pKey->zName)
+ && 0==sqlite3_stricmp(zDb, pKey->zDb)
){
*pzKey = pKey->zKey;
return pKey->nKey;
static int zonefileCompareValue(sqlite3_value *p1, sqlite3_value *p2){
int eType;
assert( p1 );
- if( p2==0 ) return 1;
eType = sqlite3_value_type(p1);
if( sqlite3_value_type(p2)!=eType ) return 1;
switch( eType ){
}
}
- *pzErr = sqlite3_mprintf("unknown encryption type: %s", zName);
+ *pzErr = sqlite3_mprintf("unknown encryption method: %s", zName);
return SQLITE_ERROR;
}
ZonefileBuffer *pFrom /* Input buffer */
){
int rc = SQLITE_OK;
- if( pFrom->n ){
- int nNonce = pCodec ? zonefileCodecNonceSize(pCodec) : 0;
- int nOrig = pTo->n;
- if( pMethod->eType==ZONEFILE_COMPRESSION_NONE ){
- if( zonefileBufferGrow(pCtx, pTo, pFrom->n + nNonce) ){
- rc = SQLITE_ERROR;
- }else{
- zonefileAppendBlob(pTo, pFrom->a, pFrom->n);
- }
+ int nNonce = pCodec ? zonefileCodecNonceSize(pCodec) : 0;
+ int nOrig = pTo->n;
+ if( pMethod->eType==ZONEFILE_COMPRESSION_NONE ){
+ if( zonefileBufferGrow(pCtx, pTo, pFrom->n + nNonce) ){
+ rc = SQLITE_ERROR;
}else{
- int nReq = pMethod->xCompressBound(pCmp, pFrom->n);
- if( zonefileBufferGrow(pCtx, pTo, nReq + nNonce) ) return SQLITE_ERROR;
- rc = pMethod->xCompress(pCmp, &pTo->a[pTo->n], &nReq, pFrom->a, pFrom->n);
- pTo->n += nReq;
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ zonefileAppendBlob(pTo, pFrom->a, pFrom->n);
}
+ }else{
+ int nReq = pMethod->xCompressBound(pCmp, pFrom->n);
+ if( zonefileBufferGrow(pCtx, pTo, nReq + nNonce) ) return SQLITE_ERROR;
+ rc = pMethod->xCompress(pCmp, &pTo->a[pTo->n], &nReq, pFrom->a, pFrom->n);
+ pTo->n += nReq;
+ }
- /* Encrypt the data just appended to buffer pTo. */
- if( pCodec ){
- zonefileCodecEncode(pCodec, &pTo->a[nOrig], pTo->n - nOrig);
- pTo->n += nNonce;
- }
+ /* Encrypt the data just appended to buffer pTo. */
+ if( rc==SQLITE_OK && pCodec ){
+ zonefileCodecEncode(pCodec, &pTo->a[nOrig], pTo->n - nOrig);
+ pTo->n += nNonce;
}
- return SQLITE_OK;
+ return rc;
}
/*
break;
case 1: /* ekey */
break;
- case 2: { /* header */
+ default: {
const char *zFile = (const char*)sqlite3_column_text(pCsr->pSelect, 0);
zonefileJsonHeader(ctx, zFile);
+ assert( i==2 );
break;
}
}
rc = SQLITE_NOMEM;
}else{
rc = pMethod->xUncompress(pCmp, aOut, nOut, aIn, nIn);
- if( rc ){
- sqlite3_free(aOut);
- aOut = 0;
- }
+ }
+ if( rc ){
+ sqlite3_free(aOut);
+ aOut = 0;
}
*paOut = aOut;
SELECT zonefile_write('test.zonefile', 'bb', json_group_object(n,v)) FROM p;
} {1 {compressor "zstd_global_dict" may not be used to compress the zonefile index}}
}
-# puts $COMPRESSION_METHODS
set extra_header 0
set cachesize 0
SELECT quote(dd.v)==quote(cc.v) FROM cc JOIN dd USING (k)
} {1 1 1}
+close [open test.zonefile w+]
+do_catchsql_test 3.4 {
+ SELECT header FROM cc_files
+} {1 {failed to read header from file: "test.zonefile"}}
+
+forcedelete test.zonefile
+do_catchsql_test 3.5 {
+ SELECT header FROM cc_files
+} {1 {failed to open file "test.zonefile" for reading}}
+
+do_execsql_test 3.6 {
+ SELECT ekey FROM cc_files
+} {{}}
+
+#-------------------------------------------------------------------------
+# Check that a file that uses an unknown compression method is handled
+# correctly (an error is returned).
+#
+reset_db
+load_static_extension db zonefile
+do_execsql_test 4.0 {
+ CREATE TABLE dd(k INTEGER PRIMARY KEY, frame INTEGER, idx INTEGER, v BLOB);
+ INSERT INTO dd VALUES(1000, 1, -1, randomblob(44));
+ INSERT INTO dd VALUES(1001, 1, -1, randomblob(55));
+ INSERT INTO dd VALUES(1002, 2, -1, randomblob(66));
+ SELECT zonefile_write('test.zonefile', 'dd');
+ CREATE VIRTUAL TABLE x1 USING zonefile;
+} {{}}
+
+do_test 4.1 {
+ hexio_write test.zonefile 5 77
+} {1}
+do_execsql_test 4.2 {
+ INSERT INTO x1_files(filename) VALUES('test.zonefile');
+} {}
+do_catchsql_test 4.3 {
+ SELECT * FROM x1
+} {1 {unsupported compression method: 119}}
+do_test 4.4 {
+ hexio_write test.zonefile 4 77
+} {1}
+do_catchsql_test 4.5 {
+ DELETE FROM x1_files;
+ INSERT INTO x1_files(filename) VALUES('test.zonefile');
+} {1 {unsupported compression method: 119}}
+
+do_test 4.6 {
+ hexio_write test.zonefile 0 00
+} {1}
+do_catchsql_test 4.7 {
+ INSERT INTO x1_files(filename) VALUES('test.zonefile');
+} {1 {failed to read zonefile header from file "test.zonefile"}}
+
+#-------------------------------------------------------------------------
+# Test using various types in the "frame" field of an input table.
+#
+reset_db
+load_static_extension db zonefile
+if {[lsearch $COMPRESSION_METHODS zlib]>=0} {
+ do_execsql_test 5.0 {
+ CREATE TABLE "a b"(k INTEGER PRIMARY KEY,frame INTEGER,idx INTEGER,v BLOB);
+ INSERT INTO "a b" VALUES(1, 0.5, -1, randomblob(44));
+ INSERT INTO "a b" VALUES(2, 0.5, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(3, 1.5, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(4, 1.5, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(5, 2, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(6, 2, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(7, 200, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(8, 200, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(9, 300, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(10, 300, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(11, NULL, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(12, NULL, -1, randomblob(55));
+ INSERT INTO "a b" VALUES(13, 'f1', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(14, 'f1', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(15, 'frame2', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(16, 'frame2', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(17, x'1234', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(18, x'1234', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(19, x'abcd', -1, randomblob(55));
+ INSERT INTO "a b" VALUES(20, x'abcd', -1, randomblob(55));
+
+ SELECT zonefile_write('test.zonefile', 'a b',
+ '{"compressionTypeContent":"zlib"}'
+ );
+ } {{}}
+
+ do_execsql_test 5.1 {
+ CREATE VIRTUAL TABLE abc USING zonefile;
+ INSERT INTO abc_files(filename) VALUES('test.zonefile');
+ SELECT group_concat(k) FROM abc_shadow_idx GROUP BY fofst
+ } {
+ 11,12 1,2 3,4 5,6 7,8
+ 9,10 13,14 15,16 17,18 19,20
+ }
+}
+
+do_execsql_test 6.0 {
+ CREATE TABLE "ab"(k INTEGER PRIMARY KEY,frame INTEGER,idx INTEGER,v BLOB);
+ INSERT INTO "ab" VALUES(1, 0.5, -1, randomblob(44));
+ INSERT INTO "ab" VALUES(2, 0.5, -1, randomblob(55));
+ INSERT INTO "ab" VALUES(3, 1.5, -1, randomblob(55));
+ INSERT INTO "ab" VALUES(4, 1.5, -1, randomblob(55));
+}
+do_catchsql_test 6.1.1 {
+ SELECT zonefile_write('test.zonefile', 'ab',
+ '{"debugExtendedHeaderSize":-1}'
+ );
+} {1 {debugExtendedHeaderSize value out of range: -1}}
+do_catchsql_test 6.1.2 {
+ SELECT zonefile_write('test.zonefile', 'ab',
+ '{"debugExtendedHeaderSize":256}'
+ );
+} {1 {debugExtendedHeaderSize value out of range: 256}}
+
+do_catchsql_test 6.2 {
+ SELECT zonefile_write('test.zonefile', 'ab',
+ '{"unknown":256}'
+ );
+} {1 {unknown parameter name: "unknown"}}
+
+forcedelete test.dir
+file mkdir test.dir
+do_catchsql_test 6.3 {
+ SELECT zonefile_write('test.dir', 'ab');
+} {1 {failed to open file "test.dir" for writing}}
+
+do_catchsql_test 6.4 {
+ CREATE VIRTUAL TABLE zzz USING zonefile;
+ INSERT INTO zzz_files(filename) VALUES('nosuchfile.zonefile');
+} {1 {failed to open file "nosuchfile.zonefile" for reading}}
+
+do_catchsql_test 6.4 {
+ INSERT INTO zzz_files(filename) VALUES('test.dir');
+} {1 {failed to read zonefile header from file "test.dir"}}
+
+#-------------------------------------------------------------------------
+# Check that errors generated when building a dictionary are handled.
+# The zstd library routines for building a dictionary throw an error
+# if they are provided with too little data.
+#
+# Also test that zstd_global_dict cannot be used to compress the zonefile
+# index (as there is nowhere in the file format to store the dictionary
+# for this compression).
+#
+reset_db
+load_static_extension db zonefile
+if {[lsearch $COMPRESSION_METHODS zstd_global_dict]>=0} {
+ do_execsql_test 7.0 {
+ CREATE TABLE "ab"(k INTEGER PRIMARY KEY,frame INTEGER,idx INTEGER,v BLOB);
+ INSERT INTO "ab" VALUES(1, -1, -1, 'abc');
+ }
+
+ do_catchsql_test 7.1 {
+ SELECT zonefile_write('test.zonefile', 'ab',
+ '{"compressionTypeContent":"zstd_global_dict"}'
+ );
+ } {1 {error generating dictionary}}
+
+ do_catchsql_test 7.2 {
+ SELECT zonefile_write('test.zonefile', 'ab',
+ '{"compressionTypeIndexData":"zstd_global_dict"}'
+ );
+ } {1 {compressor "zstd_global_dict" may not be used to compress the zonefile index}}
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+load_static_extension db zonefile
+do_catchsql_test 8.1 {
+ CREATE VIRTUAL TABLE one USING zonefile_files;
+} {1 {do not create zonefile_files tables directly!}}
+do_catchsql_test 8.2 {
+ CREATE VIRTUAL TABLE onetwothree USING zonefile_files;
+} {1 {do not create zonefile_files tables directly!}}
finish_test
}
} {}
-do_test 1.2 {
- execsql {
- CREATE VIRTUAL TABLE gg USING zonefile;
- }
- for {set i 0} {$i < $nFile} {incr i} {
- execsql {
- INSERT INTO gg_files(filename) VALUES('test' || $i || '.zonefile')
- }
- }
-} {}
+proc k {i} { lindex $::K [expr $i % [llength $::K]] }
+db func k k
+
+do_execsql_test 1.2 {
+ CREATE VIRTUAL TABLE gg USING zonefile;
+}
+for {set i 0} {$i < $nFile} {incr i} {
+ do_execsql_test 1.2.$i {
+ INSERT INTO gg_files(filename, ekey)
+ VALUES('test' || $i || '.zonefile', k($i));
+ SELECT count(*) FROM rr JOIN gg USING(k) WHERE rr.v!=gg.v;
+ } 0
+}
+
+db close
+sqlite3 db test.db
+load_static_extension db zonefile
+db func k k
do_catchsql_test 1.3 {
SELECT count(*) FROM rr JOIN gg USING(k) WHERE rr.v!=gg.v;
SELECT count(*) FROM rr JOIN gg USING(k) WHERE rr.v!=gg.v;
} {1 {missing encryption key for file "test1.zonefile"}}
-proc k {i} {
- lindex $::K [expr $i % [llength $::K]]
-}
-db func k k
do_execsql_test 1.6 {
UPDATE gg_files SET ekey = k(rowid-1);
}
3 AES_256_CTR 3
4 Aes_256_CBC 4
} {
- do_catchsql_test 2.$tn {
+ do_catchsql_test 2.1.$tn {
WITH p(n,v) AS (
VALUES('encryptionType', $alg) UNION ALL
VALUES('encryptionKey', 'secret')
} "1 {unsupported encryption method: $id}"
}
+foreach {tn alg} {
+ 1 nosuchmethod!
+} {
+ do_catchsql_test 2.1.$tn {
+ WITH p(n,v) AS (
+ VALUES('encryptionType', $alg) UNION ALL
+ VALUES('encryptionKey', 'secret')
+ )
+ SELECT zonefile_write('test' || $i || '.zonefile', 'zz',
+ json_group_object(n, v)
+ ) FROM p;
+ } "1 {unknown encryption method: $alg}"
+}
+
+#-------------------------------------------------------------------------
+# Test some hash collisions in the encryption key table.
+#
+
+# This is the same hash function used internally to store keys.
+#
+proc hash {zDb zTab iFile} {
+ binary scan $zDb c* A
+ binary scan $zTab c* B
+ set h 0
+ foreach i $A { set h [expr ($h + ($h << 3) + $i) & 0xFFFFFFFF] }
+ foreach i $B { set h [expr ($h + ($h << 3) + $i) & 0xFFFFFFFF] }
+ return [expr $h ^ $iFile]
+}
+
+do_test 3.0 {
+ set h1 [expr [hash main zone 1] % 512]
+ for {set i 0} {1} {incr i} {
+ set h2 [expr [hash "aux$i" zone 1] % 512]
+ if {$h1==$h2} break
+ }
+ set i
+} 52
+
+reset_db
+load_static_extension db zonefile
+forcedelete test.db2
+
+do_execsql_test 3.1 {
+ CREATE TABLE zz(k INTEGER PRIMARY KEY, frame INTEGER, idx INTEGER, v BLOB);
+ INSERT INTO zz VALUES(222, -1, -1, randomblob(60));
+ WITH p(n,v) AS (
+ VALUES('encryptionType', 'xor') UNION ALL
+ VALUES('encryptionKey', 'pass')
+ )
+ SELECT zonefile_write('test1.zonefile', 'zz',
+ json_group_object(n, v)
+ ) FROM p;
+
+ DELETE FROM zz;
+ INSERT INTO zz VALUES(333, -1, -1, randomblob(80));
+ WITH p(n,v) AS (
+ VALUES('encryptionType', 'xor') UNION ALL
+ VALUES('encryptionKey', 'pass')
+ )
+ SELECT zonefile_write('test2.zonefile', 'zz',
+ json_group_object(n, v)
+ ) FROM p;
+} {{} {}}
+
+do_execsql_test 3.2 {
+ ATTACH 'test.db2' AS aux52;
+ CREATE VIRTUAL TABLE main.zone USING zonefile;
+ CREATE VIRTUAL TABLE aux52.zone USING zonefile;
+ INSERT INTO main.zone_files(filename, ekey) VALUES('test1.zonefile', 'pass');
+ INSERT INTO aux52.zone_files(filename, ekey) VALUES('test2.zonefile', 'pass');
+}
+
+do_execsql_test 3.3 {
+ SELECT v IS NULL FROM main.zone;
+ SELECT v IS NULL FROM aux52.zone;
+} {0 0}
+
+do_test 3.4 {
+ set h1 [expr [hash main zone 1] % 512]
+ for {set i 0} {1} {incr i} {
+ set h2 [expr [hash "aux$i" zone 2] % 512]
+ if {$h1==$h2} break
+ }
+ set i
+} 682
+
+forcedelete test.db3
+do_execsql_test 3.5 {
+ ATTACH 'test.db3' AS aux682;
+ CREATE VIRTUAL TABLE aux682.zone USING zonefile;
+ INSERT INTO aux682.zone_files(filename, ekey) VALUES('test1.zonefile','pass');
+ INSERT INTO aux682.zone_files(filename, ekey) VALUES('test2.zonefile','pass');
+ INSERT INTO main.zone_files(filename, ekey) VALUES('test2.zonefile','pass');
+}
+
+do_execsql_test 3.6 {
+ SELECT v IS NULL FROM main.zone;
+ SELECT v IS NULL FROM aux682.zone;
+ SELECT v IS NULL FROM main.zone;
+} {0 0 0 0 0 0}
+
+
finish_test
}
}
+do_execsql_test 1.3.0 { UPDATE tt SET frame = NULL; }
+do_faultsim_test 1.3 -faults oom* -prep {
+ sqlite3 db test.db
+ load_static_extension db zonefile
+} -body {
+ execsql {
+ SELECT zonefile_write('test.zonefile', 'tt');
+ }
+} -test {
+ faultsim_test_result {0 {{}}}
+}
+
+do_execsql_test 1.4.0 {
+ INSERT INTO tt VALUES(5, -1, -1, randomblob(100));
+ INSERT INTO tt VALUES(6, -1, -1, randomblob(100));
+ INSERT INTO tt VALUES(7, -1, -1, randomblob(100));
+ INSERT INTO tt VALUES(8, -1, -1, randomblob(100));
+ INSERT INTO tt VALUES(9, -1, -1, randomblob(100));
+ CREATE VIRTUAL TABLE ttz USING zonefile;
+}
+if {[catch { db eval $sql }]==0} {
+ faultsim_save_and_close
+ do_faultsim_test 1.4 -faults oom* -prep {
+ faultsim_restore_and_reopen
+ load_static_extension db zonefile
+ } -body {
+ execsql {
+ SELECT zonefile_write('test.zonefile', 'tt',
+ '{"compressionTypeIndexData":"zstd"}'
+ );
+ }
+ } -test {
+ faultsim_test_result {0 {{}}}
+ }
+
+ faultsim_save_and_close
+ do_faultsim_test 1.5 -faults oom* -prep {
+ faultsim_restore_and_reopen
+ load_static_extension db zonefile
+ } -body {
+ execsql {
+ INSERT INTO ttz_files(filename) VALUES('test.zonefile');
+ }
+ } -test {
+ faultsim_test_result {0 {}}
+ }
+}
+
+#-------------------------------------------------------------------------
+#
do_execsql_test 2.0 {
SELECT zonefile_write('test.zonefile', 'tt',
'{"encryptionType":"xor", "encryptionKey":"secret"}'
} {{}}
faultsim_save_and_close
-do_faultsim_test 2 -faults oom* -prep {
+do_faultsim_test 2.1 -faults oom* -prep {
faultsim_restore_and_reopen
load_static_extension db zonefile
} -body {
faultsim_test_result {0 {}}
}
+faultsim_save_and_close
+do_faultsim_test 2.2 -faults oom* -prep {
+ faultsim_restore_and_reopen
+ load_static_extension db zonefile
+} -body {
+ execsql { SELECT json_extract(header, '$.magicNumber') FROM zz_files }
+} -test {
+ faultsim_test_result {0 1179332920}
+}
+
finish_test
-C Fix\sa\sproblem\scausing\sSQLITE_HAVE_LZ4\sbuilds\sof\szonefile\sto\sfail\sunless\nSQLITE_HAVE_ZLIB\sis\salso\sdefined.
-D 2018-02-23T14:09:59.252
+C Add\stest\scases\sand\sminor\sfixes\sfor\sthe\szonefile\smodule.
+D 2018-02-23T19:21:19.664
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in a2d2fb8d17c39ab5ec52beb27850b903949080848236923f436156b72a958737
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F ext/zonefile/README.md df86ef5b4f9aa8b07e1c8124b3f2dcea616927385aad59d525b784f0a06d446c
-F ext/zonefile/zonefile.c f07d553228cf0446e7d2882348a142dd9e9ebc0037402ef058c15b9f2fe2f670
-F ext/zonefile/zonefile1.test c73fb68d6b91e4047ee96915b91fa21c9df4afa23a4d4a259bce154857a35610
-F ext/zonefile/zonefileenc.test f23e16fc8810c95588dfd528af8e4332f0d1d13370fdd7163226ec886715058e
-F ext/zonefile/zonefilefault.test 7f93ba8420d6f6a461d2fbbce30a04f744764f584c0c17361a867db8088f5595
+F ext/zonefile/zonefile.c d14151c34fd9e5c73a4f345a1a2065d80dbf1596d06bf8a6547a12d18c44395d
+F ext/zonefile/zonefile1.test d1b2dcb7c0b8bba1f1fcb735fe1e6335670a23ee78e5ff0cc850e68b5540eb86
+F ext/zonefile/zonefileenc.test 10e770105edeff6a05df6be8db5481eaa8fcda2422ec5446ad21b34ed70d02d7
+F ext/zonefile/zonefilefault.test 4a454959db6568053a6ecfa3c523661476a922d417391f788e9ff2f5987dbfa8
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d2ed6910b86a086911d3c0670c9778e222186d8733fc81bcc081932d70e0452a
-R 598da87d52fb6d14f38c03e06c0538c9
+P 994aa77d7826ab220727595a6a21f1f95a8f7590798879706016665ca1934dd1
+R da6c768beabe7f2a81e16e844ff466e6
U dan
-Z 7f5f483a874eaf4d6775a13d7db50d60
+Z de8917d47be58461bbb77ef08b41c047
-994aa77d7826ab220727595a6a21f1f95a8f7590798879706016665ca1934dd1
\ No newline at end of file
+dbbcbf0066ef82c789981feff78d95861a836e6e23a22ad3bb698dd257062f75
\ No newline at end of file