AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6typedef struct AuthState {7 int call_count;8 int last_code;9 const char *last_zArg1;10 const char *last_zArg2;11 const char *last_zArg3;12 const char *last_zAuthContext;13 int return_code;14} AuthState;15 16static sqlite3 *gDb = NULL;17static AuthState gAuth;18 19static int testAuthorizer(void *pArg, int code,20 const char *z1, const char *z2,21 const char *z3, const char *z4){22 AuthState *st = (AuthState*)pArg;23 st->call_count++;24 st->last_code = code;25 st->last_zArg1 = z1;26 st->last_zArg2 = z2;27 st->last_zArg3 = z3;28 st->last_zAuthContext = z4;29 return st->return_code;30}31 32static void initParse(Parse *pParse, const char *zCtx){33 memset(pParse, 0, sizeof(*pParse));34 pParse->db = gDb;35 pParse->zAuthContext = zCtx;36}37 38void setUp(void) {39 int rc = sqlite3_open(":memory:", &gDb);40 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");41 memset(&gAuth, 0, sizeof(gAuth));42 gAuth.return_code = SQLITE_OK;43 rc = sqlite3_set_authorizer(gDb, testAuthorizer, &gAuth);44 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_set_authorizer failed");45}46 47void tearDown(void) {48 /* Clear authorizer and close DB */49 sqlite3_set_authorizer(gDb, NULL, NULL);50 if( gDb ){51 sqlite3_close(gDb);52 gDb = NULL;53 }54}55 56/* Authorizer OK: proper args and no errors */57void test_sqlite3AuthReadCol_ok_passes_args(void){58 Parse p;59 initParse(&p, "CTX");60 gAuth.return_code = SQLITE_OK;61 62 const char *zTab = "t1";63 const char *zCol = "c1";64 int iDb = 0;65 66 int rc = sqlite3AuthReadCol(&p, zTab, zCol, iDb);67 68 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);69 TEST_ASSERT_EQUAL_INT(1, gAuth.call_count);70 TEST_ASSERT_EQUAL_INT(SQLITE_READ, gAuth.last_code);71 TEST_ASSERT_EQUAL_STRING(zTab, gAuth.last_zArg1);72 TEST_ASSERT_EQUAL_STRING(zCol, gAuth.last_zArg2);73 TEST_ASSERT_NOT_NULL(gAuth.last_zArg3);74 TEST_ASSERT_EQUAL_STRING(p.zAuthContext, gAuth.last_zAuthContext);75 TEST_ASSERT_EQUAL_STRING(gDb->aDb[iDb].zDbSName, gAuth.last_zArg3);76 TEST_ASSERT_EQUAL_INT(0, p.rc);77 TEST_ASSERT_NULL(p.zErrMsg);78}79 80/* Authorizer IGNORE: propagate and no errors */81void test_sqlite3AuthReadCol_ignore_no_error(void){82 Parse p;83 initParse(&p, "CTX-IGNORE");84 gAuth.return_code = SQLITE_IGNORE;85 86 int rc = sqlite3AuthReadCol(&p, "t1", "c1", 0);87 88 TEST_ASSERT_EQUAL_INT(SQLITE_IGNORE, rc);89 TEST_ASSERT_EQUAL_INT(1, gAuth.call_count);90 TEST_ASSERT_EQUAL_INT(0, p.rc);91 TEST_ASSERT_NULL(p.zErrMsg);92}93 94/* Authorizer DENY, main db (iDb=0), nDb<=2: message without schema prefix */95void test_sqlite3AuthReadCol_deny_no_prefix_for_main_db_when_nDb_le_2(void){96 Parse p;97 initParse(&p, "CTX-DENY");98 gAuth.return_code = SQLITE_DENY;99 100 /* Ensure nDb <= 2 for this test (default is typically 2) */101 int origNDb = gDb->nDb;102 if( gDb->nDb > 2 ) gDb->nDb = 2;103 104 const char *zTab = "t1";105 const char *zCol = "c1";106 int rc = sqlite3AuthReadCol(&p, zTab, zCol, 0);107 108 TEST_ASSERT_EQUAL_INT(SQLITE_DENY, rc);109 TEST_ASSERT_EQUAL_INT(SQLITE_AUTH, p.rc);110 TEST_ASSERT_NOT_NULL(p.zErrMsg);111 TEST_ASSERT_EQUAL_STRING("access to t1.c1 is prohibited", p.zErrMsg);112 113 sqlite3DbFree(gDb, p.zErrMsg); p.zErrMsg = 0;114 gDb->nDb = origNDb;115}116 117/* Authorizer DENY, temp db (iDb=1): message should include schema prefix */118void test_sqlite3AuthReadCol_deny_includes_schema_prefix_for_temp_db(void){119 Parse p;120 initParse(&p, "CTX-DENY-TEMP");121 gAuth.return_code = SQLITE_DENY;122 123 const char *zTab = "t1";124 const char *zCol = "c1";125 int iDb = 1; /* temp schema */126 const char *zSchema = gDb->aDb[iDb].zDbSName;127 128 int rc = sqlite3AuthReadCol(&p, zTab, zCol, iDb);129 130 TEST_ASSERT_EQUAL_INT(SQLITE_DENY, rc);131 TEST_ASSERT_EQUAL_INT(SQLITE_AUTH, p.rc);132 TEST_ASSERT_NOT_NULL(p.zErrMsg);133 134 char expected[256];135 snprintf(expected, sizeof(expected), "access to %s.%s.%s is prohibited", zSchema, zTab, zCol);136 TEST_ASSERT_EQUAL_STRING(expected, p.zErrMsg);137 138 sqlite3DbFree(gDb, p.zErrMsg); p.zErrMsg = 0;139}140 141/* Authorizer DENY, main db but nDb>2: message should include schema prefix */142void test_sqlite3AuthReadCol_deny_includes_schema_prefix_when_nDb_gt_2(void){143 Parse p;144 initParse(&p, "CTX-DENY-MULTI");145 gAuth.return_code = SQLITE_DENY;146 147 int iDb = 0; /* main */148 const char *zSchema = gDb->aDb[iDb].zDbSName;149 150 int origNDb = gDb->nDb;151 if( origNDb <= 2 ) gDb->nDb = 3; /* force condition to include prefix */152 153 int rc = sqlite3AuthReadCol(&p, "t1", "c1", iDb);154 155 TEST_ASSERT_EQUAL_INT(SQLITE_DENY, rc);156 TEST_ASSERT_EQUAL_INT(SQLITE_AUTH, p.rc);157 TEST_ASSERT_NOT_NULL(p.zErrMsg);158 159 char expected[256];160 snprintf(expected, sizeof(expected), "access to %s.%s.%s is prohibited", zSchema, "t1", "c1");161 TEST_ASSERT_EQUAL_STRING(expected, p.zErrMsg);162 163 sqlite3DbFree(gDb, p.zErrMsg); p.zErrMsg = 0;164 gDb->nDb = origNDb;165}166 167/* Illegal authorizer return code: sets "authorizer malfunction" and SQLITE_ERROR */168void test_sqlite3AuthReadCol_illegal_return_code_sets_error(void){169 Parse p;170 initParse(&p, "CTX-BAD");171 gAuth.return_code = 123456; /* invalid code */172 173 int rc = sqlite3AuthReadCol(&p, "t1", "c1", 0);174 175 TEST_ASSERT_EQUAL_INT(123456, rc);176 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, p.rc);177 TEST_ASSERT_NOT_NULL(p.zErrMsg);178 TEST_ASSERT_EQUAL_STRING("authorizer malfunction", p.zErrMsg);179 180 sqlite3DbFree(gDb, p.zErrMsg); p.zErrMsg = 0;181}182 183/* When db->init.busy is true, authorizer is not called and SQLITE_OK is returned */184void test_sqlite3AuthReadCol_init_busy_short_circuits(void){185 Parse p;186 initParse(&p, "CTX-BUSY");187 gAuth.return_code = SQLITE_DENY; /* would be denied if called */188 gAuth.call_count = 0;189 190 u8 origBusy = gDb->init.busy;191 gDb->init.busy = 1;192 193 int rc = sqlite3AuthReadCol(&p, "t1", "c1", 0);194 195 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);196 TEST_ASSERT_EQUAL_INT(0, gAuth.call_count);197 TEST_ASSERT_EQUAL_INT(0, p.rc);198 TEST_ASSERT_NULL(p.zErrMsg);199 200 gDb->init.busy = origBusy;201}202 203int main(void){204 UNITY_BEGIN();205 RUN_TEST(test_sqlite3AuthReadCol_ok_passes_args);206 RUN_TEST(test_sqlite3AuthReadCol_ignore_no_error);207 RUN_TEST(test_sqlite3AuthReadCol_deny_no_prefix_for_main_db_when_nDb_le_2);208 RUN_TEST(test_sqlite3AuthReadCol_deny_includes_schema_prefix_for_temp_db);209 RUN_TEST(test_sqlite3AuthReadCol_deny_includes_schema_prefix_when_nDb_gt_2);210 RUN_TEST(test_sqlite3AuthReadCol_illegal_return_code_sets_error);211 RUN_TEST(test_sqlite3AuthReadCol_init_busy_short_circuits);212 return UNITY_END();213}