diff --git a/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api b/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api index fecc59aa19..75e5ea3da1 100644 --- a/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api +++ b/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api @@ -92,6 +92,7 @@ _sqlite3_result_text _sqlite3_result_zeroblob _sqlite3_result_zeroblob64 _sqlite3_serialize +_sqlite3_set_authorizer _sqlite3_set_auxdata _sqlite3_set_last_insert_rowid _sqlite3_shutdown diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js index 5488f26c94..9e10280220 100644 --- a/ext/wasm/api/sqlite3-api-glue.js +++ b/ext/wasm/api/sqlite3-api-glue.js @@ -162,6 +162,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"], ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"], ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"], + /* sqlite3_set_authorizer() requires a hand-written binding for + string conversions, so is defined elsewhere. */ ["sqlite3_set_auxdata", undefined, "sqlite3_context*", "int", "*", "*"/* => v(*) */], ["sqlite3_shutdown", undefined], ["sqlite3_sourceid", "string"], @@ -818,6 +820,37 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }; }/*sqlite3_prepare_v2/v3()*/; + {/* sqlite3_set_authorizer() */ + const __ssa = wasm.xWrap("sqlite3_set_authorizer", 'int', [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: "sqlite3_set_authorizer::xAuth", + signature: "i(pi"+"ssss)", + contextKey: (argIndex, argv)=>argv[0/*(sqlite3*)*/] + }), + "*" + ]); + capi.sqlite3_set_authorizer = function(pDb, xAuth, pUserData){ + if(3!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_set_authorizer', 3); + if(xAuth instanceof Function){ + const xProxy = xAuth; + /* Create a proxy which will receive the C-strings from WASM + and convert them to JS strings for the client-supplied + function. */ + xAuth = function(pV, iCode, s0, s1, s2, s3){ + try{ + s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1); + s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3); + return xProxy(pV, iCode, s0, s1, s2, s3) || 0; + }catch(e){ + return util.sqlite3_wasm_db_error(pDb, e); + } + }; + } + return __ssa(pDb, xAuth, pUserData); + }; + }/* sqlite3_set_authorizer() */ + {/* Import C-level constants and structs... */ const cJson = wasm.xCall('sqlite3_wasm_enum_json'); if(!cJson){ @@ -885,9 +918,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ capi.sqlite3_index_info[k] = capi[k]; delete capi[k]; } - capi.sqlite3_vtab_config = - (pDb, op, arg=0)=>wasm.exports.sqlite3_wasm_vtab_config( - wasm.xWrap.argAdapter('sqlite3*')(pDb), op, arg); + capi.sqlite3_vtab_config = wasm.xWrap( + 'sqlite3_wasm_vtab_config','int',[ + 'sqlite3*', 'int', 'int'] + ); }/* end vtab-related setup */ }/*end C constant and struct imports*/ diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index 5b0f177755..be73f6fe81 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -410,10 +410,43 @@ const char * sqlite3_wasm_enum_json(void){ DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/; } _DefGroup; - /* TODO? Authorizer... */ DefGroup(authorizer){ DefInt(SQLITE_DENY); DefInt(SQLITE_IGNORE); + DefInt(SQLITE_CREATE_INDEX); + DefInt(SQLITE_CREATE_TABLE); + DefInt(SQLITE_CREATE_TEMP_INDEX); + DefInt(SQLITE_CREATE_TEMP_TABLE); + DefInt(SQLITE_CREATE_TEMP_TRIGGER); + DefInt(SQLITE_CREATE_TEMP_VIEW); + DefInt(SQLITE_CREATE_TRIGGER); + DefInt(SQLITE_CREATE_VIEW); + DefInt(SQLITE_DELETE); + DefInt(SQLITE_DROP_INDEX); + DefInt(SQLITE_DROP_TABLE); + DefInt(SQLITE_DROP_TEMP_INDEX); + DefInt(SQLITE_DROP_TEMP_TABLE); + DefInt(SQLITE_DROP_TEMP_TRIGGER); + DefInt(SQLITE_DROP_TEMP_VIEW); + DefInt(SQLITE_DROP_TRIGGER); + DefInt(SQLITE_DROP_VIEW); + DefInt(SQLITE_INSERT); + DefInt(SQLITE_PRAGMA); + DefInt(SQLITE_READ); + DefInt(SQLITE_SELECT); + DefInt(SQLITE_TRANSACTION); + DefInt(SQLITE_UPDATE); + DefInt(SQLITE_ATTACH); + DefInt(SQLITE_DETACH); + DefInt(SQLITE_ALTER_TABLE); + DefInt(SQLITE_REINDEX); + DefInt(SQLITE_ANALYZE); + DefInt(SQLITE_CREATE_VTABLE); + DefInt(SQLITE_DROP_VTABLE); + DefInt(SQLITE_FUNCTION); + DefInt(SQLITE_SAVEPOINT); + //DefInt(SQLITE_COPY) /* No longer used */; + DefInt(SQLITE_RECURSIVE); } _DefGroup; DefGroup(blobFinalizers) { diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js index 82d10dff11..87cc100f33 100644 --- a/ext/wasm/common/whwasmutil.js +++ b/ext/wasm/common/whwasmutil.js @@ -1580,6 +1580,11 @@ self.WhWasmUtilInstaller = function(target){ The constructor only saves the above state for later, and does not actually bind any functions. Its convertArg() method is called via xWrap() to perform any bindings. + + Shortcomings: function pointers which include C-string arguments + may still need a level of hand-written wrappers around them, + depending on how they're used, in order to provide the client + with JS strings. */ xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter { constructor(opt) { diff --git a/ext/wasm/module-symbols.html b/ext/wasm/module-symbols.html index d2da562c99..6298aeb374 100644 --- a/ext/wasm/module-symbols.html +++ b/ext/wasm/module-symbols.html @@ -287,6 +287,7 @@ sqlite3_result_zeroblob: 'www:/c3ref/result_blob.html', sqlite3_result_zeroblob64: 'www:/c3ref/result_blob.html', sqlite3_serialize: 'www:/c3ref/serialize.html', + sqlite3_set_authorizer: 'wasm:/api-c-style.md#sqlite3_set_authorizer', sqlite3_set_auxdata: 'www:/c3ref/set_auxdata.html', sqlite3_set_last_insert_rowid: 'www:/c3ref/set_last_insert_rowid', sqlite3_shutdown: 'www:/c3ref/initialize.html', diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index 768d5cdf49..2e96daa2ff 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -1331,7 +1331,70 @@ self.sqlite3InitModule = sqlite3InitModule; T.assert(e instanceof sqlite3.SQLite3Error) .assert(0==e.message.indexOf('Cannot prepare empty')); } - }) + })/*setup table T*/ + + //////////////////////////////////////////////////////////////////// + .t({ + name: "sqlite3_set_authorizer()", + test:function(sqlite3){ + T.assert(capi.SQLITE_IGNORE>0) + .assert(capi.SQLITE_DENY>0); + const db = this.db; + const ssa = capi.sqlite3_set_authorizer; + const n = db.selectValue('select count(*) from t'); + T.assert(n>0); + let authCount = 0; + let rc = ssa(db, function(pV, iCode, s0, s1, s2, s3){ + ++authCount; + return capi.SQLITE_IGNORE; + }, 0); + T.assert(0===rc) + .assert( + undefined === db.selectValue('select count(*) from t') + /* Note that the count() never runs, so we get undefined + instead of 0. */ + ) + .assert(authCount>0); + authCount = 0; + db.exec("update t set a=-9999"); + T.assert(authCount>0); + /* Reminder: we don't use DELETE because, from the C API docs: + + "If the action code is [SQLITE_DELETE] and the callback + returns [SQLITE_IGNORE] then the [DELETE] operation proceeds + but the [truncate optimization] is disabled and all rows are + deleted individually." + */ + rc = ssa(db, null, 0); + authCount = 0; + T.assert(-9999 != db.selectValue('select a from t')) + .assert(0===authCount); + rc = ssa(db, function(pV, iCode, s0, s1, s2, s3){ + ++authCount; + return capi.SQLITE_DENY; + }, 0); + T.assert(0===rc); + let err; + try{ db.exec("select 1 from t") } + catch(e){ err = e } + T.assert(err instanceof sqlite3.SQLite3Error) + .assert(err.message.indexOf('not authorized'>0)) + .assert(1===authCount); + authCount = 0; + rc = ssa(db, function(...args){ + ++authCount; + return capi.SQLITE_OK; + }, 0); + T.assert(0===rc); + T.assert(n === db.selectValue('select count(*) from t')) + .assert(authCount>0); + authCount = 0; + rc = ssa(db, null, 0); + T.assert(0===rc); + T.assert(n === db.selectValue('select count(*) from t')) + .assert(0===authCount); + } + })/*sqlite3_set_authorizer()*/ //////////////////////////////////////////////////////////////////////// .t("sqlite3_table_column_metadata()", function(sqlite3){ diff --git a/manifest b/manifest index e4ec20ca89..3e3b3ccd20 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Create\sa\snew\saffinity\scalled\sFLEXNUM\sthat\sworks\slike\sNUMERIC\sexcept\sthat\sit\nnever\stries\sto\sconvert\sinteger\sto\sreal\sor\sreal\sto\sinteger.\s\sThe\saffinity\sis\nonly\sused\sinternally\s-\sit\sis\snot\spossible\sto\screate\sa\stable\scolumn\swith\sthis\naffinity.\s\sThis\saffinity\sis\sused\son\ssubqueries\sand\sviews\sthat\sare\sbuilt\soff\nof\sa\scompound\sSELECT\sand\swhere\sthe\sdatatype\sis\scontrolled\sby\sa\sCAST\sexpression.\ndbsqlfuzz\sc9ee6f9a0a8b8fefb02cf69de2a8b67ca39525c8 -D 2022-12-15T20:03:08.225 +C Add\ssqlite3_set_authorizer()\ssupport\sand\srelated\stests\sto\sJS. +D 2022-12-16T11:13:32.652 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -494,7 +494,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce F ext/wasm/GNUmakefile 32e5d1929d3e4d7c5892208d8078453e57339af8f7e9be320cdf96b2d60c69ba F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20 F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9 -F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 3883604dfda98352ff7ea76b2092f406d8c1ebc576e16b8c6e470fa2b1724880 +F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 4c7788042196cecab32f87d8e4965c183fea59037603888059f244b1752babcc F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 F ext/wasm/api/README.md 17fb1e10335cc87e366dec496c5b17b061f3f75cdf216e825258de34d97a3e53 F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d @@ -503,7 +503,7 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62 F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4 -F ext/wasm/api/sqlite3-api-glue.js 2e1087b870290a3a613d59ed626bde1f6da7c9c211cd36e41df1ee8b2932b508 +F ext/wasm/api/sqlite3-api-glue.js beb6a08c58c2c8d6af59036a2cbc5d994612eea88ebe0fc9ccbb8df10530e3a7 F ext/wasm/api/sqlite3-api-oo1.js c0c4ccc269cccee657ffd03f094da7e270e1367b7928926b3730d543555a12a6 F ext/wasm/api/sqlite3-api-prologue.js 86eb4488f2be85e68c23ebcfad0834c24b6075e1645c67890cc4163c462efac1 F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f @@ -512,7 +512,7 @@ F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 -F ext/wasm/api/sqlite3-wasm.c 44f1779bfaf8914e0331241ddd7a59e68df8a06223638c8b87fcb36776d9c0f4 +F ext/wasm/api/sqlite3-wasm.c f95466be697e0096c8d2e6d24cf97592c012dcc3dea48ce2d285e44ef4458794 F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8 @@ -521,7 +521,7 @@ F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c07 F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f -F ext/wasm/common/whwasmutil.js e8934d24518f99a8995e2da5a4f308d36c13bea90d36a0396585e2debba94d57 +F ext/wasm/common/whwasmutil.js ba1a8db1f32124e43e24b3d890102b6552b2c0b5a202185041a55887692df328 F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508 F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6 @@ -541,7 +541,7 @@ F ext/wasm/index-dist.html c806b6005145b71d64240606e9c6e0bf56878ee8829c66fe7486c F ext/wasm/index.html f151b7c7b5cfdc066567d556acd168e769efd4e982286dc5f849a5ee69ecd0ff F ext/wasm/jaccwabyt/jaccwabyt.js 06f2ef1ad640c26c593def3d960336e9bb789819b920516480895c38ed5f58fa F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb -F ext/wasm/module-symbols.html 650a5ad1bd54feb39eb627b06093612932317406825f3a727d5926016a46e502 +F ext/wasm/module-symbols.html 573317801087e67c946a157783715d5716e027fcf484918a0c3aae4e627cc93d F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06 F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18 F ext/wasm/speedtest1-wasmfs.html bc28eb29b69a73864b8d7aae428448f8b7e1de81d8bfb9bba99541322054dbd0 @@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9 F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406 -F ext/wasm/tester1.c-pp.js 68aec9aff32282fa2e1640c8d87dd0792cbc24bfbf303a968b4ea8b6c4096ac9 +F ext/wasm/tester1.c-pp.js d34eda179066df651acd22cd11155764be9837a8f09e126f0f168bcf13be88fb F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd537f2057a4800bd30e7dd57405c3e57df649471104c80bd32573a89568029e -R 37c0f0e978d6f512d45ea1c89699be07 -U drh -Z f6d3f39ad91532557d8a7968a4b1fd8b +P 44135d6ea84f7ba6b36549954b38a8bc048d5ffea5a9779e35950afa4eb2dfb2 +R 71885d98f7dc4ddf1de1f6596395aab3 +U stephan +Z b36a52e0da5cfda153e6c629f1035a18 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b16f3354de..9bac591a4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -44135d6ea84f7ba6b36549954b38a8bc048d5ffea5a9779e35950afa4eb2dfb2 \ No newline at end of file +551b848894c249cb3c9d237643d2ed53ffcb3b003d0cf3f797a535df1731ce39 \ No newline at end of file