Commit 128f247ea4c for nodejs

commit 128f247ea4cb52da405f6cc35dec46c088be8af3
Author: Guilherme Araújo <arauujogui@gmail.com>
Date:   Fri Nov 6 08:53:45 2026 -0300

    sqlite: use 64-bit result APIs for UDF return values

    JSValueToSQLiteResult() passed the size_t length of returned
    ArrayBuffers and ArrayBufferViews to sqlite3_result_blob(), which
    takes an int. Buffers larger than INT_MAX bytes were narrowed,
    yielding silently truncated blobs or bogus empty text values.

    Use sqlite3_result_blob64() and sqlite3_result_text64(), matching
    Statement::BindValue(), so oversized values are rejected with
    SQLITE_TOOBIG.

    Assisted-by: Claude Code
    Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/67089
    Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>

diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc
index 2bf67b97689..77617e011fa 100644
--- a/src/node_sqlite.cc
+++ b/src/node_sqlite.cc
@@ -332,11 +332,12 @@ void JSValueToSQLiteResult(Isolate* isolate,
     sqlite3_result_double(ctx, value.As<Number>()->Value());
   } else if (value->IsString()) {
     Utf8Value val(isolate, value.As<String>());
-    sqlite3_result_text(ctx, *val, val.length(), SQLITE_TRANSIENT);
+    sqlite3_result_text64(
+        ctx, *val, val.length(), SQLITE_TRANSIENT, SQLITE_UTF8);
   } else if (value->IsArrayBufferView() || value->IsArrayBuffer() ||
              value->IsSharedArrayBuffer()) {
     ArrayBufferViewContents<uint8_t> buf(value);
-    sqlite3_result_blob(ctx, buf.data(), buf.length(), SQLITE_TRANSIENT);
+    sqlite3_result_blob64(ctx, buf.data(), buf.length(), SQLITE_TRANSIENT);
   } else if (value->IsBigInt()) {
     bool lossless;
     int64_t as_int = value.As<BigInt>()->Int64Value(&lossless);
diff --git a/test/parallel/test-sqlite-custom-functions.js b/test/parallel/test-sqlite-custom-functions.js
index 20b16138813..0a4b80b80ae 100644
--- a/test/parallel/test-sqlite-custom-functions.js
+++ b/test/parallel/test-sqlite-custom-functions.js
@@ -1,5 +1,5 @@
 'use strict';
-const { skipIfSQLiteMissing, mustCall } = require('../common');
+const { skipIfSQLiteMissing, mustCall, enoughTestMem } = require('../common');
 skipIfSQLiteMissing();
 const assert = require('node:assert');
 const { Database } = require('node:sqlite');
@@ -347,6 +347,28 @@ suite('Database.prototype.function()', () => {
       });
     });

+    test('throws if returned buffer exceeds INT_MAX bytes', {
+      skip: !enoughTestMem && 'insufficient memory',
+    }, (t) => {
+      const db = new Database(':memory:');
+      for (const size of [2 ** 31, 2 ** 32 + 5]) {
+        let buf;
+        try {
+          buf = new ArrayBuffer(size);
+        } catch {
+          return t.skip('insufficient memory');
+        }
+        db.function('retLargeBuffer', () => buf);
+        const stmt = db.prepare('SELECT retLargeBuffer() AS retLargeBuffer');
+        assert.throws(() => {
+          stmt.get();
+        }, {
+          code: 'ERR_SQLITE_ERROR',
+          message: /string or blob too big/,
+        });
+      }
+    });
+
     test('throws on unsupported return types', () => {
       const db = new Database(':memory:');
       db.function('retFunction', () => {