Skip to content

Instantly share code, notes, and snippets.

@LalitMaganti
Created January 2, 2020 15:04
Show Gist options
  • Save LalitMaganti/57f8c51934379270abe58201c7b1dab1 to your computer and use it in GitHub Desktop.
Save LalitMaganti/57f8c51934379270abe58201c7b1dab1 to your computer and use it in GitHub Desktop.
SQLite vtable bug repro
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Cursor {
sqlite3_vtab_cursor c;
int index;
} Cursor;
int create(sqlite3* xdb, void* x, int y, const char* const* z, sqlite3_vtab** v,
char** a) {
int res = sqlite3_declare_vtab(xdb, "CREATE TABLE x(a INT);");
if (res != SQLITE_OK) return res;
*v = malloc(sizeof(sqlite3_vtab));
return SQLITE_OK;
}
int destroy(sqlite3_vtab* v) {
free(v);
return SQLITE_OK;
}
int open(sqlite3_vtab* v, sqlite3_vtab_cursor** c) {
*c = malloc(sizeof(Cursor));
memset(*c, 0, sizeof(Cursor));
return SQLITE_OK;
}
int bestindex(sqlite3_vtab* v, sqlite3_index_info* i) {
int c = 0;
for (int j = 0; j < i->nConstraint; ++j) {
if (i->aConstraint[j].usable)
i->aConstraintUsage[j].argvIndex = ++c;
}
return SQLITE_OK;
}
int filter(sqlite3_vtab_cursor* c, int x, const char* y, int z,
sqlite3_value** v) {
return SQLITE_OK;
}
int close(sqlite3_vtab_cursor* c) {
free(c);
return SQLITE_OK;
}
int next(sqlite3_vtab_cursor* c) {
Cursor* cursor = (Cursor*)c;
cursor->index++;
return SQLITE_OK;
}
int eof(sqlite3_vtab_cursor* c) {
Cursor* cursor = (Cursor*)c;
return cursor->index >= 2;
}
int column(sqlite3_vtab_cursor* c, sqlite3_context* a, int col) {
Cursor* cursor = (Cursor*)c;
if (cursor->index % 2 == 0) {
sqlite3_result_int(a, cursor->index);
} else {
sqlite3_result_null(a);
}
return SQLITE_OK;
}
int callback(void* noop, int c, char** col, char** name) {
for (int i = 0; i < c; ++i) {
printf("%s ", col[i]);
}
printf("\n");
return SQLITE_OK;
}
int main(int argc, char** argv) {
sqlite3* db = NULL;
sqlite3_initialize();
sqlite3_open(":memory:", &db);
sqlite3_module* module = malloc(sizeof(sqlite3_module));
memset(module, 0, sizeof(*module));
module->xCreate = &create;
module->xConnect = &create;
module->xDisconnect = &destroy;
module->xDestroy = &destroy;
module->xOpen = &open;
module->xClose = &close;
module->xBestIndex = &bestindex;
module->xFilter = &filter;
module->xNext = &next;
module->xEof = &eof;
module->xColumn = &column;
int res = sqlite3_create_module_v2(db, "Z", module, NULL, NULL);
char* err;
sqlite3_exec(db, "SELECT * FROM Z WHERE a = 0 or a = 1", &callback, NULL, &err);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment