Verify partial node reads and reject malformed address rows

This commit is contained in:
evgeny committed 2026-10-27 17:27:04 +01:00
1 parent 30a205340a
commit 44f6d8a5bc
2 files changed
+19 -4

No files matched your search

+2 -2
View File
@@ -131,13 +131,13 @@ void NodesPage::refreshNodes() {
const char* stage = "prepare";
QString failure;
sqlite3_stmt* st = nullptr;
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "Nodes refresh begin db=%p", static_cast<void*>(d));
int rc = sqlite3_prepare_v2(d,
"SELECT n.node_id,n.name,n.x25519_pubkey,n.ed25519_pubkey,n.last_seen_at,n.created_at,"
" a.node_id,a.family,a.protocol,a.address,a.port,a.rtt,a.nat_mapping,a.nat_inbound,a.nat_source"
" FROM nodes n LEFT JOIN node_addresses a ON a.node_id=n.node_id ORDER BY n.node_id,a.family,a.port",
-1, &st, nullptr);
std::unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)> statement(st, sqlite3_finalize);
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "Nodes refresh begin db=%p", static_cast<void*>(d));
if (rc == SQLITE_OK) {
stage = "step";
while ((rc = sqlite3_step(st)) == SQLITE_ROW) {
@@ -187,7 +187,7 @@ void NodesPage::refreshNodes() {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Nodes refresh failed stage=%s rc=%d finalize=%d node=%016llx: %s",
stage, rc, finalized, static_cast<unsigned long long>(currentNode), qPrintable(failure));
m_table->setRowCount(0);
m_dumpText->setPlainText(QCoreApplication::translate("ChatGui", "Query error") + ": " + failure);
m_dumpText->setPlainText(QCoreApplication::translate("ChatGui", "Query error"));
return;
}
+17 -2
View File
@@ -122,14 +122,29 @@ private slots:
}, &state), SQLITE_OK);
sqlite3_progress_handler(db.handle, 1, [](void* context) {
auto* state = static_cast<InterruptState*>(context);
if (state->afterRow && !state->rows) return 0;
if (state->afterRow && state->rows < 2) return 0;
state->interrupted = true; return 1;
}, &state);
page.refreshNodes(); QVERIFY(state.interrupted); if (afterRow) QVERIFY(state.rows > 0);
page.refreshNodes(); QVERIFY(state.interrupted); if (afterRow) QVERIFY(state.rows >= 2);
checkFailure(page); QVERIFY(!sqlite3_next_stmt(db.handle, nullptr));
sqlite3_progress_handler(db.handle, 0, nullptr, nullptr); sqlite3_trace_v2(db.handle, 0, nullptr, nullptr);
page.refreshNodes(); checkSnapshot(page);
}
void invalidAddress_data() {
QTest::addColumn<QByteArray>("update");
QTest::newRow("unknown-family") << QByteArray("family=7");
QTest::newRow("empty-blob") << QByteArray("address=x''");
QTest::newRow("text-instead-of-blob") << QByteArray("address='addr'");
}
void invalidAddress() {
QFETCH(QByteArray, update);
NodesDatabase db; QVERIFY(db.open()); NodesPage page(&db.manager);
page.refreshNodes(); checkSnapshot(page);
QVERIFY(db.execute(("UPDATE node_addresses SET " + update + " WHERE family=4").constData()));
page.refreshNodes(); checkFailure(page); QVERIFY(!sqlite3_next_stmt(db.handle, nullptr));
QVERIFY(db.execute("UPDATE node_addresses SET family=4,address=x'7F000001' WHERE protocol=1"));
page.refreshNodes(); checkSnapshot(page);
}
void disconnectedDatabase() {
NodesDatabase db; QVERIFY(db.open()); NodesPage page(&db.manager);
page.refreshNodes(); checkSnapshot(page); db.manager.setDb(nullptr); page.refreshNodes();