From 985ff47c84fada0d2e48c96b683ddc292ae58278 Mon Sep 17 00:00:00 2001 From: qing <1776177662@qq.com> Date: Thu, 6 Aug 2026 18:07:06 +0000 Subject: [PATCH] =?UTF-8?q?fix(libsqlite3):=20=E4=BF=AE=E5=A4=8D=20double?= =?UTF-8?q?=20free=20=E4=B8=8E=E7=A7=BB=E5=8A=A8=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E7=BC=BA=E9=99=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 Sqlite3 与 Sqlite3_stmt 显式 delete 拷贝、实现 noexcept 移动构造/赋值 - 析构函数判空后释放,防止重复释放与 use-after-free - ~Sqlite3() 改用 sqlite3_close_v2,确保所有 statement 释放后再关闭 - stmt() 参数改为 const std::string&,支持字符串字面量 - 成员指针显式初始化为 nullptr,errMsg 初始化为 nullptr --- libsqlite3/inc/us/Sqlite3.hpp | 51 ++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/libsqlite3/inc/us/Sqlite3.hpp b/libsqlite3/inc/us/Sqlite3.hpp index fbcb14a..e91ca36 100644 --- a/libsqlite3/inc/us/Sqlite3.hpp +++ b/libsqlite3/inc/us/Sqlite3.hpp @@ -15,7 +15,26 @@ namespace qing { } ~Sqlite3_stmt() { - sqlite3_finalize(stmt); + if (stmt) { + sqlite3_finalize(stmt); + stmt = nullptr; + } + } + + Sqlite3_stmt(const Sqlite3_stmt&) = delete; + Sqlite3_stmt& operator=(const Sqlite3_stmt&) = delete; + + Sqlite3_stmt(Sqlite3_stmt&& other) noexcept : stmt(other.stmt) { + other.stmt = nullptr; + } + + Sqlite3_stmt& operator=(Sqlite3_stmt&& other) noexcept { + if (this != &other) { + if (stmt) sqlite3_finalize(stmt); + stmt = other.stmt; + other.stmt = nullptr; + } + return *this; } void bind_int(int idx, int data) { @@ -56,7 +75,7 @@ namespace qing { } private: - sqlite3_stmt* stmt; + sqlite3_stmt* stmt = nullptr; }; class Sqlite3 { @@ -72,27 +91,45 @@ namespace qing { } ~Sqlite3() { - sqlite3_close(db); + if (db) { + sqlite3_close_v2(db); + db = nullptr; + } + } + + Sqlite3(const Sqlite3&) = delete; + Sqlite3& operator=(const Sqlite3&) = delete; + + Sqlite3(Sqlite3&& other) noexcept : db(other.db) { + other.db = nullptr; + } + + Sqlite3& operator=(Sqlite3&& other) noexcept { + if (this != &other) { + if (db) sqlite3_close_v2(db); + db = other.db; + other.db = nullptr; + } + return *this; } bool exec(const std::string& sql) { - char *errMsg; + char *errMsg = nullptr; int rc = sqlite3_exec(db, sql.c_str(), 0, 0, &errMsg); if (rc != SQLITE_OK) { std::cerr << "Failed to execute at sqlite3: " << errMsg << std::endl; sqlite3_free(errMsg); - //sqlite3_close(db); return false; } return true; } - Sqlite3_stmt stmt(std::string& sql) { + Sqlite3_stmt stmt(const std::string& sql) { return Sqlite3_stmt(db, sql.c_str()); } private: - sqlite3* db; + sqlite3* db = nullptr; }; }