From d64029102314dc63d342d8c32032a7f512100c97 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Fri, 18 Nov 2016 16:00:57 +0200 Subject: [PATCH] Add crashing test-case With 2.0.1 or earlier, if a statement contains a trailing NULL, the statement will inside qc_sqlite.c incorrectly be assumed not to be the one to be classified with a crash being indirectly the result. --- query_classifier/test/CMakeLists.txt | 9 +++- query_classifier/test/crash_qc_sqlite.c | 66 +++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 query_classifier/test/crash_qc_sqlite.c diff --git a/query_classifier/test/CMakeLists.txt b/query_classifier/test/CMakeLists.txt index 565b067f5..ba817cb5e 100644 --- a/query_classifier/test/CMakeLists.txt +++ b/query_classifier/test/CMakeLists.txt @@ -17,9 +17,16 @@ if (BUILD_QC_MYSQLEMBEDDED) endif() add_executable(classify classify.c) - add_executable(compare compare.cc) target_link_libraries(classify maxscale-common) + + add_executable(compare compare.cc) target_link_libraries(compare maxscale-common) + + add_executable(crash_qc_sqlite crash_qc_sqlite.c) + target_link_libraries(crash_qc_sqlite maxscale-common) + + add_test(TestQC_Crash_qcsqlite crash_qc_sqlite) + add_test(TestQC_MySQLEmbedded classify qc_mysqlembedded ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql) add_test(TestQC_SqLite classify qc_sqlite ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql) diff --git a/query_classifier/test/crash_qc_sqlite.c b/query_classifier/test/crash_qc_sqlite.c new file mode 100644 index 000000000..2f1983f05 --- /dev/null +++ b/query_classifier/test/crash_qc_sqlite.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl. + * + * Change Date: 2019-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ + +#include +#include +#include +#include + +#define MYSQL_HEADER_LEN 4 + +GWBUF* create_gwbuf(const char* s, size_t len) +{ + size_t payload_len = len + 1; + size_t gwbuf_len = MYSQL_HEADER_LEN + payload_len; + + GWBUF* gwbuf = gwbuf_alloc(gwbuf_len); + + *((unsigned char*)((char*)GWBUF_DATA(gwbuf))) = payload_len; + *((unsigned char*)((char*)GWBUF_DATA(gwbuf) + 1)) = (payload_len >> 8); + *((unsigned char*)((char*)GWBUF_DATA(gwbuf) + 2)) = (payload_len >> 16); + *((unsigned char*)((char*)GWBUF_DATA(gwbuf) + 3)) = 0x00; + *((unsigned char*)((char*)GWBUF_DATA(gwbuf) + 4)) = 0x03; + memcpy((char*)GWBUF_DATA(gwbuf) + 5, s, len); + + return gwbuf; +} + +int main() +{ + int rv = EXIT_FAILURE; + + set_libdir(strdup("../qc_sqlite")); + + if (qc_init("qc_sqlite", NULL)) + { + const char s[] = "SELECT @@global.max_allowed_packet"; + + GWBUF *stmt = create_gwbuf(s, sizeof(s)); // Include superfluous NULL. + + // In 2.0.1 this crashed due to is_submitted_query() in qc_sqlite.c + // being of the opinion that the statement was not the one to be + // classified and hence an alien parse-tree being passed to sqlite3's + // code generator. + qc_parse(stmt); + + qc_end(); + + rv = EXIT_SUCCESS; + } + else + { + fprintf(stderr, "error: Could not load query classifier."); + } + + return rv; +}