From 9913f3681b73fa42640750cd2fde4f99e88cbf27 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Thu, 9 Dec 2010 17:51:25 +0300 Subject: [PATCH] Demonstrate segmentation fault --- c_src/sqlite3_drv.c | 130 +++++++++++++++++++++++++++++--------------- rebar.config | 2 +- 2 files changed, 88 insertions(+), 44 deletions(-) diff --git a/c_src/sqlite3_drv.c b/c_src/sqlite3_drv.c index d34ce88..f22d661 100644 --- a/c_src/sqlite3_drv.c +++ b/c_src/sqlite3_drv.c @@ -395,6 +395,33 @@ static int bind_parameters( return result; } +static void get_columns( + sqlite3_drv_t *drv, sqlite3_stmt *statement, int column_count, + int *p_term_count, int *p_term_allocated, ErlDrvTermData **p_dataset) { + int i; + + int base = *p_term_count; + *p_term_count += column_count * 3 + 1 + 2 + 2; + if (*p_term_count > *p_term_allocated) { + *p_term_allocated = max(*p_term_count, *p_term_allocated*2); + *p_dataset = driver_realloc(*p_dataset, sizeof(ErlDrvTermData) * *p_term_allocated); + } + for (i = 0; i < column_count; i++) { + char *column_name = (char *) sqlite3_column_name(statement, i); +#ifdef DEBUG + fprintf(drv->log, "Column: %s\n", column_name); + fflush(drv->log); +#endif + + (*p_dataset)[base + 2 + (i * 3)] = ERL_DRV_STRING; + (*p_dataset)[base + 2 + (i * 3) + 1] = (ErlDrvTermData) column_name; + (*p_dataset)[base + 2 + (i * 3) + 2] = strlen(column_name); + } + (*p_dataset)[base + 2 + column_count * 3 + 0] = ERL_DRV_NIL; + (*p_dataset)[base + 2 + column_count * 3 + 1] = ERL_DRV_LIST; + (*p_dataset)[base + 2 + column_count * 3 + 2] = column_count + 1; +} + static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buffer, int buffer_size) { int result; int index = 0; @@ -479,39 +506,27 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_PORT; dataset[term_count - 1] = driver_mk_port(drv->port); if (column_count > 0) { - int base = term_count; - term_count += 2 + column_count * 3 + 1 + 2 + 2 + 2; + term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } - dataset[base] = ERL_DRV_ATOM; - dataset[base + 1] = drv->atom_columns; - for (i = 0; i < column_count; i++) { - char *column_name = (char *) sqlite3_column_name(statement, i); -#ifdef DEBUG - fprintf(drv->log, "Column: %s\n", column_name); - fflush(drv->log); -#endif + dataset[term_count - 2] = ERL_DRV_ATOM; + dataset[term_count - 1] = drv->atom_columns; + int base = term_count; + get_columns( + drv, statement, column_count, &term_count, &term_allocated, &dataset); + dataset[base + column_count * 3 + 3] = ERL_DRV_TUPLE; + dataset[base + column_count * 3 + 4] = 2; - dataset[base + 2 + (i * 3)] = ERL_DRV_STRING; - dataset[base + 2 + (i * 3) + 1] = (ErlDrvTermData) column_name; - dataset[base + 2 + (i * 3) + 2] = strlen(column_name); - } - dataset[base + 2 + column_count * 3 + 0] = ERL_DRV_NIL; - dataset[base + 2 + column_count * 3 + 1] = ERL_DRV_LIST; - dataset[base + 2 + column_count * 3 + 2] = column_count + 1; - dataset[base + 2 + column_count * 3 + 3] = ERL_DRV_TUPLE; - dataset[base + 2 + column_count * 3 + 4] = 2; - - dataset[base + 2 + column_count * 3 + 5] = ERL_DRV_ATOM; - dataset[base + 2 + column_count * 3 + 6] = drv->atom_rows; + dataset[base + column_count * 3 + 5] = ERL_DRV_ATOM; + dataset[base + column_count * 3 + 6] = drv->atom_rows; } #ifdef DEBUG @@ -534,7 +549,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_INT64; dataset[term_count - 1] = (ErlDrvTermData) int64_ptr; @@ -548,7 +563,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_FLOAT; dataset[term_count - 1] = (ErlDrvTermData) float_ptr; @@ -565,7 +580,7 @@ static void sql_exec_async(void *_async_command) { term_count += 8; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 8] = ERL_DRV_ATOM; dataset[term_count - 7] = drv->atom_blob; @@ -588,7 +603,7 @@ static void sql_exec_async(void *_async_command) { term_count += 4; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 4] = ERL_DRV_BINARY; dataset[term_count - 3] = (ErlDrvTermData) binary; @@ -600,7 +615,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_ATOM; dataset[term_count - 1] = drv->atom_null; @@ -611,7 +626,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 1] = column_count; @@ -638,7 +653,7 @@ static void sql_exec_async(void *_async_command) { term_count += 3+2+3; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 8] = ERL_DRV_NIL; dataset[term_count - 7] = ERL_DRV_LIST; @@ -655,7 +670,7 @@ static void sql_exec_async(void *_async_command) { term_count += 6; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 6] = ERL_DRV_ATOM; dataset[term_count - 5] = drv->atom_rowid; @@ -667,7 +682,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_ATOM; dataset[term_count - 1] = drv->atom_ok; @@ -676,7 +691,7 @@ static void sql_exec_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 1] = 2; @@ -711,7 +726,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_PORT; dataset[term_count - 1] = driver_mk_port(drv->port); @@ -730,7 +745,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_INT64; dataset[term_count - 1] = (ErlDrvTermData) int64_ptr; @@ -744,7 +759,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_FLOAT; dataset[term_count - 1] = (ErlDrvTermData) float_ptr; @@ -761,7 +776,7 @@ static void sql_step_async(void *_async_command) { term_count += 8; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 8] = ERL_DRV_ATOM; dataset[term_count - 7] = drv->atom_blob; @@ -784,7 +799,7 @@ static void sql_step_async(void *_async_command) { term_count += 4; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 4] = ERL_DRV_BINARY; dataset[term_count - 3] = (ErlDrvTermData) binary; @@ -796,7 +811,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_ATOM; dataset[term_count - 1] = drv->atom_null; @@ -807,7 +822,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 1] = column_count; @@ -819,7 +834,7 @@ static void sql_step_async(void *_async_command) { term_count += 4; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 4] = ERL_DRV_PORT; dataset[term_count - 3] = driver_mk_port(drv->port); @@ -843,7 +858,7 @@ static void sql_step_async(void *_async_command) { term_count += 2; if (term_count > term_allocated) { term_allocated = max(term_count, term_allocated*2); - dataset = driver_realloc(dataset, sizeof(*dataset) * term_allocated); + dataset = driver_realloc(dataset, sizeof(ErlDrvTermData) * term_allocated); } dataset[term_count - 2] = ERL_DRV_TUPLE; dataset[term_count - 1] = 2; @@ -938,6 +953,35 @@ static int prepared_bind(sqlite3_drv_t *drv, char *buffer, int buffer_size) { } } +static int prepared_columns(sqlite3_drv_t *drv, char *buffer, int buffer_size) { + int result; + long long_prepared_index; + int index = 0, type, size; + +#ifdef DEBUG + fprintf(drv->log, "Finalizing prepared statement: %.*s\n", buffer_size, buffer); + fflush(drv->log); +#endif + + ei_decode_version(buffer, &index, NULL); + ei_decode_long(buffer, &index, &long_prepared_index); + unsigned int prepared_index = (unsigned int) long_prepared_index; + + if (prepared_index >= drv->prepared_count) { + return output_error(drv, SQLITE_MISUSE, + "Trying to reset non-existent prepared statement"); + } + + sqlite3_stmt *statement = drv->prepared_stmts[prepared_index]; +// result = +// bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size); +// if (result == SQLITE_OK) { +// return output_ok(drv); +// } else { +// return result; // error has already been output +// } +} + static int prepared_step(sqlite3_drv_t *drv, char *buffer, int buffer_size) { int result; long long_prepared_index; diff --git a/rebar.config b/rebar.config index 79183e8..ab08c20 100644 --- a/rebar.config +++ b/rebar.config @@ -1,7 +1,7 @@ % -*- mode: erlang -*- {erl_opts, [debug_info]}. %% required for dialyzer {port_envs, [{"DRV_LDFLAGS", "$DRV_LDFLAGS -lsqlite3"}, - {"DRV_CFLAGS", "$DRV_CFLAGS -Wall -Wextra -Wno-unused-parameter"}]}. + {"DRV_CFLAGS", "$DRV_CFLAGS -g -Wall -Wextra -Wno-unused-parameter"}]}. {cover_enabled, true}. {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}. {dialyzer_opts, [{plt, "dialyzer/sqlite3.plt"}]}.