Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: node-sqli...@packages.debian.org Control: affects -1 + src:node-sqlite3
Please unblock package node-sqlite3 [ Reason ] A code execution vulnerability was discover in node-sqlite3 due to the underlying implementation of .toString(). It is then possible to execute arbitrary JavaScript or to achieve a denial-of-service. if a binding parameter is a crafted object. (CVE-2022-43441) [ Impact ] Major security issue [ Tests ] New test added, passed [ Risks ] No risk, patch is trivial. The main change is this: @@ -208,7 +208,7 @@ template <class T> Values::Field* return new Values::Float(pos, source.ToNumber().DoubleValue()); } else if (source.IsObject()) { - Napi::String napiVal = source.ToString(); + Napi::String napiVal = Napi::String::New(source.Env(), "[object Object]"); // Check whether toString returned a value that is not undefined. if(napiVal.Type() == 0) { return NULL; [ Checklist ] [X] all changes are documented in the d/changelog [X] I reviewed all changes and I approve them [X] attach debdiff against the package in testing [ Other info ] DSA pushed also for bullseye (5.0.0+ds1-1+deb11u2) unblock node-sqlite3/5.1.5+ds1-1
diff --git a/README.md b/README.md index 4a214a6..571df9e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Asynchronous, non-blocking [SQLite3](https://sqlite.org/) bindings for [Node.js] - [Extension support](https://github.com/TryGhost/node-sqlite3/wiki/API#databaseloadextensionpath-callback), including bundled support for the [json1 extension](https://www.sqlite.org/json1.html) - Big test suite - Written in modern C++ and tested for memory leaks - - Bundles SQLite v3.39.4, or you can build using a local SQLite + - Bundles SQLite v3.41.1, or you can build using a local SQLite # Installing diff --git a/binding.gyp b/binding.gyp index f1336f6..20d418b 100644 --- a/binding.gyp +++ b/binding.gyp @@ -25,8 +25,10 @@ "libraries": [ "-l<(sqlite_libname)" ], - "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ], - "conditions": [ [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] ], + "conditions": [ + [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ], + [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] + ], 'msvs_settings': { 'VCLinkerTool': { 'AdditionalLibraryDirectories': [ diff --git a/debian/changelog b/debian/changelog index a1b24b6..5eb4c18 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +node-sqlite3 (5.1.5+ds1-1) unstable; urgency=medium + + * Team upload + * Update lintian override info format in d/source/lintian-overrides + on line 2-3 + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository-Browse + * Update standards version to 4.6.2, no changes needed. + * New upstream version (Closes: CVE-2022-43441) + + -- Yadd <y...@debian.org> Tue, 14 Mar 2023 07:04:46 +0400 + node-sqlite3 (5.1.2+ds1-1) unstable; urgency=medium * Team upload diff --git a/debian/control b/debian/control index e775fb8..cd29f0e 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,7 @@ Build-Depends: , mocha , libsqlite3-dev , dh-sequence-nodejs -Standards-Version: 4.6.1 +Standards-Version: 4.6.2 Homepage: https://github.com/mapbox/node-sqlite3/wiki Vcs-Git: https://salsa.debian.org/js-team/node-sqlite3.git Vcs-Browser: https://salsa.debian.org/js-team/node-sqlite3 diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides index 6694acf..30e1e92 100644 --- a/debian/source/lintian-overrides +++ b/debian/source/lintian-overrides @@ -1,5 +1,5 @@ # only long lines, source is readable -source-is-missing *test/null_error.test.js* -source-contains-prebuilt-javascript-object *test/null_error.test.js* +source-is-missing [*test/null_error.test.js*] +source-contains-prebuilt-javascript-object [*test/null_error.test.js*] very-long-line-length-in-source-file *.md* very-long-line-length-in-source-file *test/null_error.test.js* diff --git a/debian/upstream/metadata b/debian/upstream/metadata index 4b6a0f1..b794be2 100644 --- a/debian/upstream/metadata +++ b/debian/upstream/metadata @@ -1,6 +1,6 @@ --- Archive: GitHub -Bug-Database: https://github.com/mapbox/node-sqlite3/issues -Bug-Submit: https://github.com/mapbox/node-sqlite3/issues/new +Bug-Database: https://github.com/TryGhost/node-sqlite3/issues +Bug-Submit: https://github.com/TryGhost/node-sqlite3/issues/new Repository: https://github.com/mapbox/node-sqlite3.git -Repository-Browse: https://github.com/mapbox/node-sqlite3 +Repository-Browse: https://github.com/TryGhost/node-sqlite3 diff --git a/deps/common-sqlite.gypi b/deps/common-sqlite.gypi index 4be536c..9d70d3b 100644 --- a/deps/common-sqlite.gypi +++ b/deps/common-sqlite.gypi @@ -1,6 +1,6 @@ { 'variables': { - 'sqlite_version%':'3390400', + 'sqlite_version%':'3410100', "toolset%":'', }, 'target_defaults': { diff --git a/package.json b/package.json index 530294f..6193ae8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sqlite3", "description": "Asynchronous, non-blocking SQLite3 bindings", - "version": "5.1.2", + "version": "5.1.5", "homepage": "https://github.com/TryGhost/node-sqlite3", "author": { "name": "Mapbox", diff --git a/src/database.cc b/src/database.cc index b16b1f7..15709ce 100644 --- a/src/database.cc +++ b/src/database.cc @@ -56,7 +56,7 @@ void Database::Process() { queue.pop(); std::unique_ptr<Baton> baton(call->baton); Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(this->Value(), cb, 1, argv); called = true; } @@ -97,7 +97,7 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { // We don't call the actual callback, so we have to make sure that // the baton gets destroyed. delete baton; - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { exception }; TRY_CATCH_CALL(Value(), cb, 1, argv); } @@ -202,7 +202,7 @@ void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else if (!db->open) { @@ -294,7 +294,7 @@ void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { Napi::Function cb = baton->callback.Value(); // Fire callbacks. - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else if (db->open) { @@ -630,7 +630,7 @@ void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { if (baton->status != SQLITE_OK) { EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { exception }; TRY_CATCH_CALL(db->Value(), cb, 1, argv); } @@ -639,7 +639,7 @@ void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { EMIT_EVENT(db->Value(), 2, info); } } - else if (!cb.IsUndefined() && cb.IsFunction()) { + else if (IS_FUNCTION(cb)) { Napi::Value argv[] = { env.Null() }; TRY_CATCH_CALL(db->Value(), cb, 1, argv); } @@ -671,7 +671,7 @@ void Database::Work_Wait(Baton* b) { assert(baton->db->pending == 0); Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { env.Null() }; TRY_CATCH_CALL(baton->db->Value(), cb, 1, argv); } @@ -742,7 +742,7 @@ void Database::Work_AfterLoadExtension(napi_env e, napi_status status, void* dat if (baton->status != SQLITE_OK) { EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { exception }; TRY_CATCH_CALL(db->Value(), cb, 1, argv); } @@ -751,7 +751,7 @@ void Database::Work_AfterLoadExtension(napi_env e, napi_status status, void* dat EMIT_EVENT(db->Value(), 2, info); } } - else if (!cb.IsUndefined() && cb.IsFunction()) { + else if (IS_FUNCTION(cb)) { Napi::Value argv[] = { env.Null() }; TRY_CATCH_CALL(db->Value(), cb, 1, argv); } diff --git a/src/macros.h b/src/macros.h index b46a875..344642d 100644 --- a/src/macros.h +++ b/src/macros.h @@ -23,6 +23,9 @@ inline bool OtherIsInt(Napi::Number source) { } } +#define IS_FUNCTION(cb) \ + !cb.IsUndefined() && cb.IsFunction() + #define REQUIRE_ARGUMENTS(n) \ if (info.Length() < (n)) { \ Napi::TypeError::New(env, "Expected " #n "arguments").ThrowAsJavaScriptException(); \ diff --git a/src/statement.cc b/src/statement.cc index 6adb123..29e06f9 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -77,7 +77,7 @@ template <class T> void Statement::Error(T* baton) { Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { exception }; TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } @@ -208,7 +208,7 @@ template <class T> Values::Field* return new Values::Float(pos, source.ToNumber().DoubleValue()); } else if (source.IsObject()) { - Napi::String napiVal = source.ToString(); + Napi::String napiVal = Napi::String::New(source.Env(), "[object Object]"); // Check whether toString returned a value that is not undefined. if(napiVal.Type() == 0) { return NULL; @@ -375,7 +375,7 @@ void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { else { // Fire callbacks. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { env.Null() }; TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } @@ -442,7 +442,7 @@ void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { else { // Fire callbacks. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { if (stmt->status == SQLITE_ROW) { // Create the result array from the data we acquired. Napi::Value argv[] = { env.Null(), RowToJS(env, &baton->row) }; @@ -516,7 +516,7 @@ void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { else { // Fire callbacks. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { (stmt->Value()).Set(Napi::String::New(env, "lastID"), Napi::Number::New(env, baton->inserted_id)); (stmt->Value()).Set( Napi::String::New(env, "changes"), Napi::Number::New(env, baton->changes)); @@ -586,7 +586,7 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { else { // Fire callbacks. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { if (baton->rows.size()) { // Create the result array from the data we acquired. Napi::Array result(Napi::Array::New(env, baton->rows.size())); @@ -716,7 +716,7 @@ void Statement::AsyncEach(uv_async_t* handle) { } Napi::Function cb = async->item_cb.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[2]; argv[0] = env.Null(); @@ -791,7 +791,7 @@ void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { // Fire callbacks. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { Napi::Value argv[] = { env.Null() }; TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } @@ -893,7 +893,7 @@ void Statement::Finalize_(Baton* b) { // Fire callback in case there was one. Napi::Function cb = baton->callback.Value(); - if (!cb.IsUndefined() && cb.IsFunction()) { + if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(baton->stmt->Value(), cb, 0, NULL); } } diff --git a/test/other_objects.test.js b/test/other_objects.test.js index 7185987..cc516c4 100644 --- a/test/other_objects.test.js +++ b/test/other_objects.test.js @@ -95,4 +95,20 @@ describe('data types', function() { }); }); + it('should ignore faulty toString in array', function(done) { + const faulty = [[{toString: null}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, null); + done(); + }); + }); + + it('should ignore faulty toString set to function', function(done) { + const faulty = [[{toString: function () {console.log('oh no');}}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, undefined); + done(); + }); + }); + });