From 903e779236deaa185d83cc66cd99012ed95145d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Fri, 2 Oct 2026 12:43:38 -0300 Subject: [PATCH] sqlite: validate aggregate() name and options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Database.prototype.aggregate()` cast its arguments without checking their types, so a missing `options` leaked a raw V8 TypeError and a non-string `name` was silently coerced. Throw `ERR_INVALID_ARG_TYPE` like the other sqlite bindings do. Assisted-by: Claude Code Signed-off-by: Guilherme Araújo --- src/node_sqlite.cc | 13 +++++++++++++ .../test-sqlite-aggregate-function.mjs | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 9ebc0cb97316..2b1ca4918bf2 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -2693,6 +2693,19 @@ void Database::AggregateFunction(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open"); THROW_AND_RETURN_IF_IN_AUTHORIZER(env, db); + + if (!args[0]->IsString()) { + THROW_ERR_INVALID_ARG_TYPE(env->isolate(), + "The \"name\" argument must be a string."); + return; + } + + if (!args[1]->IsObject()) { + THROW_ERR_INVALID_ARG_TYPE(env->isolate(), + "The \"options\" argument must be an object."); + return; + } + Utf8Value name(env->isolate(), args[0].As()); Local options = args[1].As(); Local start_v; diff --git a/test/parallel/test-sqlite-aggregate-function.mjs b/test/parallel/test-sqlite-aggregate-function.mjs index f588cc3ee680..83f7833cb3f5 100644 --- a/test/parallel/test-sqlite-aggregate-function.mjs +++ b/test/parallel/test-sqlite-aggregate-function.mjs @@ -20,6 +20,24 @@ describe('Database.prototype.aggregate()', () => { return fn; } + test('throws if name is not a string', (t) => { + t.assert.throws(() => { + db.aggregate(123, { start: 0, step: () => {} }); + }, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "name" argument must be a string.' + }); + }); + + test('throws if options is not an object', (t) => { + t.assert.throws(() => { + db.aggregate('sum'); + }, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "options" argument must be an object.' + }); + }); + test('throws if options.start is not provided', (t) => { t.assert.throws(() => { db.aggregate('sum', {