How to make SQLite SELECT query in C correctly?

Deadly 提交于 2021-01-29 17:03:18

问题


I want to make query like this one:

SELECT lyrics FROM cache WHERE author=%s0, title=%s1 LIMIT 1;

where strings %s0 and %s1 should be substituted. Assuming strings are not sanitized, UTF-8 encoded (As database itself), simple null-terminated char* arrays. What are my options to do this? Are there any built-in functions in SQLite (C API) for this?


回答1:


Like mentioned in comments already prepared statements should be used.

Why Prepared Statements Should Be Favoured

When you create SQL queries yourself as a string, they almost always contain parts of a user's input. An attacker can take advantage of this by, for example, cleverly changing the semantics of the query using ' and thus gaining unauthorized access to data or destroying data.

This is called SQL injection and is one of the top most critical security risks, see here: https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf

Defense

The use of prepared statements with variable binding (aka parameterized queries) is how all developers should first be taught how to write database queries.

https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html#defense-option-1-prepared-statements-with-parameterized-queries

How to use prepared statements with SQLite

For prepared statements see https://www.sqlite.org/c3ref/stmt.html.

Basic steps are:

  • create the prepared statement
  • bind values to parameters
  • run the SQL
  • destroy the object to avoid resource leaks

Example

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

void exit_with_error(sqlite3 *db, const char * msg) {
    fprintf(stderr, "%s: %s\n", msg, sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
}

int main() {
    sqlite3 *db;
    sqlite3_stmt *stmt;

    int rc = sqlite3_open("path-to-lyrics", &db);

    if (rc != SQLITE_OK)
        exit_with_error(db, "can't open db: ");

    //create prepared statement
    rc = sqlite3_prepare_v2(db, "SELECT lyrics FROM cache WHERE author=?1 AND title=?2 LIMIT 1;", -1, &stmt, 0);
    if (rc != SQLITE_OK)
        exit_with_error(db, "failure fetching data: ");

    //bind values to parameters
    sqlite3_bind_text(stmt, 1, "Don Brownrigg", -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, "Just Breathe", -1, SQLITE_STATIC);

    //run the SQL
    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) {
        printf("%s\n", sqlite3_column_text(stmt, 0));
    }

    //destroy the object to avoid resource leaks
    sqlite3_finalize(stmt);

    sqlite3_close(db);    

    return 0;
}

Build

With CMake it could look like this:

cmake_minimum_required(VERSION 3.14)
project(sqlitequery C)

set(CMAKE_C_STANDARD 99)

add_executable(sqlitequery main.c)

target_link_libraries (sqlitequery sqlite3)

On command line one could build with something like:

gcc -Wall -Wextra main.c -lsqlite3 -o sqlitequery


来源:https://stackoverflow.com/questions/57505263/how-to-make-sqlite-select-query-in-c-correctly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!