Skip to content

SIGSEGV in command::execute_all() with trailing whitespace #78

@stewbond

Description

@stewbond

When running sqlite3ppp::command::execute_all() with a command that has trailing whitespace, we get a SIGSEGV from sqlite3_transfer_bindings().

Consider the following:

sqlite3pp::database db(":memory:");
                                                                                
sqlite3pp::command cmd0(db, " ");                                       
assert( cmd0.execute() == SQLITE_MISUSE );                              
                                                                                
sqlite3pp::command cmd1(db, "CREATE TABLE Bar ( v ); ");                
cmd1.execute_all();  

cmd0.execute() runs a command that is empty (one space). This returns SQLITE_MISUSE as expected.

I expect cmd1.execute_all() should run "CREATE TABLE BAR(v);" and then should either break from the while loop, or run the command on " " which would return SQLITE_MISUSE. Instead it segfaults. I think the problem stems from the while loop that detects if we're done:

while (std::strlen(sql) > 0) { // sqlite3_complete() is broken.
    ...
    sqlite3_transfer_bindings(old_stmt, stmt_); // <-- SIGSEGV here
    ...
    sql = tail_;
}

If sqlite3_complete() really is broken and we need to write our own implementation, then perhaps we should do something more elaborate than std::strlen(sql) > 0. Maybe something like this could work:

while (std::strlen(sql) > 0) { // sqlite3_complete() is broken.
    ...
    sqlite3_transfer_bindings(old_stmt, stmt_);
    ...
    for(sql = tail_; *sql != '\0' && std::isspace(*sql); ++sql){}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions