AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6 7static sqlite3 *gDb = NULL;8 9static void assert_str_contains(const char *haystack, const char *needle){10 TEST_ASSERT_NOT_NULL(haystack);11 TEST_ASSERT_NOT_NULL(needle);12 TEST_ASSERT_NOT_NULL_MESSAGE(strstr(haystack, needle), "Expected substring not found in message");13}14 15void setUp(void) {16 int rc = sqlite3_open(":memory:", &gDb);17 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");18 /* Ensure extension loading is disabled by default for a known baseline */19 rc = sqlite3_enable_load_extension(gDb, 0);20 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21}22 23void tearDown(void) {24 if( gDb ){25 int rc = sqlite3_close(gDb);26 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_close failed");27 gDb = NULL;28 }29}30 31/* Test: with loading disabled, should return SQLITE_ERROR and "not authorized" */32void test_sqlite3_load_extension_requires_enable(void) {33 char *zErr = NULL;34 int rc = sqlite3_load_extension(gDb, "definitely_missing_extension_file_xyz", NULL, &zErr);35 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);36 TEST_ASSERT_NOT_NULL(zErr);37 assert_str_contains(zErr, "not authorized");38 sqlite3_free(zErr);39}40 41/* Test: when enabled, loading a missing file fails gracefully with proper message */42void test_sqlite3_load_extension_unable_to_open_when_enabled(void) {43 int rc = sqlite3_enable_load_extension(gDb, 1);44 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);45 46 char *zErr = NULL;47 rc = sqlite3_load_extension(gDb, "definitely_missing_extension_file_xyz", NULL, &zErr);48 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);49 TEST_ASSERT_NOT_NULL(zErr);50 assert_str_contains(zErr, "unable to open shared library");51 sqlite3_free(zErr);52}53 54/* Test: passing NULL for pzErrMsg should not crash and still return error */55void test_sqlite3_load_extension_null_errmsg_pointer(void) {56 int rc = sqlite3_enable_load_extension(gDb, 1);57 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);58 59 rc = sqlite3_load_extension(gDb, "still_missing_extension_abc", NULL, NULL);60 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);61}62 63/* Test: empty filename is rejected */64void test_sqlite3_load_extension_empty_filename(void) {65 int rc = sqlite3_enable_load_extension(gDb, 1);66 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);67 68 char *zErr = NULL;69 rc = sqlite3_load_extension(gDb, "", NULL, &zErr);70 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);71 TEST_ASSERT_NOT_NULL(zErr);72 assert_str_contains(zErr, "unable to open shared library");73 sqlite3_free(zErr);74}75 76/* Test: overly long filename (> SQLITE_MAX_PATHLEN) is rejected */77void test_sqlite3_load_extension_very_long_filename(void) {78 int rc = sqlite3_enable_load_extension(gDb, 1);79 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);80 81 size_t n = (size_t)SQLITE_MAX_PATHLEN + 50;82 char *fname = (char*)sqlite3_malloc64(n + 1);83 TEST_ASSERT_NOT_NULL(fname);84 memset(fname, 'a', n);85 fname[n] = '\0';86 87 char *zErr = NULL;88 rc = sqlite3_load_extension(gDb, fname, NULL, &zErr);89 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);90 TEST_ASSERT_NOT_NULL(zErr);91 assert_str_contains(zErr, "unable to open shared library");92 sqlite3_free(zErr);93 sqlite3_free(fname);94}95 96/* Test: disabling after enabling restores "not authorized" behavior */97void test_sqlite3_load_extension_disable_restores_protection(void) {98 int rc = sqlite3_enable_load_extension(gDb, 1);99 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);100 101 rc = sqlite3_enable_load_extension(gDb, 0);102 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);103 104 char *zErr = NULL;105 rc = sqlite3_load_extension(gDb, "definitely_missing_extension_file_xyz", NULL, &zErr);106 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);107 TEST_ASSERT_NOT_NULL(zErr);108 assert_str_contains(zErr, "not authorized");109 sqlite3_free(zErr);110}111 112/* Test: database remains usable after a failed load attempt */113void test_sqlite3_load_extension_db_remains_usable_after_failure(void) {114 int rc = sqlite3_enable_load_extension(gDb, 1);115 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);116 117 /* Trigger a failure */118 char *zErr = NULL;119 rc = sqlite3_load_extension(gDb, "no_such_ext_zzz", NULL, &zErr);120 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);121 sqlite3_free(zErr);122 123 /* Verify DB is still fully functional */124 sqlite3_stmt *pStmt = NULL;125 rc = sqlite3_prepare_v2(gDb, "SELECT 1;", -1, &pStmt, NULL);126 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);127 rc = sqlite3_step(pStmt);128 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);129 TEST_ASSERT_EQUAL_INT(1, sqlite3_column_int(pStmt, 0));130 rc = sqlite3_finalize(pStmt);131 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);132}133 134int main(void) {135 UNITY_BEGIN();136 RUN_TEST(test_sqlite3_load_extension_requires_enable);137 RUN_TEST(test_sqlite3_load_extension_unable_to_open_when_enabled);138 RUN_TEST(test_sqlite3_load_extension_null_errmsg_pointer);139 RUN_TEST(test_sqlite3_load_extension_empty_filename);140 RUN_TEST(test_sqlite3_load_extension_very_long_filename);141 RUN_TEST(test_sqlite3_load_extension_disable_restores_protection);142 RUN_TEST(test_sqlite3_load_extension_db_remains_usable_after_failure);143 return UNITY_END();144}