首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言動態構建 SQLite3 插入語句:官方推薦的安全做法

     編輯:關於C語言

在 C 語言中向 SQLite3 動態插入資料時,直接拼接 SQL 字串極易導致SQL 注入與特殊字元轉義錯誤。SQLite 官方文檔提供標準解法:sqlite3_mprintf() 格式化器,支援 %q 自動轉義單引號。

問題場景

假設變數 zText 包含使用者輸入:

char *zText = "It's a happy day!";  // 含單引號

若直接拼接:

// 危險!單引號會破壞 SQL 語法
char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%s')", zText);

生成的 SQL 為 INSERT INTO table VALUES('It's a happy day!'),語法錯誤。

官方推薦做法:%q 格式化符號

char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
sqlite3_exec(db, zSQL, 0, 0, 0);
sqlite3_free(zSQL);  // 必須釋放 mprintf 分配的記憶體

%q 會自動將字串中的單引號 ' 轉義為雙單引號 ''(SQL 標準轉義方式),生成安全 SQL:

INSERT INTO table VALUES('It''s a happy day!')

完整範例程式

#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    sqlite3 *db;
    if (sqlite3_open("test.db", &db) != SQLITE_OK) {
        fprintf(stderr, "Open failed: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    // 建表
    sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS notes (content TEXT);", 0, 0, 0);

    // 模擬使用者輸入
    char *inputs[] = {
        "Normal text",
        "It's a quote",
        "Special \"double\" quotes",
        "Semicolon; DROP TABLE notes;--"
    };

    for (int i = 0; i < 4; i++) {
        char *zSQL = sqlite3_mprintf("INSERT INTO notes VALUES('%q');", inputs[i]);
        char *errMsg = NULL;
        if (sqlite3_exec(db, zSQL, 0, 0, &errMsg) != SQLITE_OK) {
            fprintf(stderr, "Insert failed: %s\n", errMsg);
            sqlite3_free(errMsg);
        }
        sqlite3_free(zSQL);
    }

    // 驗證查詢
    sqlite3_exec(db, "SELECT * FROM notes;", 
        [](void*, int argc, char** argv, char**) {
            for (int i = 0; i < argc; i++) printf("%s ", argv[i] ? argv[i] : "NULL");
            printf("\n");
            return 0;
        }, 0, NULL);

    sqlite3_close(db);
    return 0;
}

關鍵要點總結

項目說明
sqlite3_mprintf類 printf,但自動分配記憶體並支援 SQLite 專用格式符
%q核心安全機制:單引號 → 雙單引號,防注入、防語法錯誤
%Q同 %q,但 NULL 指標輸出為 NULL 關鍵字而非空字串
記憶體管理回傳字串需呼叫 sqlite3_free() 釋放
參數化查詢更推薦使用 sqlite3_prepare_v2 + sqlite3_bind_text,完全避免字串拼接

進階:參數化查詢 (最佳實踐)

sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "INSERT INTO notes VALUES(?);", -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, zText, -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);

參數化查詢從根本上分離代碼與資料,效能更高(可重複執行預編譯語句),是生產環境首選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved