Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_delete_vtabIsReadOnly.c205 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Prototype of the provided test wrapper for the static function */7int test_vtabIsReadOnly(Parse *pParse, Table *pTab);8 9/* Stub xUpdate implementation to indicate write-capable virtual table */10static int stub_xUpdate(sqlite3_vtab* pVtab, int op, sqlite3_value** argv, sqlite_int64* pRowid){11  (void)pVtab; (void)op; (void)argv; (void)pRowid;12  return SQLITE_OK;13}14 15/* Helpers to build a minimal virtual table environment */16static void initParse(sqlite3 *db, Parse *pParse, int inTrigger, int trustedOn){17  memset(pParse, 0, sizeof(Parse));18  pParse->db = db;19  if( inTrigger ){20    /* Any non-NULL indicates we are within a trigger's parse context */21    pParse->pToplevel = pParse;22  }else{23    pParse->pToplevel = 0;24  }25  /* Set or clear the trusted schema flag */26  if( trustedOn ){27    db->flags |= SQLITE_TrustedSchema;28  }else{29    db->flags &= ~SQLITE_TrustedSchema;30  }31}32 33static void setupVirtualTable(sqlite3 *db, Table *pTab, const char *zName,34                              int hasXUpdate, int eRisk,35                              VTable **ppVT, Module **ppMod, struct sqlite3_module **ppIface){36  VTable *pVT = (VTable*)sqlite3_malloc(sizeof(VTable));37  Module *pMod = (Module*)sqlite3_malloc(sizeof(Module));38  struct sqlite3_module *pIface = (struct sqlite3_module*)sqlite3_malloc(sizeof(struct sqlite3_module));39 40  TEST_ASSERT_NOT_NULL_MESSAGE(pVT, "Alloc VTable failed");41  TEST_ASSERT_NOT_NULL_MESSAGE(pMod, "Alloc Module failed");42  TEST_ASSERT_NOT_NULL_MESSAGE(pIface, "Alloc sqlite3_module failed");43 44  memset(pVT, 0, sizeof(VTable));45  memset(pMod, 0, sizeof(Module));46  memset(pIface, 0, sizeof(struct sqlite3_module));47 48  /* Configure the module interface: only xUpdate matters here */49  if( hasXUpdate ){50    pIface->xUpdate = stub_xUpdate;51  }else{52    pIface->xUpdate = 0;53  }54 55  pMod->pModule = pIface;56 57  pVT->db = db;58  pVT->pMod = pMod;59  pVT->eVtabRisk = eRisk;60 61  memset(pTab, 0, sizeof(Table));62  pTab->zName = zName ? zName : "vtab";63  pTab->tabFlags = TF_Virtual; /* Ensure IsVirtual(pTab) is true */64  pTab->u.vtab.p = pVT;65 66  if( ppVT ) *ppVT = pVT;67  if( ppMod ) *ppMod = pMod;68  if( ppIface ) *ppIface = pIface;69}70 71static void cleanupVirtualTable(Table *pTab){72  if( pTab==0 ) return;73  VTable *pVT = pTab->u.vtab.p;74  if( pVT ){75    Module *pMod = pVT->pMod;76    if( pMod ){77      if( pMod->pModule ){78        sqlite3_free((void*)pMod->pModule);79      }80      sqlite3_free(pMod);81    }82    sqlite3_free(pVT);83  }84  memset(&pTab->u, 0, sizeof(pTab->u));85}86 87/* Unity required */88void setUp(void) {89  /* No global setup needed */90}91void tearDown(void) {92  /* No global teardown needed */93}94 95/* Tests */96 97void test_vtabIsReadOnly_no_xUpdate_returns_1(void){98  sqlite3 *db = 0;99  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));100 101  Parse parse;102  initParse(db, &parse, /*inTrigger=*/0, /*trustedOn=*/1);103 104  Table tab;105  setupVirtualTable(db, &tab, "vt_no_update", /*hasXUpdate=*/0, /*eRisk=*/0, NULL, NULL, NULL);106 107  int rc = test_vtabIsReadOnly(&parse, &tab);108  TEST_ASSERT_EQUAL_INT_MESSAGE(1, rc, "vtab without xUpdate should be read-only (return 1)");109  TEST_ASSERT_NULL(parse.zErrMsg);110 111  cleanupVirtualTable(&tab);112  sqlite3_close(db);113}114 115void test_vtabIsReadOnly_with_xUpdate_not_in_trigger_no_error_returns_0(void){116  sqlite3 *db = 0;117  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));118 119  Parse parse;120  initParse(db, &parse, /*inTrigger=*/0, /*trustedOn=*/0);121 122  Table tab;123  /* Risk level high but not in trigger => no error */124  setupVirtualTable(db, &tab, "vt_update_ok", /*hasXUpdate=*/1, /*eRisk=*/2, NULL, NULL, NULL);125 126  int rc = test_vtabIsReadOnly(&parse, &tab);127  TEST_ASSERT_EQUAL_INT(0, rc);128  TEST_ASSERT_NULL_MESSAGE(parse.zErrMsg, "No error should be set when not in trigger");129 130  cleanupVirtualTable(&tab);131  sqlite3_close(db);132}133 134void test_vtabIsReadOnly_in_trigger_trusted_off_non_innocuous_sets_error(void){135  sqlite3 *db = 0;136  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));137 138  Parse parse;139  initParse(db, &parse, /*inTrigger=*/1, /*trustedOn=*/0);140 141  Table tab;142  setupVirtualTable(db, &tab, "vt_risky", /*hasXUpdate=*/1, /*eRisk=*/1, NULL, NULL, NULL);143 144  int rc = test_vtabIsReadOnly(&parse, &tab);145  TEST_ASSERT_EQUAL_INT(0, rc);146  TEST_ASSERT_NOT_NULL_MESSAGE(parse.zErrMsg, "Expected error message for risky vtab in trigger with trusted_schema=OFF");147  /* Error message contains table name */148  TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "vt_risky"));149  /* nErr should be incremented by sqlite3ErrorMsg */150  TEST_ASSERT_TRUE(parse.nErr > 0);151 152  sqlite3DbFree(db, parse.zErrMsg); parse.zErrMsg = 0;153  cleanupVirtualTable(&tab);154  sqlite3_close(db);155}156 157void test_vtabIsReadOnly_in_trigger_trusted_on_non_innocuous_allowed(void){158  sqlite3 *db = 0;159  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));160 161  Parse parse;162  initParse(db, &parse, /*inTrigger=*/1, /*trustedOn=*/1);163 164  Table tab;165  setupVirtualTable(db, &tab, "vt_noninnoc", /*hasXUpdate=*/1, /*eRisk=*/1, NULL, NULL, NULL);166 167  int rc = test_vtabIsReadOnly(&parse, &tab);168  TEST_ASSERT_EQUAL_INT(0, rc);169  TEST_ASSERT_NULL_MESSAGE(parse.zErrMsg, "No error expected when trusted_schema=ON for non-innocuous vtab");170 171  cleanupVirtualTable(&tab);172  sqlite3_close(db);173}174 175void test_vtabIsReadOnly_in_trigger_trusted_on_directonly_still_errors(void){176  sqlite3 *db = 0;177  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));178 179  Parse parse;180  initParse(db, &parse, /*inTrigger=*/1, /*trustedOn=*/1);181 182  Table tab;183  /* eRisk > 1 models DIRECTONLY */184  setupVirtualTable(db, &tab, "vt_directonly", /*hasXUpdate=*/1, /*eRisk=*/2, NULL, NULL, NULL);185 186  int rc = test_vtabIsReadOnly(&parse, &tab);187  TEST_ASSERT_EQUAL_INT(0, rc);188  TEST_ASSERT_NOT_NULL_MESSAGE(parse.zErrMsg, "DIRECTONLY vtab should be rejected in trigger even if trusted_schema=ON");189  TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "vt_directonly"));190  TEST_ASSERT_TRUE(parse.nErr > 0);191 192  sqlite3DbFree(db, parse.zErrMsg); parse.zErrMsg = 0;193  cleanupVirtualTable(&tab);194  sqlite3_close(db);195}196 197int main(void){198  UNITY_BEGIN();199  RUN_TEST(test_vtabIsReadOnly_no_xUpdate_returns_1);200  RUN_TEST(test_vtabIsReadOnly_with_xUpdate_not_in_trigger_no_error_returns_0);201  RUN_TEST(test_vtabIsReadOnly_in_trigger_trusted_off_non_innocuous_sets_error);202  RUN_TEST(test_vtabIsReadOnly_in_trigger_trusted_on_non_innocuous_allowed);203  RUN_TEST(test_vtabIsReadOnly_in_trigger_trusted_on_directonly_still_errors);204  return UNITY_END();205}