]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a Number/BigInt descrepancy in oo1.DB() when passed a WASM-string db filename...
authorstephan <stephan@noemail.net>
Sun, 21 Sep 2025 21:17:41 +0000 (21:17 +0000)
committerstephan <stephan@noemail.net>
Sun, 21 Sep 2025 21:17:41 +0000 (21:17 +0000)
FossilOrigin-Name: d078aff7817ccd4f891024e55703519307a53815d472086bf3d42b2be28698b3

ext/wasm/api/sqlite3-api-glue.c-pp.js
ext/wasm/api/sqlite3-api-oo1.c-pp.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/common/whwasmutil.js
manifest
manifest.uuid

index 903b8b41710c40f82ea60e17d8383d6d60fc083a..5564ce881e2040b25261f1c5b925c81d761111ce 100644 (file)
@@ -1470,17 +1470,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        Helper for string:flexible conversions which requires a
        byte-length counterpart argument. Passed a value and its
        ostensible length, this function returns [V,N], where V is
-       either v or a transformed copy of v and N is either (if v is a
-       WASM pointer, in which case n might be a BigInt), -1 (if v is a
-       string or Array), or the byte length of v (if it's a byte array
-       or ArrayBuffer).
+       either v or a to-string transformed copy of v and N is either n
+       (if v is a WASM pointer, in which case n might be a BigInt), -1
+       (if v is a string or Array), or the byte length of v (if it's a
+       byte array or ArrayBuffer).
     */
     const __flexiString = (v,n)=>{
       if('string'===typeof v){
         n = -1;
       }else if(util.isSQLableTypedArray(v)){
         n = v.byteLength;
-        v = util.typedArrayToString(
+        v = wasm.typedArrayToString(
           (v instanceof ArrayBuffer) ? new Uint8Array(v) : v
         );
       }else if(Array.isArray(v)){
index 51d7e20f999d8c8cd6a1b9208eb056f262150cf9..84a388302f49694058ff777b94e356c8c0a51d12 100644 (file)
@@ -269,7 +269,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         sqlite3.config.error("Invalid DB ctor args",opt,arguments);
         toss3("Invalid arguments for DB constructor:", arguments, "opts:", opt);
       }
-      let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
+      let fnJs = wasm.isPtr(fn) ? wasm.cstrToJs(fn) : fn;
       const vfsCheck = ctor._name2vfs[fnJs];
       if(vfsCheck){
         vfsName = vfsCheck.vfs;
@@ -1283,9 +1283,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         toss3("xValue must be provided if xInverse is.");
       }
       const pApp = opt.pApp;
-      if(undefined!==pApp &&
-         null!==pApp &&
-         (('number'!==typeof pApp) || !util.isInt32(pApp))){
+      if( undefined!==pApp
+          && null!==pApp
+          && !wasm.isPtr(pApp) ){
         toss3("Invalid value for pApp property. Must be a legal WASM pointer value.");
       }
       const xDestroy = opt.xDestroy || 0;
@@ -1586,18 +1586,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
      If key is a number and within range of stmt's bound parameter
      count, key is returned.
 
-     If key is not a number then it is checked against named
-     parameters. If a match is found, its index is returned.
+     If key is not a number then it must be a JS string (not a WASM
+     string) and it is checked against named parameters. If a match is
+     found, its index is returned.
 
      Else it throws.
   */
   const affirmParamIndex = function(stmt,key){
     const n = ('number'===typeof key)
           ? key : capi.sqlite3_bind_parameter_index(stmt.pointer, key);
-    if(0===n || !util.isInt32(n)){
-      toss3("Invalid bind() parameter name: "+key);
-    }
-    else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range.");
+    if( 0===n || !util.isInt32(n) ) toss3("Invalid bind() parameter name: "+key);
+    else if( n<1 || n>stmt.parameterCount ) toss3("Bind index",key,"is out of range.");
     return n;
   };
 
index 42d232cce8442402d585314b568383c7317e1b0f..32ecb1ed0f00ce9aaf686965884efd1d3cf0d2ab 100644 (file)
@@ -214,7 +214,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   };
 
   /** Internal helper for SQLite3Error ctor. */
-  const __isInt = (n)=>'number'===typeof n && n===(n | 0);
+  const isInt32 = (n)=>
+        'number'===typeof n
+        && n===(n | 0)
+        && n<=2147483647 && n>=-2147483648;
 
   /**
      An Error subclass specifically for reporting DB-level errors and
@@ -248,7 +251,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     constructor(...args){
       let rc;
       if(args.length){
-        if(__isInt(args[0])){
+        if(isInt32(args[0])){
           rc = args[0];
           if(1===args.length){
             super(__rcStr(args[0]));
@@ -291,16 +294,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     toss3("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'.");
   }
 
-  /**
-     Returns true if n is a 32-bit (signed) integer, else
-     false. This is used for determining when we need to switch to
-     double-type DB operations for integer values in order to keep
-     more precision.
-  */
-  const isInt32 = (n)=>{
-    return ('bigint'!==typeof n /*TypeError: can't convert BigInt to number*/)
-      && !!(n===(n|0) && n<=2147483647 && n>=-2147483648);
-  };
   /**
      Returns true if the given BigInt value is small enough to fit
      into an int64 value, else false.
@@ -336,16 +329,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false;
   };
 
-
-  /** Internal helper to use in operations which need to distinguish
-      between TypedArrays which are backed by a SharedArrayBuffer
-      from those which are not. */
-  const __SAB = ('undefined'===typeof SharedArrayBuffer)
-        ? function(){} : SharedArrayBuffer;
-  /** Returns true if the given TypedArray object is backed by a
-      SharedArrayBuffer, else false. */
-  const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB);
-
   /**
      Returns true if v appears to be one of our bind()-able TypedArray
      types: Uint8Array or Int8Array or ArrayBuffer. Support for
@@ -354,11 +337,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      property can be used to pass them as an ArrayBuffer. If it's not
      a bindable array type, a falsy value is returned.
   */
-  const isBindableTypedArray = (v)=>{
-    return v && (v instanceof Uint8Array
-                 || v instanceof Int8Array
-                 || v instanceof ArrayBuffer);
-  };
+  const isBindableTypedArray = (v)=>
+        v && (v instanceof Uint8Array
+              || v instanceof Int8Array
+              || v instanceof ArrayBuffer);
 
   /**
      Returns true if v appears to be one of the TypedArray types
@@ -369,69 +351,29 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      and friends to the isBindableTypedArray() list but not to the
      isSQLableTypedArray() list.
   */
-  const isSQLableTypedArray = (v)=>{
-    return v && (v instanceof Uint8Array
-                 || v instanceof Int8Array
-                 || v instanceof ArrayBuffer);
-  };
+  const isSQLableTypedArray = (v)=>
+        v && (v instanceof Uint8Array
+              || v instanceof Int8Array
+              || v instanceof ArrayBuffer);
 
   /** Returns true if isBindableTypedArray(v) does, else throws with a message
       that v is not a supported TypedArray value. */
-  const affirmBindableTypedArray = (v)=>{
-    return isBindableTypedArray(v)
-      || toss3("Value is not of a supported TypedArray type.");
-  };
-
-  /**
-     Returns either aTypedArray.slice(begin,end) (if
-     aTypedArray.buffer is a SharedArrayBuffer) or
-     aTypedArray.subarray(begin,end) (if it's not).
-
-     This distinction is important for APIs which don't like to
-     work on SABs, e.g. TextDecoder, and possibly for our
-     own APIs which work on memory ranges which "might" be
-     modified by other threads while they're working.
-  */
-  const typedArrayPart = (aTypedArray, begin, end)=>{
-    //if( 8===wasm..ptr.size ){
-    // slice() and subarray() do not like BigInt args.
-    if( 'bigint'===typeof begin ) begin = Number(begin);
-    if( 'bigint'===typeof end ) end = Number(end);
-    begin = Number(begin);
-    end = Number(end);
-    //}
-    return isSharedTypedArray(aTypedArray)
-      ? aTypedArray.slice(begin, end)
-      : aTypedArray.subarray(begin, end);
-  };
-
-  const utf8Decoder = new TextDecoder('utf-8');
-
-  /**
-     Uses TextDecoder to decode the given half-open range of the given
-     TypedArray to a string. This differs from a simple call to
-     TextDecoder in that it accounts for whether the first argument is
-     backed by a SharedArrayBuffer or not, and can work more
-     efficiently if it's not (TextDecoder refuses to act upon an SAB).
-
-     If begin/end are not provided or are falsy then each defaults to
-     the start/end of the string.
-  */
-  const typedArrayToString = function(typedArray, begin, end){
-    return utf8Decoder.decode(
-      typedArrayPart(typedArray, begin || 0, end || typedArray.length)
-    );
-  };
+  const affirmBindableTypedArray = (v)=>
+        isBindableTypedArray(v)
+        || toss3("Value is not of a supported TypedArray type.");
 
   /**
      If v is-a Array, its join("") result is returned.  If
-     isSQLableTypedArray(v) is true then typedArrayToString(v) is
+     isSQLableTypedArray(v) is true then wasm.typedArrayToString(v) is
      returned. If it looks like a WASM pointer, wasm.cstrToJs(v) is
      returned. Else v is returned as-is.
+
+     Reminder to self: the "return as-is" instead of returning ''+v is
+     arguably a design mistake but changing it is risky at this point.
   */
   const flexibleString = function(v){
     if(isSQLableTypedArray(v)){
-      return typedArrayToString(
+      return wasm.typedArrayToString(
         (v instanceof ArrayBuffer) ? new Uint8Array(v) : v,
         0, v.length
       );
@@ -806,13 +748,11 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     bigIntFits32, bigIntFits64, bigIntFitsDouble,
     isBindableTypedArray,
     isInt32, isSQLableTypedArray, isTypedArray,
-    typedArrayToString,
     isUIThread: ()=>(globalThis.window===globalThis && !!globalThis.document),
     // is this true for ESM?: 'undefined'===typeof WorkerGlobalScope
-    isSharedTypedArray,
     toss: function(...args){throw new Error(args.join(' '))},
     toss3,
-    typedArrayPart,
+    typedArrayPart: wasm.typedArrayPart,
     /**
        Given a byte array or ArrayBuffer, this function throws if the
        lead bytes of that buffer do not hold a SQLite3 database header,
@@ -1270,7 +1210,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
         do{
           const j = (n>nAlloc ? nAlloc : n);
           r(j, ptr);
-          ta.set(typedArrayPart(heap, ptr, wasm.ptr.add(ptr,j)), offset);
+          ta.set(wasm.typedArrayPart(heap, ptr, wasm.ptr.add(ptr,j)), offset);
           n -= j;
           offset += j;
         } while(n > 0);
index 1cc4f7bc0c1a4793b7a772b07ac4f68679d90c21..31ab522fa53f8917ccc505c14cff3b6c830d5a01 100644 (file)
@@ -996,24 +996,61 @@ globalThis.WhWasmUtilInstaller = function(target){
     return Number(pos - ptr);
   };
 
+
   /** Internal helper to use in operations which need to distinguish
-      between SharedArrayBuffer heap memory and non-shared heap. */
+      between TypedArrays which are backed by a SharedArrayBuffer
+      from those which are not. */
   const __SAB = ('undefined'===typeof SharedArrayBuffer)
-        ? function(){} : SharedArrayBuffer;
-  const __utf8Decode = function(arrayBuffer, begin, end){
-    //if( 'bigint'===typeof begin ) begin = Number(begin);
-    //if( 'bigint'===typeof end ) end = Number(end);
-    /*if( 8===__ptrSize ){
-      begin = Number(begin);
-      end = Number(end);
-    }*/
-    return cache.utf8Decoder.decode(
-      (arrayBuffer.buffer instanceof __SAB)
-        ? arrayBuffer.slice(begin, end)
-        : arrayBuffer.subarray(begin, end)
-    );
+        ? function(){/*dummy class*/} : SharedArrayBuffer;
+  /** Returns true if the given TypedArray object is backed by a
+      SharedArrayBuffer, else false. */
+  const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB);
+
+  target.isSharedTypedArray = isSharedTypedArray;
+
+  /**
+     Returns either aTypedArray.slice(begin,end) (if
+     aTypedArray.buffer is a SharedArrayBuffer) or
+     aTypedArray.subarray(begin,end) (if it's not).
+
+     This distinction is important for APIs which don't like to
+     work on SABs, e.g. TextDecoder, and possibly for our
+     own APIs which work on memory ranges which "might" be
+     modified by other threads while they're working.
+
+     begin and end may be of type Number or (in 64-bit builds) BigInt
+     (which get coerced to Numbers).
+  */
+  const typedArrayPart = (aTypedArray, begin, end)=>{
+    if( 8===__ptrSize ){
+      // slice() and subarray() do not like BigInt args.
+      if( 'bigint'===typeof begin ) begin = Number(begin);
+      if( 'bigint'===typeof end ) end = Number(end);
+    }
+    return isSharedTypedArray(aTypedArray)
+      ? aTypedArray.slice(begin, end)
+      : aTypedArray.subarray(begin, end);
   };
 
+  target.typedArrayPart = typedArrayPart;
+
+  /**
+     Uses TextDecoder to decode the given half-open range of the given
+     TypedArray to a string. This differs from a simple call to
+     TextDecoder in that it accounts for whether the first argument is
+     backed by a SharedArrayBuffer or not, and can work more
+     efficiently if it's not (TextDecoder refuses to act upon an SAB).
+
+     If begin/end are not provided or are falsy then each defaults to
+     the start/end of the array.
+  */
+  const typedArrayToString = (typedArray, begin, end)=>
+        cache.utf8Decoder.decode(
+          typedArrayPart(typedArray, begin, end)
+        );
+
+  target.typedArrayToString = typedArrayToString;
+
   /**
      Expects ptr to be a pointer into the WASM heap memory which
      refers to a NUL-terminated C-style string encoded as UTF-8. This
@@ -1024,7 +1061,7 @@ globalThis.WhWasmUtilInstaller = function(target){
   target.cstrToJs = function(ptr){
     const n = target.cstrlen(ptr);
     return n
-      ? __utf8Decode(heapWrappers().HEAP8U, Number(ptr), Number(ptr)+n)
+      ? typedArrayToString(heapWrappers().HEAP8U, Number(ptr), Number(ptr)+n)
       : (null===n ? n : "");
   };
 
index 7120657501620bc848fedf060c0a924af63b9c66..c4dc7a5894ddf53abba677bf092c6c0099494d4c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sStructType.dispose()/ondispose()\smemleak\sin\sJaccwabyt\sbindings\sin\s64-bit\sbuilds\sand\supdate\sits\sdocs\sfor\s64-bit\sadditions.\sRemove\sthe\sparts\sof\stester1.js\srelated\sto\sskipping\sspecific\stests\sin\s64-bit\sbuilds.
-D 2025-09-21T20:26:47.094
+C Fix\sa\sNumber/BigInt\sdescrepancy\sin\soo1.DB()\swhen\spassed\sa\sWASM-string\sdb\sfilename.\sConsolidate\ssome\sduplicated\sinternal\scode\sand\sadjacent\sminor\scleanups.
+D 2025-09-21T21:17:41.884
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -597,9 +597,9 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
 F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
 F ext/wasm/api/pre-js.c-pp.js 58f823de197e2c10d76179aa05410a593b7ae03e1ece983bb42ffd818e8857e1
 F ext/wasm/api/sqlite3-api-cleanup.js d4f1a5e665afaf84015f6ef0ddd766f638cb28501c4569b1d4b527c4b5a2b9a4
-F ext/wasm/api/sqlite3-api-glue.c-pp.js 814bdccd7e7c28520cd9a2480785fda027529061e9187460d7155775034afd0f
-F ext/wasm/api/sqlite3-api-oo1.c-pp.js 831ce373495f6a5d9230f31a1e09e8995e317828926e736d58c9e7091c6b1d07
-F ext/wasm/api/sqlite3-api-prologue.js bdf8e553c2142916fd7a2382e1becfed7a5755da95f585f632336634e5728448
+F ext/wasm/api/sqlite3-api-glue.c-pp.js 775a4971821aa523c35589b8bfb630672979b6f93d40e31fac67e625278b1b49
+F ext/wasm/api/sqlite3-api-oo1.c-pp.js db4c8ebb03bac60db32ce03f8c615b00f4e4ad53e7d5de5e63d2780cba052caa
+F ext/wasm/api/sqlite3-api-prologue.js 859556cbccac7585d532d34d88ffd94d5f3899f205ecd86aebde7ca233800b9c
 F ext/wasm/api/sqlite3-api-worker1.c-pp.js 760191cd13416e6f5adfd9fcc8a97fed5645c9e0a5fbac213a2d4ce2d79a4334
 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
 F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
@@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e
 F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
-F ext/wasm/common/whwasmutil.js aff84dc5b7bf1f06a567d4ab43d28422447f5806487210f805d4d85b400b82b8
+F ext/wasm/common/whwasmutil.js 01ff73506497bc72fb4befa728180fadbfce233cbc6d334349de20ac599f8680
 F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
 F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
 F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
@@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 0336fa95e15c53ac6ab8152a840163a5aac64725874ffb848ce1d95e3af90586
-R b1fcd52f2c860acb4ea0ae4f12feba2f
+P 6baea1d719b0c345fee5f32a3917ce9c507a2d8cb029eaca675daca77f297eba
+R d30caea5f4cf59306605198c4b94e5e3
 U stephan
-Z bf93d953cde2ac0d4ff0dc420f01f479
+Z 4273dba133b18477f15537f7ebd93229
 # Remove this line to create a well-formed Fossil manifest.
index 1a1b11754c708bab160fdfaa0c381ac48a6937f8..2d24b0602607824274d62792f8f6f5d4a74b4fda 100644 (file)
@@ -1 +1 @@
-6baea1d719b0c345fee5f32a3917ce9c507a2d8cb029eaca675daca77f297eba
+d078aff7817ccd4f891024e55703519307a53815d472086bf3d42b2be28698b3