Copy column names to driver-allocated memory.

Fixes issue #14 by copying out column names before memory can be overwritten by another statement.
This commit is contained in:
Alexey Romanov
2012-09-17 10:32:16 +04:00
parent e417a95f53
commit 8752bffec1

View File

@@ -507,7 +507,7 @@ static int bind_parameters(
static void get_columns( static void get_columns(
sqlite3_drv_t *drv, sqlite3_stmt *statement, int column_count, int base, sqlite3_drv_t *drv, sqlite3_stmt *statement, int column_count, int base,
int *p_term_count, int *p_term_allocated, ErlDrvTermData **p_dataset) { int *p_term_count, int *p_term_allocated, ptr_list** p_ptrs, ErlDrvTermData **p_dataset) {
int i; int i;
*p_term_count += column_count * 3 + 3; *p_term_count += column_count * 3 + 3;
@@ -516,12 +516,16 @@ static void get_columns(
*p_dataset = driver_realloc(*p_dataset, sizeof(ErlDrvTermData) * *p_term_allocated); *p_dataset = driver_realloc(*p_dataset, sizeof(ErlDrvTermData) * *p_term_allocated);
} }
for (i = 0; i < column_count; i++) { for (i = 0; i < column_count; i++) {
char *column_name = (char *) sqlite3_column_name(statement, i); const char *column_name = sqlite3_column_name(statement, i);
TRACE((drv->log, "Column: %s\n", column_name)); size_t column_name_length = strlen(column_name);
char *column_name_copy = driver_alloc(sizeof(char *) * (column_name_length + 1));
strcpy(column_name_copy, column_name);
*p_ptrs = add_to_ptr_list(*p_ptrs, column_name_copy);
TRACE((drv->log, "Column: %s\n", column_name_copy));
(*p_dataset)[base + (i * 3)] = ERL_DRV_STRING; (*p_dataset)[base + (i * 3)] = ERL_DRV_STRING;
(*p_dataset)[base + (i * 3) + 1] = (ErlDrvTermData) column_name; (*p_dataset)[base + (i * 3) + 1] = (ErlDrvTermData) column_name_copy;
(*p_dataset)[base + (i * 3) + 2] = strlen(column_name); (*p_dataset)[base + (i * 3) + 2] = column_name_length;
} }
(*p_dataset)[base + column_count * 3 + 0] = ERL_DRV_NIL; (*p_dataset)[base + column_count * 3 + 0] = ERL_DRV_NIL;
(*p_dataset)[base + column_count * 3 + 1] = ERL_DRV_LIST; (*p_dataset)[base + column_count * 3 + 1] = ERL_DRV_LIST;
@@ -620,7 +624,7 @@ static int sql_exec_one_statement(
(*dataset_p)[*term_count_p - 1] = drv->atom_columns; (*dataset_p)[*term_count_p - 1] = drv->atom_columns;
base_term_count = *term_count_p; base_term_count = *term_count_p;
get_columns( get_columns(
drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, dataset_p); drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, ptrs_p, dataset_p);
*term_count_p += 4; *term_count_p += 4;
if (*term_count_p > *term_allocated_p) { if (*term_count_p > *term_allocated_p) {
*term_allocated_p = max(*term_count_p, *term_allocated_p*2); *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
@@ -1138,6 +1142,7 @@ static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
int index = 0, term_count = 0, term_allocated = 0, column_count; int index = 0, term_count = 0, term_allocated = 0, column_count;
sqlite3_stmt *statement; sqlite3_stmt *statement;
ErlDrvTermData *dataset = NULL; ErlDrvTermData *dataset = NULL;
ptr_list* ptrs = NULL;
ei_decode_version(buffer, &index, NULL); ei_decode_version(buffer, &index, NULL);
ei_decode_long(buffer, &index, &long_prepared_index); ei_decode_long(buffer, &index, &long_prepared_index);
@@ -1165,11 +1170,13 @@ static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
column_count = sqlite3_column_count(statement); column_count = sqlite3_column_count(statement);
get_columns( get_columns(
drv, statement, column_count, 2, &term_count, &term_allocated, &dataset); drv, statement, column_count, 2, &term_count, &term_allocated, &ptrs, &dataset);
dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 2] = ERL_DRV_TUPLE;
dataset[term_count - 1] = 2; dataset[term_count - 1] = 2;
return driver_output_term(drv->port, dataset, term_count); driver_output_term(drv->port, dataset, term_count);
free_ptr_list(ptrs, driver_free_fun);
return 0;
} }
static int prepared_step(sqlite3_drv_t *drv, char *buffer, int buffer_size) { static int prepared_step(sqlite3_drv_t *drv, char *buffer, int buffer_size) {