From 149ff07c2ecaa0414e4c8d96d208c8bb9c1565ef Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 22 May 2025 19:27:04 -0400 Subject: [PATCH] sqlite: handle thrown errors in result callback This commit updates the aggregate function 'result' callback handling to not crash when an exception is thrown. Fixes: https://github.com/nodejs/node/issues/58425 --- src/node_sqlite.cc | 5 ++++- .../test-sqlite-aggregate-function.mjs | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 0295ee4ff2f739..4a9d1c1af9c85e 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -373,7 +373,10 @@ class CustomAggregate { result = Local::New(isolate, agg->value); } - JSValueToSQLiteResult(isolate, ctx, result); + if (!result.IsEmpty()) { + JSValueToSQLiteResult(isolate, ctx, result); + } + if (is_final) { DestroyAggregateData(ctx); } diff --git a/test/parallel/test-sqlite-aggregate-function.mjs b/test/parallel/test-sqlite-aggregate-function.mjs index 3db7494daf12ef..050705c771e6af 100644 --- a/test/parallel/test-sqlite-aggregate-function.mjs +++ b/test/parallel/test-sqlite-aggregate-function.mjs @@ -309,6 +309,27 @@ describe('step', () => { }); describe('result', () => { + test('throws if result throws an error', (t) => { + const db = new DatabaseSync(':memory:'); + t.after(() => db.close()); + db.exec('CREATE TABLE data (value INTEGER)'); + db.exec('INSERT INTO data VALUES (1), (2), (3)'); + db.aggregate('sum_int', { + start: 0, + step: (acc, value) => { + return acc + value; + }, + result: () => { + throw new Error('result error'); + }, + }); + t.assert.throws(() => { + db.prepare('SELECT sum_int(value) as result FROM data').get(); + }, { + message: 'result error' + }); + }); + test('executes once when options.inverse is not present', (t) => { const db = new DatabaseSync(':memory:'); t.after(() => db.close());