Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_auth_sqlite3AuthRead.c422 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Helper capture for the authorizer */7typedef struct AuthCapture {8  int ret;9  int nCall;10  int lastCode;11  const char *a1;12  const char *a2;13  const char *a3;14  const char *a4;15} AuthCapture;16 17static int testAuth(void *pArg, int code, const char *a1, const char *a2,18                    const char *a3, const char *a4){19  AuthCapture *cap = (AuthCapture*)pArg;20  cap->nCall++;21  cap->lastCode = code;22  cap->a1 = a1;23  cap->a2 = a2;24  cap->a3 = a3;25  cap->a4 = a4;26  return cap->ret;27}28 29/* Helpers to construct minimal structures needed by sqlite3AuthRead */30 31static Table* makeTestTable(sqlite3 *db, const char *zName,32                            const char **colNames, int nCol, int iPKey){33  Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));34  TEST_ASSERT_NOT_NULL(pTab);35  pTab->zName = sqlite3DbStrDup(db, zName);36  TEST_ASSERT_NOT_NULL(pTab->zName);37  pTab->nCol = (u16)nCol;38  if( nCol>0 ){39    pTab->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nCol);40    TEST_ASSERT_NOT_NULL(pTab->aCol);41    for(int i=0; i<nCol; i++){42      pTab->aCol[i].zCnName = sqlite3DbStrDup(db, colNames[i]);43      TEST_ASSERT_NOT_NULL(pTab->aCol[i].zCnName);44    }45  }46  pTab->iPKey = iPKey;47  return pTab;48}49 50static void freeTestTable(sqlite3 *db, Table *pTab){51  if( !pTab ) return;52  if( pTab->aCol ){53    for(int i=0; i<pTab->nCol; i++){54      if( pTab->aCol[i].zCnName ){55        sqlite3DbFree(db, (void*)pTab->aCol[i].zCnName);56      }57    }58    sqlite3DbFree(db, pTab->aCol);59  }60  if( pTab->zName ) sqlite3DbFree(db, pTab->zName);61  sqlite3DbFree(db, pTab);62}63 64static SrcList* makeSrcList1(sqlite3 *db, Table *pTab, int iCursor){65  SrcList *pList = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));66  TEST_ASSERT_NOT_NULL(pList);67  pList->nSrc = 1;68  pList->nAlloc = 1;69  pList->a[0].iCursor = iCursor;70  pList->a[0].pSTab = pTab;71  return pList;72}73 74static void freeSrcList(sqlite3 *db, SrcList *pList){75  if( pList ) sqlite3DbFree(db, pList);76}77 78static void initParse(Parse *pParse, sqlite3 *db, const char *zCtx){79  memset(pParse, 0, sizeof(*pParse));80  pParse->db = db;81  pParse->zAuthContext = zCtx;82}83 84void setUp(void) {85  /* empty */86}87 88void tearDown(void) {89  /* empty */90}91 92/* Test: basic OK authorization with explicit column index */93void test_sqlite3AuthRead_basic_ok(void){94  sqlite3 *db = 0;95  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));96  AuthCapture cap = {0};97  cap.ret = SQLITE_OK;98  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));99 100  const char *cols[] = {"id","name"};101  Table *pTab = makeTestTable(db, "T", cols, 2, -1);102  SrcList *pList = makeSrcList1(db, pTab, 5);103 104  Parse sParse; initParse(&sParse, db, "ctx");105  Expr e; memset(&e, 0, sizeof(e));106  e.op = TK_COLUMN;107  e.iTable = 5;108  e.iColumn = 1; /* "name" */109  Schema *pSchema = db->aDb[0].pSchema;110 111  sqlite3AuthRead(&sParse, &e, pSchema, pList);112 113  TEST_ASSERT_EQUAL_INT(1, cap.nCall);114  TEST_ASSERT_EQUAL_INT(SQLITE_READ, cap.lastCode);115  TEST_ASSERT_NOT_NULL(cap.a1);116  TEST_ASSERT_NOT_NULL(cap.a2);117  TEST_ASSERT_NOT_NULL(cap.a3);118  TEST_ASSERT_NOT_NULL(cap.a4);119  TEST_ASSERT_EQUAL_STRING("T", cap.a1);120  TEST_ASSERT_EQUAL_STRING("name", cap.a2);121  TEST_ASSERT_EQUAL_STRING(db->aDb[0].zDbSName, cap.a3); /* usually "main" */122  TEST_ASSERT_EQUAL_STRING("ctx", cap.a4);123 124  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);125  TEST_ASSERT_EQUAL_INT(0, sParse.rc);126  TEST_ASSERT_NULL(sParse.zErrMsg);127 128  sqlite3_set_authorizer(db, NULL, NULL);129  sqlite3DbFree(db, sParse.zErrMsg);130  freeSrcList(db, pList);131  freeTestTable(db, pTab);132  sqlite3_close(db);133}134 135/* Test: SQLITE_IGNORE causes TK_NULL */136void test_sqlite3AuthRead_ignore_sets_null(void){137  sqlite3 *db = 0;138  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));139  AuthCapture cap = {0};140  cap.ret = SQLITE_IGNORE;141  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));142 143  const char *cols[] = {"id","name"};144  Table *pTab = makeTestTable(db, "T", cols, 2, -1);145  SrcList *pList = makeSrcList1(db, pTab, 3);146 147  Parse sParse; initParse(&sParse, db, "ctx");148  Expr e; memset(&e, 0, sizeof(e));149  e.op = TK_COLUMN;150  e.iTable = 3;151  e.iColumn = 0; /* "id" */152  Schema *pSchema = db->aDb[0].pSchema;153 154  sqlite3AuthRead(&sParse, &e, pSchema, pList);155 156  TEST_ASSERT_EQUAL_INT(1, cap.nCall);157  TEST_ASSERT_EQUAL_INT(TK_NULL, e.op);158  TEST_ASSERT_EQUAL_INT(0, sParse.rc);159  TEST_ASSERT_NULL(sParse.zErrMsg);160 161  sqlite3_set_authorizer(db, NULL, NULL);162  sqlite3DbFree(db, sParse.zErrMsg);163  freeSrcList(db, pList);164  freeTestTable(db, pTab);165  sqlite3_close(db);166}167 168/* Test: SQLITE_DENY results in parse error and no op change */169void test_sqlite3AuthRead_deny_sets_parse_error(void){170  sqlite3 *db = 0;171  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));172  AuthCapture cap = {0};173  cap.ret = SQLITE_DENY;174  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));175 176  const char *cols[] = {"id","name"};177  Table *pTab = makeTestTable(db, "T", cols, 2, -1);178  SrcList *pList = makeSrcList1(db, pTab, 1);179 180  Parse sParse; initParse(&sParse, db, "ctx");181  Expr e; memset(&e, 0, sizeof(e));182  e.op = TK_COLUMN;183  e.iTable = 1;184  e.iColumn = 1; /* "name" */185  Schema *pSchema = db->aDb[0].pSchema;186 187  sqlite3AuthRead(&sParse, &e, pSchema, pList);188 189  TEST_ASSERT_EQUAL_INT(1, cap.nCall);190  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);191  TEST_ASSERT_EQUAL_INT(SQLITE_AUTH, sParse.rc);192  TEST_ASSERT_NOT_NULL(sParse.zErrMsg);193  TEST_ASSERT_NOT_NULL(strstr(sParse.zErrMsg, "prohibited"));194  TEST_ASSERT_NOT_NULL(strstr(sParse.zErrMsg, "T.name"));195 196  sqlite3_set_authorizer(db, NULL, NULL);197  sqlite3DbFree(db, sParse.zErrMsg);198  freeSrcList(db, pList);199  freeTestTable(db, pTab);200  sqlite3_close(db);201}202 203/* Test: Invalid authorizer return yields "authorizer malfunction" and SQLITE_ERROR */204void test_sqlite3AuthRead_invalid_code_sets_malfunction(void){205  sqlite3 *db = 0;206  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));207  AuthCapture cap = {0};208  cap.ret = 12345; /* invalid */209  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));210 211  const char *cols[] = {"id","name"};212  Table *pTab = makeTestTable(db, "T", cols, 2, -1);213  SrcList *pList = makeSrcList1(db, pTab, 7);214 215  Parse sParse; initParse(&sParse, db, "ctx");216  Expr e; memset(&e, 0, sizeof(e));217  e.op = TK_COLUMN;218  e.iTable = 7;219  e.iColumn = 0; /* "id" */220  Schema *pSchema = db->aDb[0].pSchema;221 222  sqlite3AuthRead(&sParse, &e, pSchema, pList);223 224  TEST_ASSERT_EQUAL_INT(1, cap.nCall);225  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);226  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, sParse.rc);227  TEST_ASSERT_NOT_NULL(sParse.zErrMsg);228  TEST_ASSERT_NOT_NULL(strstr(sParse.zErrMsg, "authorizer malfunction"));229 230  sqlite3_set_authorizer(db, NULL, NULL);231  sqlite3DbFree(db, sParse.zErrMsg);232  freeSrcList(db, pList);233  freeTestTable(db, pTab);234  sqlite3_close(db);235}236 237/* Test: iColumn < 0 uses PRIMARY KEY name when iPKey>=0 */238void test_sqlite3AuthRead_uses_pk_when_iColumn_neg(void){239  sqlite3 *db = 0;240  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));241  AuthCapture cap = {0};242  cap.ret = SQLITE_OK;243  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));244 245  const char *cols[] = {"id","name"};246  Table *pTab = makeTestTable(db, "T", cols, 2, 0); /* iPKey = column 0 "id" */247  SrcList *pList = makeSrcList1(db, pTab, 9);248 249  Parse sParse; initParse(&sParse, db, "ctx");250  Expr e; memset(&e, 0, sizeof(e));251  e.op = TK_COLUMN;252  e.iTable = 9;253  e.iColumn = -1; /* will resolve to PK column name "id" */254  Schema *pSchema = db->aDb[0].pSchema;255 256  sqlite3AuthRead(&sParse, &e, pSchema, pList);257 258  TEST_ASSERT_EQUAL_INT(1, cap.nCall);259  TEST_ASSERT_EQUAL_STRING("id", cap.a2); /* column argument should be PK name */260  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);261  TEST_ASSERT_EQUAL_INT(0, sParse.rc);262  TEST_ASSERT_NULL(sParse.zErrMsg);263 264  sqlite3_set_authorizer(db, NULL, NULL);265  sqlite3DbFree(db, sParse.zErrMsg);266  freeSrcList(db, pList);267  freeTestTable(db, pTab);268  sqlite3_close(db);269}270 271/* Test: iColumn < 0 and no PK uses "ROWID" */272void test_sqlite3AuthRead_uses_rowid_when_no_pk(void){273  sqlite3 *db = 0;274  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));275  AuthCapture cap = {0};276  cap.ret = SQLITE_OK;277  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));278 279  const char *cols[] = {"c1","c2"};280  Table *pTab = makeTestTable(db, "T", cols, 2, -1); /* no PK */281  SrcList *pList = makeSrcList1(db, pTab, 2);282 283  Parse sParse; initParse(&sParse, db, "ctx");284  Expr e; memset(&e, 0, sizeof(e));285  e.op = TK_COLUMN;286  e.iTable = 2;287  e.iColumn = -1; /* will resolve to "ROWID" */288  Schema *pSchema = db->aDb[0].pSchema;289 290  sqlite3AuthRead(&sParse, &e, pSchema, pList);291 292  TEST_ASSERT_EQUAL_INT(1, cap.nCall);293  TEST_ASSERT_NOT_NULL(cap.a2);294  TEST_ASSERT_EQUAL_INT(0, strcmp(cap.a2, "ROWID"));295  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);296  TEST_ASSERT_EQUAL_INT(0, sParse.rc);297  TEST_ASSERT_NULL(sParse.zErrMsg);298 299  sqlite3_set_authorizer(db, NULL, NULL);300  sqlite3DbFree(db, sParse.zErrMsg);301  freeSrcList(db, pList);302  freeTestTable(db, pTab);303  sqlite3_close(db);304}305 306/* Test: TK_TRIGGER path uses pParse->pTriggerTab and respects IGNORE */307void test_sqlite3AuthRead_trigger_context_ignore_to_null(void){308  sqlite3 *db = 0;309  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));310  AuthCapture cap = {0};311  cap.ret = SQLITE_IGNORE;312  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));313 314  const char *cols[] = {"a","b"};315  Table *pTab = makeTestTable(db, "TrigTab", cols, 2, -1);316 317  Parse sParse; initParse(&sParse, db, "ctx");318  sParse.pTriggerTab = pTab;319 320  Expr e; memset(&e, 0, sizeof(e));321  e.op = TK_TRIGGER;322  e.iColumn = 1; /* "b" */323  Schema *pSchema = db->aDb[0].pSchema;324 325  sqlite3AuthRead(&sParse, &e, pSchema, NULL);326 327  TEST_ASSERT_EQUAL_INT(1, cap.nCall);328  TEST_ASSERT_EQUAL_STRING("TrigTab", cap.a1);329  TEST_ASSERT_EQUAL_STRING("b", cap.a2);330  TEST_ASSERT_EQUAL_INT(TK_NULL, e.op);331  TEST_ASSERT_EQUAL_INT(0, sParse.rc);332  TEST_ASSERT_NULL(sParse.zErrMsg);333 334  sqlite3_set_authorizer(db, NULL, NULL);335  sqlite3DbFree(db, sParse.zErrMsg);336  freeTestTable(db, pTab);337  sqlite3_close(db);338}339 340/* Test: schema not found (iDb<0) -> no authorizer call, no changes */341void test_sqlite3AuthRead_schema_not_found_no_call(void){342  sqlite3 *db = 0;343  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));344  AuthCapture cap = {0};345  cap.ret = SQLITE_OK;346  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));347 348  const char *cols[] = {"x"};349  Table *pTab = makeTestTable(db, "T", cols, 1, -1);350  SrcList *pList = makeSrcList1(db, pTab, 4);351 352  Parse sParse; initParse(&sParse, db, "ctx");353  Expr e; memset(&e, 0, sizeof(e));354  e.op = TK_COLUMN;355  e.iTable = 4;356  e.iColumn = 0;357 358  /* Create a Schema not attached to db so sqlite3SchemaToIndex returns -1 */359  Schema *pFakeSchema = (Schema*)sqlite3DbMallocZero(db, sizeof(Schema));360  TEST_ASSERT_NOT_NULL(pFakeSchema);361 362  sqlite3AuthRead(&sParse, &e, pFakeSchema, pList);363 364  TEST_ASSERT_EQUAL_INT(0, cap.nCall);365  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);366  TEST_ASSERT_EQUAL_INT(0, sParse.rc);367  TEST_ASSERT_NULL(sParse.zErrMsg);368 369  sqlite3_set_authorizer(db, NULL, NULL);370  sqlite3DbFree(db, pFakeSchema);371  sqlite3DbFree(db, sParse.zErrMsg);372  freeSrcList(db, pList);373  freeTestTable(db, pTab);374  sqlite3_close(db);375}376 377/* Test: table not found in SrcList (cursor mismatch) -> no authorizer call */378void test_sqlite3AuthRead_table_not_found_no_call(void){379  sqlite3 *db = 0;380  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));381  AuthCapture cap = {0};382  cap.ret = SQLITE_OK;383  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_set_authorizer(db, testAuth, &cap));384 385  const char *cols[] = {"c1","c2"};386  Table *pTab = makeTestTable(db, "T", cols, 2, -1);387  SrcList *pList = makeSrcList1(db, pTab, 10); /* iCursor=10 */388 389  Parse sParse; initParse(&sParse, db, "ctx");390  Expr e; memset(&e, 0, sizeof(e));391  e.op = TK_COLUMN;392  e.iTable = 11; /* mismatch: no entry with iCursor=11 */393  e.iColumn = 0;394  Schema *pSchema = db->aDb[0].pSchema;395 396  sqlite3AuthRead(&sParse, &e, pSchema, pList);397 398  TEST_ASSERT_EQUAL_INT(0, cap.nCall);399  TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op);400  TEST_ASSERT_EQUAL_INT(0, sParse.rc);401  TEST_ASSERT_NULL(sParse.zErrMsg);402 403  sqlite3_set_authorizer(db, NULL, NULL);404  sqlite3DbFree(db, sParse.zErrMsg);405  freeSrcList(db, pList);406  freeTestTable(db, pTab);407  sqlite3_close(db);408}409 410int main(void){411  UNITY_BEGIN();412  RUN_TEST(test_sqlite3AuthRead_basic_ok);413  RUN_TEST(test_sqlite3AuthRead_ignore_sets_null);414  RUN_TEST(test_sqlite3AuthRead_deny_sets_parse_error);415  RUN_TEST(test_sqlite3AuthRead_invalid_code_sets_malfunction);416  RUN_TEST(test_sqlite3AuthRead_uses_pk_when_iColumn_neg);417  RUN_TEST(test_sqlite3AuthRead_uses_rowid_when_no_pk);418  RUN_TEST(test_sqlite3AuthRead_trigger_context_ignore_to_null);419  RUN_TEST(test_sqlite3AuthRead_schema_not_found_no_call);420  RUN_TEST(test_sqlite3AuthRead_table_not_found_no_call);421  return UNITY_END();422}