diff --git a/include/Admin_ifaces.h b/include/Admin_ifaces.h index 7d009d0d4d..6d3acc7b5b 100644 --- a/include/Admin_ifaces.h +++ b/include/Admin_ifaces.h @@ -44,6 +44,49 @@ class ifaces_desc { class admin_main_loop_listeners { private: + struct tokenizer_owner { + tokenizer_t value; + + explicit tokenizer_owner(char *list) { + tokenizer(&value, list, ";", TOKENIZER_NO_EMPTIES); + } + + ~tokenizer_owner() { + free_tokenizer(&value); + } + + tokenizer_owner(const tokenizer_owner&) = delete; + tokenizer_owner& operator=(const tokenizer_owner&) = delete; + tokenizer_owner(tokenizer_owner&&) = delete; + tokenizer_owner& operator=(tokenizer_owner&&) = delete; + }; + + struct interface_array_owner { + char **value; + + explicit interface_array_owner(char **value_) : value(value_) {} + + ~interface_array_owner() { + if (value) { + for (int i = 0; i < MAX_IFACES; ++i) { + l_free(0, value[i]); + } + l_free(0, value); + } + } + + interface_array_owner(const interface_array_owner&) = delete; + interface_array_owner& operator=(const interface_array_owner&) = delete; + interface_array_owner(interface_array_owner&&) = delete; + interface_array_owner& operator=(interface_array_owner&&) = delete; + + char **release() { + char **released = value; + value = nullptr; + return released; + } + }; + int version; #ifdef PA_PTHREAD_MUTEX pthread_rwlock_t rwlock; @@ -129,19 +172,32 @@ class admin_main_loop_listeners { bool update_ifaces(char *list, char ***_ifaces) { wrlock(); - int i; - char **ifaces=*_ifaces; - tokenizer_t tok; - tokenizer( &tok, list, ";", TOKENIZER_NO_EMPTIES ); - const char* token; - ifaces=reset_ifaces(ifaces); - i=0; - for ( token = tokenize( &tok ) ; token && i < MAX_IFACES ; token = tokenize( &tok ) ) { - ifaces[i]=(char *)malloc(strlen(token)+1); - strcpy(ifaces[i],token); + char **old_ifaces = *_ifaces; + char **new_ifaces = (char **)l_alloc(MAX_IFACES * sizeof(char *)); + if (new_ifaces != nullptr) { + memset(new_ifaces, 0, MAX_IFACES * sizeof(char *)); + } + interface_array_owner replacement(new_ifaces); + if (replacement.value == nullptr) { + wrunlock(); + return false; + } + + tokenizer_owner tokens(list); + int i = 0; + for (const char *token = tokenize(&tokens.value); + token && i < MAX_IFACES; + token = tokenize(&tokens.value)) { + replacement.value[i] = strdup(token); + if (replacement.value[i] == nullptr) { + wrunlock(); + return false; + } i++; } - free_tokenizer( &tok ); + + interface_array_owner previous(old_ifaces); + *_ifaces = replacement.release(); version++; wrunlock(); return true; diff --git a/include/MySQL_Query_Processor.h b/include/MySQL_Query_Processor.h index c63d1de226..223a5f1ec5 100644 --- a/include/MySQL_Query_Processor.h +++ b/include/MySQL_Query_Processor.h @@ -60,7 +60,7 @@ class MySQL_Query_Processor : public Query_Processor { private: Command_Counter* commands_counters[MYSQL_COM_QUERY___NONE]; - static bool _is_valid_gtid(char* gtid, size_t gtid_len); + static bool _is_valid_gtid(const char* gtid, size_t gtid_len); static MySQL_Query_Processor_Rule_t* new_query_rule(const MySQL_Query_Processor_Rule_t* mqr); inline @@ -74,25 +74,29 @@ class MySQL_Query_Processor : public Query_Processor { inline void query_parser_first_comment_extended(const char* key, const char* value, MySQL_Query_Processor_Output* qpo) { - if (!strcasecmp(key, "min_gtid")) { - if (mysql_thread___ignore_min_gtid_annotations) { - proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "Ignoring min_gtid=%s\n", value); - } else { - size_t l = strlen(value); - if (_is_valid_gtid((char*)value, l)) { - char* buf = (char*)malloc(l + 1); - strncpy(buf, value, l); - buf[l] = '\0'; - - if (qpo->min_gtid) { - free(qpo->min_gtid); - } - qpo->min_gtid = buf; - } else { - proxy_warning("Invalid min_gtid value=%s\n", value); - } - } + if (strcasecmp(key, "min_gtid")) { + return; + } + if (mysql_thread___ignore_min_gtid_annotations) { + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "Ignoring min_gtid=%s\n", value); + return; + } + size_t l = strlen(value); + if (!_is_valid_gtid(value, l)) { + proxy_warning("Invalid min_gtid value=%s\n", value); + return; + } + char* buf = (char*)l_alloc(l + 1); + if (buf == nullptr) { + proxy_warning("Unable to allocate memory for min_gtid=%s\n", value); + return; + } + memcpy(buf, value, l); + buf[l] = '\0'; + if (qpo->min_gtid) { + l_free(0, qpo->min_gtid); } + qpo->min_gtid = buf; } friend class Query_Processor; diff --git a/include/proxysql_glovars.hpp b/include/proxysql_glovars.hpp index 104c2613c1..6879227ac7 100644 --- a/include/proxysql_glovars.hpp +++ b/include/proxysql_glovars.hpp @@ -48,9 +48,12 @@ class ProxySQL_Checksum_Value { epoch = 0; in_shutdown = false; } - void set_checksum(char *c) { + void set_checksum(const char *c) { memset(checksum,0,ProxySQL_Checksum_Value_LENGTH); - strncpy(checksum,c,ProxySQL_Checksum_Value_LENGTH); + if (c) { + const size_t length = strnlen(c, ProxySQL_Checksum_Value_LENGTH); + memcpy(checksum, c, length); + } replace_checksum_zeros(checksum); } ~ProxySQL_Checksum_Value() { diff --git a/include/proxysql_macros.h b/include/proxysql_macros.h index 5aa3f55d70..29c8337acc 100644 --- a/include/proxysql_macros.h +++ b/include/proxysql_macros.h @@ -4,7 +4,7 @@ #define char_malloc (char *)malloc #define free_null(__c) { if(__c) { free(__c); (__c)=NULL; } } -#define itostr(__s, __i) { (__s)=char_malloc(32); sprintf(__s, "%lld", (__i)); } +#define itostr(__s, __i) { (__s)=char_malloc(32); snprintf((__s), 32, "%lld", (__i)); } // fast memory copy forward . Use this instead of memcpy for small buffers #define MEM_COPY_FWD(dst_p, src_p, bytes) \ diff --git a/lib/Admin_Handler.cpp b/lib/Admin_Handler.cpp index 8875adc903..fe3d9a0db2 100644 --- a/lib/Admin_Handler.cpp +++ b/lib/Admin_Handler.cpp @@ -351,7 +351,7 @@ static bool extract_psql_pattern(const char* query, char* pattern_buf, size_t bu if (!relname_pos) return false; // Skip to the operator or LIKE keyword - const char* value_pos = relname_pos + strlen("c.relname"); + const char* value_pos = relname_pos + sizeof("c.relname") - 1; while (*value_pos && *value_pos == ' ') value_pos++; // Safety check: ensure we haven't gone past end of string @@ -526,14 +526,16 @@ bool is_admin_command_or_alias(const std::vector& cmds, char *query return false; } -const char * match_command_prefix(const std::vector& cmd_prefix, char *query, int query_len) { +const char * match_command_prefix(const std::vector& cmd_prefix, char *query, int query_len, size_t &prefix_len) { for (auto &prefix : cmd_prefix) { if ((unsigned int) query_len >= prefix.length() && !strncasecmp(prefix.c_str(), query, prefix.length())) { + prefix_len = prefix.length(); return prefix.c_str(); } } + prefix_len = 0; return nullptr; } @@ -576,17 +578,20 @@ std::tuple parse_command_purge_query_digests(cha bool match = false; enum SERVER_TYPE server_type = SERVER_TYPE_MYSQL; time_t last_seen = 0; + size_t prefix_len = 0; - const char *prefix = match_command_prefix(CMD_PREFIX_PURGE_QUERY_DIGESTS, query, query_len); + const char *prefix = match_command_prefix(CMD_PREFIX_PURGE_QUERY_DIGESTS, query, query_len, prefix_len); if (prefix) { match = true; - if (strstr(prefix, "_pgsql_") != nullptr) { + const std::string_view prefix_sv(prefix, prefix_len); + const std::string_view pgsql_tag("_pgsql_"); + if (prefix_sv.find(pgsql_tag) != std::string_view::npos) { server_type = SERVER_TYPE_PGSQL; } // parse timestamp - mf_unique_ptr ts_str(strdup(query + strlen(prefix))); + mf_unique_ptr ts_str(strdup(query + prefix_len)); char *ts_end = nullptr; long long ts = strtoll(trim_spaces_in_place(ts_str.get()), &ts_end, 10); @@ -637,17 +642,24 @@ bool admin_handler_command_kill_mysql_connection(uint32_t session_thd_id, S* ses template bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_space_length, S* sess, ProxySQL_Admin *pa) { + static const char cmd_coredump[] = "PROXYSQL COREDUMP"; + static const size_t cmd_coredump_len = sizeof(cmd_coredump) - 1; + static const char cmd_coredump_compressed[] = "PROXYSQL COMPRESSEDCOREDUMP"; + static const size_t cmd_coredump_compressed_len = sizeof(cmd_coredump_compressed) - 1; + static const char cmd_cluster_node_uuid[] = "PROXYSQL CLUSTER_NODE_UUID "; + static const size_t cmd_cluster_node_uuid_len = sizeof(cmd_cluster_node_uuid) - 1; + #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || defined(__mips__)) && defined(__linux) - // currently only support x86-32, x86-64, ARM, and MIPS on Linux - if (!(strncasecmp("PROXYSQL COREDUMP", query_no_space, strlen("PROXYSQL COREDUMP")))) { - string filename = "core"; - if (query_no_space_length > strlen("PROXYSQL COREDUMP")) { - if (query_no_space[strlen("PROXYSQL COREDUMP")] == ' ') { - filename = string(query_no_space+strlen("PROXYSQL COREDUMP ")); - } else { - filename = ""; + // currently only support x86-32, x86-64, ARM, and MIPS on Linux + if (!(strncasecmp(cmd_coredump, query_no_space, cmd_coredump_len))) { + string filename = "core"; + if (query_no_space_length > (unsigned int)cmd_coredump_len) { + if (query_no_space[cmd_coredump_len] == ' ') { + filename = string(query_no_space + cmd_coredump_len + 1); + } else { + filename = ""; + } } - } if (filename == "") { proxy_error("Received incorrect PROXYSQL COREDUMP command: %s\n", query_no_space); } else { @@ -658,17 +670,17 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ string msg = "Coredump: " + filename; SPA->send_ok_msg_to_client(sess, (char *)msg.c_str(), 0, query_no_space); return false; - } - } - if (!(strncasecmp("PROXYSQL COMPRESSEDCOREDUMP", query_no_space, strlen("PROXYSQL COMPRESSEDCOREDUMP")))) { - string filename = "core"; - if (query_no_space_length > strlen("PROXYSQL COMPRESSEDCOREDUMP")) { - if (query_no_space[strlen("PROXYSQL COMPRESSEDCOREDUMP")] == ' ') { - filename = string(query_no_space+strlen("PROXYSQL COMPRESSEDCOREDUMP ")); - } else { - filename = ""; } } + if (!(strncasecmp(cmd_coredump_compressed, query_no_space, cmd_coredump_compressed_len))) { + string filename = "core"; + if (query_no_space_length > (unsigned int)cmd_coredump_compressed_len) { + if (query_no_space[cmd_coredump_compressed_len] == ' ') { + filename = string(query_no_space + cmd_coredump_compressed_len + 1); + } else { + filename = ""; + } + } if (filename == "") { proxy_error("Received incorrect PROXYSQL COMPRESSEDCOREDUMP command: %s\n", query_no_space); } else { @@ -683,8 +695,8 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ } #endif - if (!(strncasecmp("PROXYSQL CLUSTER_NODE_UUID ", query_no_space, strlen("PROXYSQL CLUSTER_NODE_UUID ")))) { - int l = strlen("PROXYSQL CLUSTER_NODE_UUID "); + if (!(strncasecmp(cmd_cluster_node_uuid, query_no_space, cmd_cluster_node_uuid_len))) { + int l = cmd_cluster_node_uuid_len; if (sess->client_myds->addr.port == 0) { proxy_warning("Received PROXYSQL CLUSTER_NODE_UUID not from TCP socket. Exiting client\n"); SPA->send_error_msg_to_client(sess, (char *)"Received PROXYSQL CLUSTER_NODE_UUID not from TCP socket"); @@ -742,7 +754,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } } - if (query_no_space_length==strlen("PROXYSQL READONLY") && !strncasecmp("PROXYSQL READONLY",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL READONLY") - 1 && !strncasecmp("PROXYSQL READONLY",query_no_space, query_no_space_length)) { // this command enables admin_read_only , so the admin module is in read_only mode proxy_info("Received PROXYSQL READONLY command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -750,7 +762,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); return false; } - if (query_no_space_length==strlen("PROXYSQL READWRITE") && !strncasecmp("PROXYSQL READWRITE",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL READWRITE") - 1 && !strncasecmp("PROXYSQL READWRITE",query_no_space, query_no_space_length)) { // this command disables admin_read_only , so the admin module won't be in read_only mode proxy_info("Received PROXYSQL WRITE command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -758,7 +770,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); return false; } - if (query_no_space_length == strlen("PROXYSQL START") && !strncasecmp("PROXYSQL START", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL START") - 1 && !strncasecmp("PROXYSQL START", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL START command\n"); ProxySQL_Admin* SPA = (ProxySQL_Admin*)pa; @@ -795,7 +807,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL RESTART") && !strncasecmp("PROXYSQL RESTART",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL RESTART") - 1 && !strncasecmp("PROXYSQL RESTART",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL RESTART command\n"); // This function was introduced into 'prometheus::Registry' for being // able to do a complete reset of all the 'prometheus counters'. It @@ -806,7 +818,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length == strlen("PROXYSQL STOP") && !strncasecmp("PROXYSQL STOP", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL STOP") - 1 && !strncasecmp("PROXYSQL STOP", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL STOP command\n"); ProxySQL_Admin* SPA = (ProxySQL_Admin*)pa; @@ -859,7 +871,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL PAUSE") && !strncasecmp("PROXYSQL PAUSE",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL PAUSE") - 1 && !strncasecmp("PROXYSQL PAUSE",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL PAUSE command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; if (admin_nostart_) { @@ -881,7 +893,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ GloMTH->set_int_variable_and_commit("poll_timeout", "10"); GloMTH->signal_all_threads(0); GloMTH->stop_listeners(); - admin_proxysql_mysql_paused=true; + admin_proxysql_mysql_paused=true; // we now rollback poll_timeout char buf[32]; sprintf(buf,"%d",admin_old_wait_timeout); @@ -911,7 +923,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL RESUME") && !strncasecmp("PROXYSQL RESUME",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL RESUME") - 1 && !strncasecmp("PROXYSQL RESUME",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL RESUME command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; if (admin_nostart_) { @@ -971,7 +983,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL SHUTDOWN SLOW") && !strncasecmp("PROXYSQL SHUTDOWN SLOW",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL SHUTDOWN SLOW") - 1 && !strncasecmp("PROXYSQL SHUTDOWN SLOW",query_no_space, query_no_space_length)) { glovars.proxy_restart_on_error=false; glovars.reload=0; proxy_info("Received PROXYSQL SHUTDOWN SLOW command\n"); @@ -979,7 +991,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL FLUSH LOGS") && !strncasecmp("PROXYSQL FLUSH LOGS",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL FLUSH LOGS") - 1 && !strncasecmp("PROXYSQL FLUSH LOGS",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH LOGS command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; SPA->flush_logs(); @@ -987,7 +999,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length==strlen("PROXYSQL FLUSH QUERY CACHE") && !strncasecmp("PROXYSQL FLUSH QUERY CACHE",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL FLUSH QUERY CACHE") - 1 && !strncasecmp("PROXYSQL FLUSH QUERY CACHE",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH QUERY CACHE command\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; if (GloMyQC) { @@ -1000,7 +1012,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length == strlen("PROXYSQL FLUSH MYSQL QUERY CACHE") && !strncasecmp("PROXYSQL FLUSH MYSQL QUERY CACHE", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL FLUSH MYSQL QUERY CACHE") - 1 && !strncasecmp("PROXYSQL FLUSH MYSQL QUERY CACHE", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH MYSQL QUERY CACHE command\n"); ProxySQL_Admin* SPA = (ProxySQL_Admin*)pa; if (GloMyQC) { @@ -1010,7 +1022,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length == strlen("PROXYSQL FLUSH PGSQL QUERY CACHE") && !strncasecmp("PROXYSQL FLUSH PGSQL QUERY CACHE", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL FLUSH PGSQL QUERY CACHE") - 1 && !strncasecmp("PROXYSQL FLUSH PGSQL QUERY CACHE", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH PGSQL QUERY CACHE command\n"); ProxySQL_Admin* SPA = (ProxySQL_Admin*)pa; uint64_t count = 0; @@ -1041,7 +1053,12 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (!strcasecmp("PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE", query_no_space)) { + static const char *flush_pass_query = "PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE"; + static const size_t flush_pass_query_len = sizeof("PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE") - 1; + if ( + query_no_space_length == static_cast(flush_pass_query_len) + && !strncasecmp(flush_pass_query, query_no_space, flush_pass_query_len) + ) { proxy_info("Received PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE command\n"); ProxySQL_Admin *SPA = (ProxySQL_Admin *)pa; if (GloMyPTAuthCache) { @@ -1053,7 +1070,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ { static const char *pt_prefix = "PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE FOR USER "; - const size_t pt_prefix_len = strlen(pt_prefix); + static const size_t pt_prefix_len = sizeof("PROXYSQL FLUSH PASSTHROUGH_AUTH_CACHE FOR USER ") - 1; if (query_no_space_length > pt_prefix_len && !strncasecmp(pt_prefix, query_no_space, pt_prefix_len)) { const char *user_start = query_no_space + pt_prefix_len; @@ -1081,9 +1098,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ } } - if ( - (query_no_space_length==strlen("PROXYSQL FLUSH CONFIGDB") && !strncasecmp("PROXYSQL FLUSH CONFIGDB",query_no_space, query_no_space_length)) // see #923 - ) { + if (query_no_space_length==sizeof("PROXYSQL FLUSH CONFIGDB") - 1 && !strncasecmp("PROXYSQL FLUSH CONFIGDB",query_no_space, query_no_space_length)) { // see #923 proxy_info("Received %s command\n", query_no_space); proxy_warning("A misconfigured configdb will cause undefined behaviors\n"); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1093,7 +1108,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ } #ifdef DEBUG - if (query_no_space_length == strlen("PROXYSQL FLUSH STATS") && !strncasecmp("PROXYSQL FLUSH STATS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL FLUSH STATS") - 1 && !strncasecmp("PROXYSQL FLUSH STATS", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH STATS command\n"); ProxySQL_Admin *SPA = (ProxySQL_Admin *)pa; SPA->flush_stats(); @@ -1101,7 +1116,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length == strlen("PROXYSQL FLUSH MYSQL STATS") && !strncasecmp("PROXYSQL FLUSH MYSQL STATS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL FLUSH MYSQL STATS") - 1 && !strncasecmp("PROXYSQL FLUSH MYSQL STATS", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH MYSQL STATS command\n"); ProxySQL_Admin *SPA = (ProxySQL_Admin *)pa; SPA->flush_mysql_stats(); @@ -1109,7 +1124,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return false; } - if (query_no_space_length == strlen("PROXYSQL FLUSH PGSQL STATS") && !strncasecmp("PROXYSQL FLUSH PGSQL STATS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL FLUSH PGSQL STATS") - 1 && !strncasecmp("PROXYSQL FLUSH PGSQL STATS", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL FLUSH PGSQL STATS command\n"); ProxySQL_Admin *SPA = (ProxySQL_Admin *)pa; SPA->flush_pgsql_stats(); @@ -1119,7 +1134,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ #endif // DEBUG #ifdef PROXYSQLTSDB - if (query_no_space_length == strlen("PROXYSQL TSDB DOWNSAMPLE") && !strncasecmp("PROXYSQL TSDB DOWNSAMPLE", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("PROXYSQL TSDB DOWNSAMPLE") - 1 && !strncasecmp("PROXYSQL TSDB DOWNSAMPLE", query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL TSDB DOWNSAMPLE command\n"); if (GloProxyStats) { GloProxyStats->tsdb_downsample_metrics(); @@ -1166,13 +1181,13 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ } #ifndef NOJEM - if (query_no_space_length==strlen("PROXYSQL MEMPROFILE START") && !strncasecmp("PROXYSQL MEMPROFILE START",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL MEMPROFILE START") - 1 && !strncasecmp("PROXYSQL MEMPROFILE START",query_no_space, query_no_space_length)) { bool en=true; mallctl("prof.active", NULL, NULL, &en, sizeof(bool)); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); return false; } - if (query_no_space_length==strlen("PROXYSQL MEMPROFILE STOP") && !strncasecmp("PROXYSQL MEMPROFILE STOP",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL MEMPROFILE STOP") - 1 && !strncasecmp("PROXYSQL MEMPROFILE STOP",query_no_space, query_no_space_length)) { bool en=false; mallctl("prof.active", NULL, NULL, &en, sizeof(bool)); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); @@ -1181,13 +1196,13 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ #endif #ifdef WITHGCOV - if (query_no_space_length==strlen("PROXYSQL GCOV DUMP") && !strncasecmp("PROXYSQL GCOV DUMP",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL GCOV DUMP") - 1 && !strncasecmp("PROXYSQL GCOV DUMP",query_no_space, query_no_space_length)) { proxy_info("Received %s command\n", query_no_space); __gcov_dump(); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); return false; } - if (query_no_space_length==strlen("PROXYSQL GCOV RESET") && !strncasecmp("PROXYSQL GCOV RESET",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL GCOV RESET") - 1 && !strncasecmp("PROXYSQL GCOV RESET",query_no_space, query_no_space_length)) { proxy_info("Received %s command\n", query_no_space); __gcov_reset(); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); @@ -1195,7 +1210,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ } #endif - if (query_no_space_length==strlen("PROXYSQL KILL") && !strncasecmp("PROXYSQL KILL",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL KILL") - 1 && !strncasecmp("PROXYSQL KILL",query_no_space, query_no_space_length)) { proxy_info("Received PROXYSQL KILL command\n"); #ifdef DEBUG // In debug builds prefer coordinated shutdown to avoid teardown races. @@ -1206,7 +1221,7 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ #endif } - if (query_no_space_length==strlen("PROXYSQL SHUTDOWN") && !strncasecmp("PROXYSQL SHUTDOWN",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("PROXYSQL SHUTDOWN") - 1 && !strncasecmp("PROXYSQL SHUTDOWN",query_no_space, query_no_space_length)) { // in 2.1 , PROXYSQL SHUTDOWN behaves like PROXYSQL KILL : quick exit // the former PROXYQL SHUTDOWN is now replaced with PROXYSQL SHUTDOWN SLOW proxy_info("Received PROXYSQL SHUTDOWN command\n"); @@ -1258,10 +1273,10 @@ static char* mask_sensitive_values_in_query(const char* query) { /** * @brief Checks if a given variable name is considered sensitive (e.g., passwords, credentials). - * + * * This function identifies variable names that, if logged in plaintext, could * expose sensitive information. - * + * * @param var_name The name of the variable to check. * @return True if the variable name is sensitive, false otherwise. */ @@ -1276,24 +1291,29 @@ static bool is_sensitive_set_variable_name(const char* var_name) { // Returns true if the given name is either a known mysql or admin global variable. bool is_valid_global_variable(const char *var_name) { - if (strlen(var_name) > 6 && !strncmp(var_name, "mysql-", 6) && GloMTH->has_variable(var_name + 6)) { + if (var_name == NULL) { + return false; + } + const std::string_view name = var_name; + + if (name.size() > 6 && name.compare(0, 6, "mysql-") == 0 && GloMTH->has_variable(var_name + 6)) { return true; - } else if (strlen(var_name) > 6 && !strncmp(var_name, "pgsql-", 6) && GloPTH->has_variable(var_name + 6)) { + } else if (name.size() > 6 && name.compare(0, 6, "pgsql-") == 0 && GloPTH->has_variable(var_name + 6)) { return true; - } else if (strlen(var_name) > 6 && !strncmp(var_name, "admin-", 6) && SPA->has_variable(var_name + 6)) { + } else if (name.size() > 6 && name.compare(0, 6, "admin-") == 0 && SPA->has_variable(var_name + 6)) { return true; -#ifdef PROXYSQLTSDB - } else if (strlen(var_name) > 5 && !strncmp(var_name, "tsdb-", 5) && GloProxyStats && GloProxyStats->has_variable(var_name + 5)) { + #ifdef PROXYSQLTSDB + } else if (name.size() > 5 && name.compare(0, 5, "tsdb-") == 0 && GloProxyStats && GloProxyStats->has_variable(var_name + 5)) { return true; -#endif - } else if (strlen(var_name) > 5 && !strncmp(var_name, "ldap-", 5) && GloMyLdapAuth && GloMyLdapAuth->has_variable(var_name + 5)) { + #endif + } else if (name.size() > 5 && name.compare(0, 5, "ldap-") == 0 && GloMyLdapAuth && GloMyLdapAuth->has_variable(var_name + 5)) { return true; - } else if (strlen(var_name) > 13 && !strncmp(var_name, "sqliteserver-", 13) && GloSQLite3Server && GloSQLite3Server->has_variable(var_name + 13)) { + } else if (name.size() > 13 && name.compare(0, 13, "sqliteserver-") == 0 && GloSQLite3Server && GloSQLite3Server->has_variable(var_name + 13)) { return true; -#ifdef PROXYSQLCLICKHOUSE - } else if (strlen(var_name) > 11 && !strncmp(var_name, "clickhouse-", 11) && GloClickHouseServer && GloClickHouseServer->has_variable(var_name + 11)) { + #ifdef PROXYSQLCLICKHOUSE + } else if (name.size() > 11 && name.compare(0, 11, "clickhouse-") == 0 && GloClickHouseServer && GloClickHouseServer->has_variable(var_name + 11)) { return true; -#endif /* PROXYSQLCLICKHOUSE */ + #endif /* PROXYSQLCLICKHOUSE */ // `mcp-*` and `genai-*` variables live in the genai plugin // (carve-out Steps 4.C and 5). Core no longer holds an // authoritative list, so we accept any `mcp-` / @@ -1309,9 +1329,9 @@ bool is_valid_global_variable(const char *var_name) { // Step 7 removed the surrounding `#ifdef PROXYSQLGENAI` — these // loose prefix checks are unconditional now: SET only succeeds // at write-into-runtime time when the genai plugin is loaded. - } else if (strlen(var_name) > 4 && !strncmp(var_name, "mcp-", 4)) { + } else if (name.size() > 4 && name.compare(0, 4, "mcp-") == 0) { return true; - } else if (strlen(var_name) > 6 && !strncmp(var_name, "genai-", 6)) { + } else if (name.size() > 6 && name.compare(0, 6, "genai-") == 0) { return true; } else { return false; @@ -1330,8 +1350,8 @@ bool admin_handler_command_set(char *query_no_space, unsigned int query_no_space strstr(query_no_space, (char *)"mysql-default_authentication_plugin"); if (!skip_raw_query_log) { // issue #599 proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command %s\n", query_no_space); - if (strncasecmp(query_no_space,(char *)"set autocommit",strlen((char *)"set autocommit"))) { - if (strncasecmp(query_no_space,(char *)"SET @@session.autocommit",strlen((char *)"SET @@session.autocommit"))) { + if (strncasecmp(query_no_space,"set autocommit",sizeof("set autocommit") - 1)) { + if (strncasecmp(query_no_space,"SET @@session.autocommit",sizeof("SET @@session.autocommit") - 1)) { char* masked_query = mask_sensitive_values_in_query(query_no_space); proxy_info("Received command %s\n", masked_query); free(masked_query); @@ -1340,7 +1360,7 @@ bool admin_handler_command_set(char *query_no_space, unsigned int query_no_space } // Get a pointer to the beginning of var=value entry and split to get var name and value - char *set_entry = query_no_space + strlen("SET "); + char *set_entry = query_no_space + sizeof("SET ") - 1; char *untrimmed_var_name=NULL; char *var_value=NULL; c_split_2(set_entry, "=", &untrimmed_var_name, &var_value); @@ -1407,11 +1427,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query #ifdef DEBUG if ((query_no_space_length>11) && ( (!strncasecmp("SAVE DEBUG ", query_no_space, 11)) || (!strncasecmp("LOAD DEBUG ", query_no_space, 11))) ) { if ( - (query_no_space_length==strlen("LOAD DEBUG TO MEMORY") && !strncasecmp("LOAD DEBUG TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG TO MEMORY") - 1 && !strncasecmp("LOAD DEBUG TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD DEBUG TO MEM") && !strncasecmp("LOAD DEBUG TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG TO MEM") - 1 && !strncasecmp("LOAD DEBUG TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD DEBUG FROM DISK") && !strncasecmp("LOAD DEBUG FROM DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG FROM DISK") - 1 && !strncasecmp("LOAD DEBUG FROM DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); // we are now copying the data from memory to disk @@ -1431,11 +1451,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE DEBUG FROM MEMORY") && !strncasecmp("SAVE DEBUG FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG FROM MEMORY") - 1 && !strncasecmp("SAVE DEBUG FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE DEBUG FROM MEM") && !strncasecmp("SAVE DEBUG FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG FROM MEM") - 1 && !strncasecmp("SAVE DEBUG FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE DEBUG TO DISK") && !strncasecmp("SAVE DEBUG TO DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG TO DISK") - 1 && !strncasecmp("SAVE DEBUG TO DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); // we are now copying the data from disk to memory @@ -1455,13 +1475,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD DEBUG FROM MEMORY") && !strncasecmp("LOAD DEBUG FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG FROM MEMORY") - 1 && !strncasecmp("LOAD DEBUG FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD DEBUG FROM MEM") && !strncasecmp("LOAD DEBUG FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG FROM MEM") - 1 && !strncasecmp("LOAD DEBUG FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD DEBUG TO RUNTIME") && !strncasecmp("LOAD DEBUG TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG TO RUNTIME") - 1 && !strncasecmp("LOAD DEBUG TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD DEBUG TO RUN") && !strncasecmp("LOAD DEBUG TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD DEBUG TO RUN") - 1 && !strncasecmp("LOAD DEBUG TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1477,13 +1497,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE DEBUG TO MEMORY") && !strncasecmp("SAVE DEBUG TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG TO MEMORY") - 1 && !strncasecmp("SAVE DEBUG TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE DEBUG TO MEM") && !strncasecmp("SAVE DEBUG TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG TO MEM") - 1 && !strncasecmp("SAVE DEBUG TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE DEBUG FROM RUNTIME") && !strncasecmp("SAVE DEBUG FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG FROM RUNTIME") - 1 && !strncasecmp("SAVE DEBUG FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE DEBUG FROM RUN") && !strncasecmp("SAVE DEBUG FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE DEBUG FROM RUN") - 1 && !strncasecmp("SAVE DEBUG FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1502,13 +1522,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; if ( - (query_no_space_length==strlen("LOAD RESTAPI FROM MEMORY") && !strncasecmp("LOAD RESTAPI FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD RESTAPI FROM MEMORY") - 1 && !strncasecmp("LOAD RESTAPI FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD RESTAPI FROM MEM") && !strncasecmp("LOAD RESTAPI FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD RESTAPI FROM MEM") - 1 && !strncasecmp("LOAD RESTAPI FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD RESTAPI TO RUNTIME") && !strncasecmp("LOAD RESTAPI TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD RESTAPI TO RUNTIME") - 1 && !strncasecmp("LOAD RESTAPI TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD RESTAPI TO RUN") && !strncasecmp("LOAD RESTAPI TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD RESTAPI TO RUN") - 1 && !strncasecmp("LOAD RESTAPI TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1519,7 +1539,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD RESTAPI FROM CONFIG") && !strncasecmp("LOAD RESTAPI FROM CONFIG",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD RESTAPI FROM CONFIG") - 1 && !strncasecmp("LOAD RESTAPI FROM CONFIG",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); if (GloVars.configfile_open) { @@ -1547,13 +1567,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE RESTAPI TO MEMORY") && !strncasecmp("SAVE RESTAPI TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE RESTAPI TO MEMORY") - 1 && !strncasecmp("SAVE RESTAPI TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE RESTAPI TO MEM") && !strncasecmp("SAVE RESTAPI TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE RESTAPI TO MEM") - 1 && !strncasecmp("SAVE RESTAPI TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE RESTAPI FROM RUNTIME") && !strncasecmp("SAVE RESTAPI FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE RESTAPI FROM RUNTIME") - 1 && !strncasecmp("SAVE RESTAPI FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE RESTAPI FROM RUN") && !strncasecmp("SAVE RESTAPI FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE RESTAPI FROM RUN") - 1 && !strncasecmp("SAVE RESTAPI FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1570,13 +1590,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; if ( - (query_no_space_length==strlen("LOAD SCHEDULER FROM MEMORY") && !strncasecmp("LOAD SCHEDULER FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SCHEDULER FROM MEMORY") - 1 && !strncasecmp("LOAD SCHEDULER FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SCHEDULER FROM MEM") && !strncasecmp("LOAD SCHEDULER FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SCHEDULER FROM MEM") - 1 && !strncasecmp("LOAD SCHEDULER FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SCHEDULER TO RUNTIME") && !strncasecmp("LOAD SCHEDULER TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SCHEDULER TO RUNTIME") - 1 && !strncasecmp("LOAD SCHEDULER TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SCHEDULER TO RUN") && !strncasecmp("LOAD SCHEDULER TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SCHEDULER TO RUN") - 1 && !strncasecmp("LOAD SCHEDULER TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1587,7 +1607,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD SCHEDULER FROM CONFIG") && !strncasecmp("LOAD SCHEDULER FROM CONFIG",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SCHEDULER FROM CONFIG") - 1 && !strncasecmp("LOAD SCHEDULER FROM CONFIG",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); if (GloVars.configfile_open) { @@ -1615,13 +1635,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE SCHEDULER TO MEMORY") && !strncasecmp("SAVE SCHEDULER TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SCHEDULER TO MEMORY") - 1 && !strncasecmp("SAVE SCHEDULER TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SCHEDULER TO MEM") && !strncasecmp("SAVE SCHEDULER TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SCHEDULER TO MEM") - 1 && !strncasecmp("SAVE SCHEDULER TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SCHEDULER FROM RUNTIME") && !strncasecmp("SAVE SCHEDULER FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SCHEDULER FROM RUNTIME") - 1 && !strncasecmp("SAVE SCHEDULER FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SCHEDULER FROM RUN") && !strncasecmp("SAVE SCHEDULER FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SCHEDULER FROM RUN") - 1 && !strncasecmp("SAVE SCHEDULER FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1636,8 +1656,9 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query if (query_no_space_length>27) { if (!strncasecmp(" TO RUNTIME", query_no_space+query_no_space_length-11, 11)) { char *name=(char *)malloc(query_no_space_length-27+1); - strncpy(name,query_no_space+16,query_no_space_length-27); - name[query_no_space_length-27]=0; + size_t name_len = (size_t)(query_no_space_length - 27); + memcpy(name,query_no_space+16, name_len); + name[name_len]=0; int i=0; int s=strlen(name); bool legitname=true; @@ -1686,11 +1707,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query #ifdef PROXYSQLCLICKHOUSE if ( ( GloVars.global.clickhouse_server == true ) && (query_no_space_length>22) && ( (!strncasecmp("SAVE CLICKHOUSE USERS ", query_no_space, 22)) || (!strncasecmp("LOAD CLICKHOUSE USERS ", query_no_space, 22))) ) { if ( - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS TO MEMORY") && !strncasecmp("LOAD CLICKHOUSE USERS TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS TO MEMORY") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS TO MEM") && !strncasecmp("LOAD CLICKHOUSE USERS TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS TO MEM") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS FROM DISK") && !strncasecmp("LOAD CLICKHOUSE USERS FROM DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS FROM DISK") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS FROM DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1701,11 +1722,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS FROM MEMORY") && !strncasecmp("SAVE CLICKHOUSE USERS FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS FROM MEMORY") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS FROM MEM") && !strncasecmp("SAVE CLICKHOUSE USERS FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS FROM MEM") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS TO DISK") && !strncasecmp("SAVE CLICKHOUSE USERS TO DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS TO DISK") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS TO DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1716,13 +1737,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS FROM MEMORY") && !strncasecmp("LOAD CLICKHOUSE USERS FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS FROM MEMORY") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS FROM MEM") && !strncasecmp("LOAD CLICKHOUSE USERS FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS FROM MEM") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS TO RUNTIME") && !strncasecmp("LOAD CLICKHOUSE USERS TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS TO RUNTIME") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE USERS TO RUN") && !strncasecmp("LOAD CLICKHOUSE USERS TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE USERS TO RUN") - 1 && !strncasecmp("LOAD CLICKHOUSE USERS TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1733,13 +1754,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS TO MEMORY") && !strncasecmp("SAVE CLICKHOUSE USERS TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS TO MEMORY") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS TO MEM") && !strncasecmp("SAVE CLICKHOUSE USERS TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS TO MEM") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS FROM RUNTIME") && !strncasecmp("SAVE CLICKHOUSE USERS FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS FROM RUNTIME") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE USERS FROM RUN") && !strncasecmp("SAVE CLICKHOUSE USERS FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE USERS FROM RUN") - 1 && !strncasecmp("SAVE CLICKHOUSE USERS FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1776,7 +1797,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; } - if ((query_no_space_length>17) && + if ((query_no_space_length>17) && ((!strncasecmp("SAVE MYSQL USERS ", query_no_space, 17)) || (!strncasecmp("LOAD MYSQL USERS ", query_no_space, 17)) || ((!strncasecmp("SAVE PGSQL USERS ", query_no_space, 17)) || (!strncasecmp("LOAD PGSQL USERS ", query_no_space, 17))))) { @@ -1786,7 +1807,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query tuple, vector>& t = load_save_disk_commands[modname]; if ( is_admin_command_or_alias(get<1>(t), query_no_space, query_no_space_length) ) { ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; - + if (is_pgsql) SPA->flush_pgsql_users__from_disk_to_memory(); else @@ -1803,7 +1824,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query SPA->flush_pgsql_users__from_memory_to_disk(); else SPA->flush_mysql_users__from_memory_to_disk(); - + proxy_debug(PROXY_DEBUG_ADMIN, 4, "Saving %s to DISK\n", modname.c_str()); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); return false; @@ -1828,7 +1849,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD MYSQL USERS FROM CONFIG") && (!strncasecmp("LOAD MYSQL USERS FROM CONFIG",query_no_space, query_no_space_length) || + (query_no_space_length==sizeof("LOAD MYSQL USERS FROM CONFIG") - 1 && (!strncasecmp("LOAD MYSQL USERS FROM CONFIG",query_no_space, query_no_space_length) || !strncasecmp("LOAD PGSQL USERS FROM CONFIG", query_no_space, query_no_space_length))) ) { proxy_info("Received %s command\n", query_no_space); @@ -1896,11 +1917,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query if ((query_no_space_length>28) && ( (!strncasecmp("SAVE SQLITESERVER VARIABLES ", query_no_space, 28)) || (!strncasecmp("LOAD SQLITESERVER VARIABLES ", query_no_space, 28))) ) { if ( - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES TO MEMORY") && !strncasecmp("LOAD SQLITESERVER VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES TO MEMORY") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES TO MEM") && !strncasecmp("LOAD SQLITESERVER VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES TO MEM") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES FROM DISK") && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES FROM DISK") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -1910,11 +1931,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES FROM MEMORY") && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES FROM MEMORY") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES FROM MEM") && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES FROM MEM") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES TO DISK") && !strncasecmp("SAVE SQLITESERVER VARIABLES TO DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES TO DISK") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES TO DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -1924,13 +1945,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES FROM MEMORY") && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES FROM MEMORY") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES FROM MEM") && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES FROM MEM") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES TO RUNTIME") && !strncasecmp("LOAD SQLITESERVER VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES TO RUNTIME") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES TO RUN") && !strncasecmp("LOAD SQLITESERVER VARIABLES TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES TO RUN") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1941,13 +1962,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES TO MEMORY") && !strncasecmp("SAVE SQLITESERVER VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES TO MEMORY") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES TO MEM") && !strncasecmp("SAVE SQLITESERVER VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES TO MEM") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES FROM RUNTIME") && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES FROM RUNTIME") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE SQLITESERVER VARIABLES FROM RUN") && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE SQLITESERVER VARIABLES FROM RUN") - 1 && !strncasecmp("SAVE SQLITESERVER VARIABLES FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -1961,11 +1982,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query if ((query_no_space_length>26) && ( (!strncasecmp("SAVE CLICKHOUSE VARIABLES ", query_no_space, 26)) || (!strncasecmp("LOAD CLICKHOUSE VARIABLES ", query_no_space, 26))) ) { if ( - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES TO MEMORY") && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES TO MEMORY") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES TO MEM") && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES TO MEM") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES FROM DISK") && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES FROM DISK") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -1975,11 +1996,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES FROM MEMORY") && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES FROM MEMORY") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES FROM MEM") && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES FROM MEM") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES TO DISK") && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES TO DISK") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -1989,13 +2010,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES FROM MEMORY") && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES FROM MEMORY") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES FROM MEM") && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES FROM MEM") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES TO RUNTIME") && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES TO RUNTIME") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD CLICKHOUSE VARIABLES TO RUN") && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD CLICKHOUSE VARIABLES TO RUN") - 1 && !strncasecmp("LOAD CLICKHOUSE VARIABLES TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2006,13 +2027,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES TO MEMORY") && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES TO MEMORY") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES TO MEM") && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES TO MEM") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES FROM RUNTIME") && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES FROM RUNTIME") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE CLICKHOUSE VARIABLES FROM RUN") && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE CLICKHOUSE VARIABLES FROM RUN") - 1 && !strncasecmp("SAVE CLICKHOUSE VARIABLES FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2026,13 +2047,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query if (GloMyLdapAuth) { if ((query_no_space_length>20) && ( (!strncasecmp("SAVE LDAP VARIABLES ", query_no_space, 20)) || (!strncasecmp("LOAD LDAP VARIABLES ", query_no_space, 20))) ) { - + if ( - (query_no_space_length==strlen("LOAD LDAP VARIABLES TO MEMORY") && !strncasecmp("LOAD LDAP VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES TO MEMORY") - 1 && !strncasecmp("LOAD LDAP VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD LDAP VARIABLES TO MEM") && !strncasecmp("LOAD LDAP VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES TO MEM") - 1 && !strncasecmp("LOAD LDAP VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD LDAP VARIABLES FROM DISK") && !strncasecmp("LOAD LDAP VARIABLES FROM DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES FROM DISK") - 1 && !strncasecmp("LOAD LDAP VARIABLES FROM DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -2040,13 +2061,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query *ql=strlen(*q)+1; return true; } - + if ( - (query_no_space_length==strlen("SAVE LDAP VARIABLES FROM MEMORY") && !strncasecmp("SAVE LDAP VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES FROM MEMORY") - 1 && !strncasecmp("SAVE LDAP VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE LDAP VARIABLES FROM MEM") && !strncasecmp("SAVE LDAP VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES FROM MEM") - 1 && !strncasecmp("SAVE LDAP VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE LDAP VARIABLES TO DISK") && !strncasecmp("SAVE LDAP VARIABLES TO DISK",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES TO DISK") - 1 && !strncasecmp("SAVE LDAP VARIABLES TO DISK",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); l_free(*ql,*q); @@ -2054,15 +2075,15 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query *ql=strlen(*q)+1; return true; } - + if ( - (query_no_space_length==strlen("LOAD LDAP VARIABLES FROM MEMORY") && !strncasecmp("LOAD LDAP VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES FROM MEMORY") - 1 && !strncasecmp("LOAD LDAP VARIABLES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD LDAP VARIABLES FROM MEM") && !strncasecmp("LOAD LDAP VARIABLES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES FROM MEM") - 1 && !strncasecmp("LOAD LDAP VARIABLES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD LDAP VARIABLES TO RUNTIME") && !strncasecmp("LOAD LDAP VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES TO RUNTIME") - 1 && !strncasecmp("LOAD LDAP VARIABLES TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD LDAP VARIABLES TO RUN") && !strncasecmp("LOAD LDAP VARIABLES TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD LDAP VARIABLES TO RUN") - 1 && !strncasecmp("LOAD LDAP VARIABLES TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2075,15 +2096,15 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query SPA->send_ok_msg_to_client(sess, info, 0, query_no_space); return false; } - + if ( - (query_no_space_length==strlen("SAVE LDAP VARIABLES TO MEMORY") && !strncasecmp("SAVE LDAP VARIABLES TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES TO MEMORY") - 1 && !strncasecmp("SAVE LDAP VARIABLES TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE LDAP VARIABLES TO MEM") && !strncasecmp("SAVE LDAP VARIABLES TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES TO MEM") - 1 && !strncasecmp("SAVE LDAP VARIABLES TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE LDAP VARIABLES FROM RUNTIME") && !strncasecmp("SAVE LDAP VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES FROM RUNTIME") - 1 && !strncasecmp("SAVE LDAP VARIABLES FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE LDAP VARIABLES FROM RUN") && !strncasecmp("SAVE LDAP VARIABLES FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE LDAP VARIABLES FROM RUN") - 1 && !strncasecmp("SAVE LDAP VARIABLES FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2195,11 +2216,11 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD MYSQL VARIABLES FROM CONFIG") && !strncasecmp("LOAD MYSQL VARIABLES FROM CONFIG",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD PGSQL VARIABLES FROM CONFIG") && !strncasecmp("LOAD PGSQL VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD SQLITESERVER VARIABLES FROM CONFIG") && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD TSDB VARIABLES FROM CONFIG") && !strncasecmp("LOAD TSDB VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD GENAI VARIABLES FROM CONFIG") && !strncasecmp("LOAD GENAI VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD MYSQL VARIABLES FROM CONFIG",query_no_space, query_no_space_length)) || + (query_no_space_length==sizeof("LOAD PGSQL VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD PGSQL VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || + (query_no_space_length==sizeof("LOAD SQLITESERVER VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD SQLITESERVER VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || + (query_no_space_length==sizeof("LOAD TSDB VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD TSDB VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) || + (query_no_space_length==sizeof("LOAD GENAI VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD GENAI VARIABLES FROM CONFIG", query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); if (GloVars.configfile_open) { @@ -2332,9 +2353,9 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; } } - + if ( - (query_no_space_length==strlen("LOAD MYSQL SERVERS FROM CONFIG") && (!strncasecmp("LOAD MYSQL SERVERS FROM CONFIG",query_no_space, query_no_space_length) || + (query_no_space_length==sizeof("LOAD MYSQL SERVERS FROM CONFIG") - 1 && (!strncasecmp("LOAD MYSQL SERVERS FROM CONFIG",query_no_space, query_no_space_length) || !strncasecmp("LOAD PGSQL SERVERS FROM CONFIG", query_no_space, query_no_space_length) ))) { proxy_info("Received %s command\n", query_no_space); @@ -2418,13 +2439,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; */ if ( - (query_no_space_length==strlen("LOAD PROXYSQL SERVERS FROM MEMORY") && !strncasecmp("LOAD PROXYSQL SERVERS FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD PROXYSQL SERVERS FROM MEMORY") - 1 && !strncasecmp("LOAD PROXYSQL SERVERS FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD PROXYSQL SERVERS FROM MEM") && !strncasecmp("LOAD PROXYSQL SERVERS FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD PROXYSQL SERVERS FROM MEM") - 1 && !strncasecmp("LOAD PROXYSQL SERVERS FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD PROXYSQL SERVERS TO RUNTIME") && !strncasecmp("LOAD PROXYSQL SERVERS TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD PROXYSQL SERVERS TO RUNTIME") - 1 && !strncasecmp("LOAD PROXYSQL SERVERS TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD PROXYSQL SERVERS TO RUN") && !strncasecmp("LOAD PROXYSQL SERVERS TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD PROXYSQL SERVERS TO RUN") - 1 && !strncasecmp("LOAD PROXYSQL SERVERS TO RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2444,13 +2465,13 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; } if ( - (query_no_space_length==strlen("SAVE PROXYSQL SERVERS TO MEMORY") && !strncasecmp("SAVE PROXYSQL SERVERS TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE PROXYSQL SERVERS TO MEMORY") - 1 && !strncasecmp("SAVE PROXYSQL SERVERS TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE PROXYSQL SERVERS TO MEM") && !strncasecmp("SAVE PROXYSQL SERVERS TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE PROXYSQL SERVERS TO MEM") - 1 && !strncasecmp("SAVE PROXYSQL SERVERS TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE PROXYSQL SERVERS FROM RUNTIME") && !strncasecmp("SAVE PROXYSQL SERVERS FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE PROXYSQL SERVERS FROM RUNTIME") - 1 && !strncasecmp("SAVE PROXYSQL SERVERS FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE PROXYSQL SERVERS FROM RUN") && !strncasecmp("SAVE PROXYSQL SERVERS FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE PROXYSQL SERVERS FROM RUN") - 1 && !strncasecmp("SAVE PROXYSQL SERVERS FROM RUN",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2471,7 +2492,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD PROXYSQL SERVERS FROM CONFIG") && !strncasecmp("LOAD PROXYSQL SERVERS FROM CONFIG",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD PROXYSQL SERVERS FROM CONFIG") - 1 && !strncasecmp("LOAD PROXYSQL SERVERS FROM CONFIG",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); if (GloVars.configfile_open) { @@ -2516,7 +2537,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; if ( - (query_no_space_length==strlen("LOAD MYSQL FIREWALL FROM CONFIG") && (!strncasecmp("LOAD MYSQL FIREWALL FROM CONFIG",query_no_space, query_no_space_length) || + (query_no_space_length==sizeof("LOAD MYSQL FIREWALL FROM CONFIG") - 1 && (!strncasecmp("LOAD MYSQL FIREWALL FROM CONFIG",query_no_space, query_no_space_length) || !strncasecmp("LOAD PGSQL FIREWALL FROM CONFIG", query_no_space, query_no_space_length))) ) { proxy_info("Received %s command\n", query_no_space); @@ -2550,21 +2571,21 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD MYSQL FIREWALL FROM MEMORY") && !strncasecmp("LOAD MYSQL FIREWALL FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL FIREWALL FROM MEMORY") - 1 && !strncasecmp("LOAD MYSQL FIREWALL FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL FIREWALL FROM MEM") && !strncasecmp("LOAD MYSQL FIREWALL FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL FIREWALL FROM MEM") - 1 && !strncasecmp("LOAD MYSQL FIREWALL FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL FIREWALL TO RUNTIME") && !strncasecmp("LOAD MYSQL FIREWALL TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL FIREWALL TO RUNTIME") - 1 && !strncasecmp("LOAD MYSQL FIREWALL TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL FIREWALL TO RUN") && !strncasecmp("LOAD MYSQL FIREWALL TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL FIREWALL TO RUN") - 1 && !strncasecmp("LOAD MYSQL FIREWALL TO RUN",query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL FIREWALL FROM MEMORY") && !strncasecmp("LOAD PGSQL FIREWALL FROM MEMORY", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL FIREWALL FROM MEMORY") - 1 && !strncasecmp("LOAD PGSQL FIREWALL FROM MEMORY", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL FIREWALL FROM MEM") && !strncasecmp("LOAD PGSQL FIREWALL FROM MEM", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL FIREWALL FROM MEM") - 1 && !strncasecmp("LOAD PGSQL FIREWALL FROM MEM", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL FIREWALL TO RUNTIME") && !strncasecmp("LOAD PGSQL FIREWALL TO RUNTIME", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL FIREWALL TO RUNTIME") - 1 && !strncasecmp("LOAD PGSQL FIREWALL TO RUNTIME", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL FIREWALL TO RUN") && !strncasecmp("LOAD PGSQL FIREWALL TO RUN", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL FIREWALL TO RUN") - 1 && !strncasecmp("LOAD PGSQL FIREWALL TO RUN", query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -2579,21 +2600,21 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("SAVE MYSQL FIREWALL TO MEMORY") && !strncasecmp("SAVE MYSQL FIREWALL TO MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE MYSQL FIREWALL TO MEMORY") - 1 && !strncasecmp("SAVE MYSQL FIREWALL TO MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE MYSQL FIREWALL TO MEM") && !strncasecmp("SAVE MYSQL FIREWALL TO MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE MYSQL FIREWALL TO MEM") - 1 && !strncasecmp("SAVE MYSQL FIREWALL TO MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE MYSQL FIREWALL FROM RUNTIME") && !strncasecmp("SAVE MYSQL FIREWALL FROM RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE MYSQL FIREWALL FROM RUNTIME") - 1 && !strncasecmp("SAVE MYSQL FIREWALL FROM RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SAVE MYSQL FIREWALL FROM RUN") && !strncasecmp("SAVE MYSQL FIREWALL FROM RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SAVE MYSQL FIREWALL FROM RUN") - 1 && !strncasecmp("SAVE MYSQL FIREWALL FROM RUN",query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL FIREWALL TO MEMORY") && !strncasecmp("SAVE PGSQL FIREWALL TO MEMORY", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL FIREWALL TO MEMORY") - 1 && !strncasecmp("SAVE PGSQL FIREWALL TO MEMORY", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL FIREWALL TO MEM") && !strncasecmp("SAVE PGSQL FIREWALL TO MEM", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL FIREWALL TO MEM") - 1 && !strncasecmp("SAVE PGSQL FIREWALL TO MEM", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL FIREWALL FROM RUNTIME") && !strncasecmp("SAVE PGSQL FIREWALL FROM RUNTIME", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL FIREWALL FROM RUNTIME") - 1 && !strncasecmp("SAVE PGSQL FIREWALL FROM RUNTIME", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL FIREWALL FROM RUN") && !strncasecmp("SAVE PGSQL FIREWALL FROM RUN", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL FIREWALL FROM RUN") - 1 && !strncasecmp("SAVE PGSQL FIREWALL FROM RUN", query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); @@ -2619,7 +2640,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query return false; if ( - (query_no_space_length==strlen("LOAD MYSQL QUERY RULES FROM CONFIG") && (!strncasecmp("LOAD MYSQL QUERY RULES FROM CONFIG",query_no_space, query_no_space_length) || + (query_no_space_length==sizeof("LOAD MYSQL QUERY RULES FROM CONFIG") - 1 && (!strncasecmp("LOAD MYSQL QUERY RULES FROM CONFIG",query_no_space, query_no_space_length) || !strncasecmp("LOAD PGSQL QUERY RULES FROM CONFIG", query_no_space, query_no_space_length))) ) { proxy_info("Received %s command\n", query_no_space); @@ -2655,27 +2676,27 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD MYSQL QUERY RULES FROM MEMORY") && !strncasecmp("LOAD MYSQL QUERY RULES FROM MEMORY",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL QUERY RULES FROM MEMORY") - 1 && !strncasecmp("LOAD MYSQL QUERY RULES FROM MEMORY",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL QUERY RULES FROM MEM") && !strncasecmp("LOAD MYSQL QUERY RULES FROM MEM",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL QUERY RULES FROM MEM") - 1 && !strncasecmp("LOAD MYSQL QUERY RULES FROM MEM",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL QUERY RULES TO RUNTIME") && !strncasecmp("LOAD MYSQL QUERY RULES TO RUNTIME",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL QUERY RULES TO RUNTIME") - 1 && !strncasecmp("LOAD MYSQL QUERY RULES TO RUNTIME",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("LOAD MYSQL QUERY RULES TO RUN") && !strncasecmp("LOAD MYSQL QUERY RULES TO RUN",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD MYSQL QUERY RULES TO RUN") - 1 && !strncasecmp("LOAD MYSQL QUERY RULES TO RUN",query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL QUERY RULES FROM MEMORY") && !strncasecmp("LOAD PGSQL QUERY RULES FROM MEMORY", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL QUERY RULES FROM MEMORY") - 1 && !strncasecmp("LOAD PGSQL QUERY RULES FROM MEMORY", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL QUERY RULES FROM MEM") && !strncasecmp("LOAD PGSQL QUERY RULES FROM MEM", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL QUERY RULES FROM MEM") - 1 && !strncasecmp("LOAD PGSQL QUERY RULES FROM MEM", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL QUERY RULES TO RUNTIME") && !strncasecmp("LOAD PGSQL QUERY RULES TO RUNTIME", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL QUERY RULES TO RUNTIME") - 1 && !strncasecmp("LOAD PGSQL QUERY RULES TO RUNTIME", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("LOAD PGSQL QUERY RULES TO RUN") && !strncasecmp("LOAD PGSQL QUERY RULES TO RUN", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("LOAD PGSQL QUERY RULES TO RUN") - 1 && !strncasecmp("LOAD PGSQL QUERY RULES TO RUN", query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; char* err = NULL; - + if (query_no_space[5] == 'P' || query_no_space[5] == 'p') err = SPA->load_pgsql_query_rules_to_runtime(); else @@ -2686,7 +2707,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded pgsql query rules to RUNTIME\n"); else proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded mysql query rules to RUNTIME\n"); - + SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); } else { SPA->send_error_msg_to_client(sess, err); @@ -2695,21 +2716,21 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length == strlen("SAVE MYSQL QUERY RULES TO MEMORY") && !strncasecmp("SAVE MYSQL QUERY RULES TO MEMORY", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE MYSQL QUERY RULES TO MEMORY") - 1 && !strncasecmp("SAVE MYSQL QUERY RULES TO MEMORY", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE MYSQL QUERY RULES TO MEM") && !strncasecmp("SAVE MYSQL QUERY RULES TO MEM", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE MYSQL QUERY RULES TO MEM") - 1 && !strncasecmp("SAVE MYSQL QUERY RULES TO MEM", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE MYSQL QUERY RULES FROM RUNTIME") && !strncasecmp("SAVE MYSQL QUERY RULES FROM RUNTIME", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE MYSQL QUERY RULES FROM RUNTIME") - 1 && !strncasecmp("SAVE MYSQL QUERY RULES FROM RUNTIME", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE MYSQL QUERY RULES FROM RUN") && !strncasecmp("SAVE MYSQL QUERY RULES FROM RUN", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE MYSQL QUERY RULES FROM RUN") - 1 && !strncasecmp("SAVE MYSQL QUERY RULES FROM RUN", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL QUERY RULES TO MEMORY") && !strncasecmp("SAVE PGSQL QUERY RULES TO MEMORY", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL QUERY RULES TO MEMORY") - 1 && !strncasecmp("SAVE PGSQL QUERY RULES TO MEMORY", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL QUERY RULES TO MEM") && !strncasecmp("SAVE PGSQL QUERY RULES TO MEM", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL QUERY RULES TO MEM") - 1 && !strncasecmp("SAVE PGSQL QUERY RULES TO MEM", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL QUERY RULES FROM RUNTIME") && !strncasecmp("SAVE PGSQL QUERY RULES FROM RUNTIME", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL QUERY RULES FROM RUNTIME") - 1 && !strncasecmp("SAVE PGSQL QUERY RULES FROM RUNTIME", query_no_space, query_no_space_length)) || - (query_no_space_length == strlen("SAVE PGSQL QUERY RULES FROM RUN") && !strncasecmp("SAVE PGSQL QUERY RULES FROM RUN", query_no_space, query_no_space_length)) + (query_no_space_length == sizeof("SAVE PGSQL QUERY RULES FROM RUN") - 1 && !strncasecmp("SAVE PGSQL QUERY RULES FROM RUN", query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); @@ -2754,7 +2775,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } if ( - (query_no_space_length==strlen("LOAD ADMIN VARIABLES FROM CONFIG") && !strncasecmp("LOAD ADMIN VARIABLES FROM CONFIG",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("LOAD ADMIN VARIABLES FROM CONFIG") - 1 && !strncasecmp("LOAD ADMIN VARIABLES FROM CONFIG",query_no_space, query_no_space_length)) ) { proxy_info("Received %s command\n", query_no_space); if (GloVars.configfile_open) { @@ -2791,8 +2812,8 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query } - if (!strncasecmp("SAVE CONFIG TO FILE", query_no_space, strlen("SAVE CONFIG TO FILE"))) { - std::string fileName = query_no_space + strlen("SAVE CONFIG TO FILE"); + if (!strncasecmp("SAVE CONFIG TO FILE", query_no_space, sizeof("SAVE CONFIG TO FILE") - 1)) { + std::string fileName = query_no_space + sizeof("SAVE CONFIG TO FILE") - 1; fileName.erase(0, fileName.find_first_not_of("\t\n\v\f\r ")); fileName.erase(fileName.find_last_not_of("\t\n\v\f\r ") + 1); @@ -2872,7 +2893,7 @@ std::string timediff_timezone_offset() { time(&rawtime); info = localtime(&rawtime); strftime(result, 8, "%z", info); - offset = (result[0] == '+') ? 1 : 0; + offset = (result[0] == '+') ? 1 : 0; time_zone_offset = ((std::string)(result)).substr(offset, 3-offset) + ":" + ((std::string)(result)).substr(3, 2) + ":00"; return time_zone_offset; @@ -2972,7 +2993,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { run_query = false; goto __run_query; } - + switch (hdr.type) { case PG_PKT_STARTUP_V2: case PG_PKT_STARTUP: @@ -3012,7 +3033,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { if (query_no_space_length) { // fix bug #925 - while (query_no_space_length && + while (query_no_space_length && (query_no_space[query_no_space_length-1]==';' || query_no_space[query_no_space_length-1]==' ')) { query_no_space_length--; query_no_space[query_no_space_length]=0; @@ -3029,15 +3050,17 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { // add global mutex, see bug #1188 pthread_mutex_lock(&pa->sql_query_global_mutex); - if (strcasestr(query_no_space, "INFORMATION_SCHEMA.TABLES") != nullptr) { - const char* info_table_name = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '"; - const char* info_engine_table_type = "SELECT engine, table_type FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '"; + if (strcasestr(query_no_space, "INFORMATION_SCHEMA.TABLES") != nullptr) { + const char* info_table_name = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '"; + const size_t info_table_name_len = sizeof("SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '") - 1; + const char* info_engine_table_type = "SELECT engine, table_type FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '"; + const size_t info_engine_table_type_len = sizeof("SELECT engine, table_type FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = DATABASE() AND table_name = '") - 1; - if (query_no_space_length > strlen(info_table_name) && - strncasecmp(query_no_space, info_table_name, strlen(info_table_name)) == 0) { - std::string query_str(query_no_space, query_no_space_length); + if (query_no_space_length > static_cast(info_table_name_len) && + strncasecmp(query_no_space, info_table_name, info_table_name_len) == 0) { + std::string query_str(query_no_space, query_no_space_length); - size_t start_pos = strlen(info_table_name); + size_t start_pos = info_table_name_len; size_t end_pos = query_str.find('\'', start_pos); if (end_pos != std::string::npos) { @@ -3055,11 +3078,11 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (query_no_space_length > strlen(info_engine_table_type) && - strncasecmp(query_no_space, info_engine_table_type, strlen(info_engine_table_type)) == 0) { - std::string query_str(query_no_space, query_no_space_length); + if (query_no_space_length > static_cast(info_engine_table_type_len) && + strncasecmp(query_no_space, info_engine_table_type, info_engine_table_type_len) == 0) { + std::string query_str(query_no_space, query_no_space_length); - size_t start_pos = strlen(info_engine_table_type); + size_t start_pos = info_engine_table_type_len; size_t end_pos = query_str.find('\'', start_pos); if (end_pos != std::string::npos) { @@ -3079,13 +3102,14 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if (strcasestr(query_no_space, "INFORMATION_SCHEMA.COLUMNS") != nullptr) { - const char* info_column_data_type = "SELECT column_name, extra, generation_expression, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema=database() AND table_name='"; + const char* info_column_data_type = "SELECT column_name, extra, generation_expression, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema=database() AND table_name='"; + const size_t info_column_data_type_len = sizeof("SELECT column_name, extra, generation_expression, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema=database() AND table_name='") - 1; - if (query_no_space_length > strlen(info_column_data_type) && - strncasecmp(query_no_space, info_column_data_type, strlen(info_column_data_type)) == 0) { - std::string query_str(query_no_space, query_no_space_length); + if (query_no_space_length > static_cast(info_column_data_type_len) && + strncasecmp(query_no_space, info_column_data_type, info_column_data_type_len) == 0) { + std::string query_str(query_no_space, query_no_space_length); - size_t start_pos = strlen(info_column_data_type); + size_t start_pos = info_column_data_type_len; size_t end_pos = query_str.find('\'', start_pos); if (end_pos != std::string::npos) { @@ -3104,7 +3128,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp("SELECT LOGFILE", query_no_space, strlen("SELECT LOGFILE")) && strcasestr(query_no_space, "FROM INFORMATION_SCHEMA.FILES") != nullptr) { + if (!strncasecmp("SELECT LOGFILE", query_no_space, sizeof("SELECT LOGFILE") - 1) && strcasestr(query_no_space, "FROM INFORMATION_SCHEMA.FILES") != nullptr) { string err_msg = "Invalid command - SELECT .. FROM INFORMATION_SCHEMA.FILES. "; err_msg += "If you are using mysqldump, use --no-tablespaces flag to avoid this error message"; SPA->send_error_msg_to_client(sess, const_cast(err_msg.c_str())); @@ -3113,9 +3137,9 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats - if (!strncasecmp("LOGENTRY ", query_no_space, strlen("LOGENTRY "))) { - proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command LOGENTRY: %s\n", query_no_space + strlen("LOGENTRY ")); - proxy_info("Received command LOGENTRY: %s\n", query_no_space + strlen("LOGENTRY ")); + if (!strncasecmp("LOGENTRY ", query_no_space, sizeof("LOGENTRY ") - 1)) { + proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command LOGENTRY: %s\n", query_no_space + sizeof("LOGENTRY ") - 1); + proxy_info("Received command LOGENTRY: %s\n", query_no_space + sizeof("LOGENTRY ") - 1); SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); run_query=false; goto __run_query; @@ -3123,7 +3147,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } - if (!strncasecmp("DUMP EVENTSLOG ", query_no_space, strlen("DUMP EVENTSLOG "))) { + if (!strncasecmp("DUMP EVENTSLOG ", query_no_space, sizeof("DUMP EVENTSLOG ") - 1)) { int num_rows = 0; proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command DUMP EVENTSLOG: %s\n", query_no_space); proxy_info("Received command DUMP EVENTSLOG: %s\n", query_no_space); @@ -3149,7 +3173,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("DUMP PGSQL EVENTSLOG ", query_no_space, strlen("DUMP PGSQL EVENTSLOG "))) { + if (!strncasecmp("DUMP PGSQL EVENTSLOG ", query_no_space, sizeof("DUMP PGSQL EVENTSLOG ") - 1)) { int num_rows = 0; proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command DUMP PGSQL EVENTSLOG: %s\n", query_no_space); proxy_info("Received command DUMP PGSQL EVENTSLOG: %s\n", query_no_space); @@ -3184,27 +3208,27 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { // handle special queries from Cluster // for bug #1188 , ProxySQL Admin needs to know the exact query - if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats - string tn = ""; - if (!strncasecmp(CLUSTER_QUERY_RUNTIME_MYSQL_SERVERS, query_no_space, strlen(CLUSTER_QUERY_RUNTIME_MYSQL_SERVERS))) { - tn = "cluster_mysql_servers"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_REPLICATION_HOSTGROUPS, query_no_space, strlen(CLUSTER_QUERY_MYSQL_REPLICATION_HOSTGROUPS))) { - tn = "mysql_replication_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS, query_no_space, strlen(CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS))) { - tn = "mysql_group_replication_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_GALERA, query_no_space, strlen(CLUSTER_QUERY_MYSQL_GALERA))) { - tn = "mysql_galera_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_AWS_AURORA, query_no_space, strlen(CLUSTER_QUERY_MYSQL_AWS_AURORA))) { - tn = "mysql_aws_aurora_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES, query_no_space, strlen(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES))) { - tn = "mysql_hostgroup_attributes"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS, query_no_space, strlen(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS))) { - tn = "mysql_servers_ssl_params"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_AWS_RDS_BGD, query_no_space, strlen(CLUSTER_QUERY_MYSQL_AWS_RDS_BGD))) { - tn = "mysql_aws_rds_bgd_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_V2, query_no_space, strlen(CLUSTER_QUERY_MYSQL_SERVERS_V2))) { - tn = "mysql_servers_v2"; - } + if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats + string tn = ""; + if (!strncasecmp(CLUSTER_QUERY_RUNTIME_MYSQL_SERVERS, query_no_space, sizeof(CLUSTER_QUERY_RUNTIME_MYSQL_SERVERS) - 1)) { + tn = "cluster_mysql_servers"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_REPLICATION_HOSTGROUPS, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_REPLICATION_HOSTGROUPS) - 1)) { + tn = "mysql_replication_hostgroups"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS) - 1)) { + tn = "mysql_group_replication_hostgroups"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_GALERA, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_GALERA) - 1)) { + tn = "mysql_galera_hostgroups"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_AWS_AURORA, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_AWS_AURORA) - 1)) { + tn = "mysql_aws_aurora_hostgroups"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES) - 1)) { + tn = "mysql_hostgroup_attributes"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS) - 1)) { + tn = "mysql_servers_ssl_params"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_AWS_RDS_BGD, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_AWS_RDS_BGD) - 1)) { + tn = "mysql_aws_rds_bgd_hostgroups"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_V2, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_SERVERS_V2) - 1)) { + tn = "mysql_servers_v2"; + } if (tn != "") { GloAdmin->mysql_servers_wrlock(); resultset = MyHGM->get_current_mysql_table(tn); @@ -3244,21 +3268,21 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { run_query=false; goto __run_query; } - + } } if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats string tn = ""; - if (!strncasecmp(CLUSTER_QUERY_RUNTIME_PGSQL_SERVERS, query_no_space, strlen(CLUSTER_QUERY_RUNTIME_PGSQL_SERVERS))) { + if (!strncasecmp(CLUSTER_QUERY_RUNTIME_PGSQL_SERVERS, query_no_space, sizeof(CLUSTER_QUERY_RUNTIME_PGSQL_SERVERS) - 1)) { tn = "cluster_pgsql_servers"; - } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_REPLICATION_HOSTGROUPS, query_no_space, strlen(CLUSTER_QUERY_PGSQL_REPLICATION_HOSTGROUPS))) { + } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_REPLICATION_HOSTGROUPS, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_REPLICATION_HOSTGROUPS) - 1)) { tn = "pgsql_replication_hostgroups"; - } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_HOSTGROUP_ATTRIBUTES, query_no_space, strlen(CLUSTER_QUERY_PGSQL_HOSTGROUP_ATTRIBUTES))) { + } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_HOSTGROUP_ATTRIBUTES, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_HOSTGROUP_ATTRIBUTES) - 1)) { tn = "pgsql_hostgroup_attributes"; - } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_SERVERS_V2, query_no_space, strlen(CLUSTER_QUERY_PGSQL_SERVERS_V2))) { + } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_SERVERS_V2, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_SERVERS_V2) - 1)) { tn = "pgsql_servers_v2"; - } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_SERVERS_SSL_PARAMS, query_no_space, strlen(CLUSTER_QUERY_PGSQL_SERVERS_SSL_PARAMS))) { + } else if (!strncasecmp(CLUSTER_QUERY_PGSQL_SERVERS_SSL_PARAMS, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_SERVERS_SSL_PARAMS) - 1)) { tn = "pgsql_servers_ssl_params"; } if (tn != "") { @@ -3301,7 +3325,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp(CLUSTER_QUERY_MYSQL_USERS, query_no_space, strlen(CLUSTER_QUERY_MYSQL_USERS))) { + if (!strncasecmp(CLUSTER_QUERY_MYSQL_USERS, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_USERS) - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { pthread_mutex_lock(&users_mutex); resultset = GloMyAuth->get_current_mysql_users(); @@ -3314,7 +3338,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp(CLUSTER_QUERY_PGSQL_USERS, query_no_space, strlen(CLUSTER_QUERY_PGSQL_USERS))) { + if (!strncasecmp(CLUSTER_QUERY_PGSQL_USERS, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_USERS) - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { pthread_mutex_lock(&users_mutex); resultset = GloPgAuth->get_current_pgsql_users(); @@ -3328,7 +3352,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats - if (!strncasecmp(CLUSTER_QUERY_MYSQL_QUERY_RULES, query_no_space, strlen(CLUSTER_QUERY_MYSQL_QUERY_RULES))) { + if (!strncasecmp(CLUSTER_QUERY_MYSQL_QUERY_RULES, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_QUERY_RULES) - 1)) { GloMyQPro->wrlock(); resultset = GloMyQPro->get_current_query_rules_inner(); if (resultset == NULL) { @@ -3348,7 +3372,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } } - if (!strncasecmp(CLUSTER_QUERY_MYSQL_QUERY_RULES_FAST_ROUTING, query_no_space, strlen(CLUSTER_QUERY_MYSQL_QUERY_RULES_FAST_ROUTING))) { + if (!strncasecmp(CLUSTER_QUERY_MYSQL_QUERY_RULES_FAST_ROUTING, query_no_space, sizeof(CLUSTER_QUERY_MYSQL_QUERY_RULES_FAST_ROUTING) - 1)) { GloMyQPro->wrlock(); resultset = GloMyQPro->get_current_query_rules_fast_routing_inner(); if (resultset == NULL) { @@ -3371,7 +3395,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats - if (!strncasecmp(CLUSTER_QUERY_PGSQL_QUERY_RULES, query_no_space, strlen(CLUSTER_QUERY_PGSQL_QUERY_RULES))) { + if (!strncasecmp(CLUSTER_QUERY_PGSQL_QUERY_RULES, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_QUERY_RULES) - 1)) { GloPgQPro->wrlock(); resultset = GloPgQPro->get_current_query_rules_inner(); if (resultset == NULL) { @@ -3394,7 +3418,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } } - if (!strncasecmp(CLUSTER_QUERY_PGSQL_QUERY_RULES_FAST_ROUTING, query_no_space, strlen(CLUSTER_QUERY_PGSQL_QUERY_RULES_FAST_ROUTING))) { + if (!strncasecmp(CLUSTER_QUERY_PGSQL_QUERY_RULES_FAST_ROUTING, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_QUERY_RULES_FAST_ROUTING) - 1)) { GloPgQPro->wrlock(); resultset = GloPgQPro->get_current_query_rules_fast_routing_inner(); if (resultset == NULL) { @@ -3419,7 +3443,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp(CLUSTER_QUERY_PGSQL_VARIABLES, query_no_space, strlen(CLUSTER_QUERY_PGSQL_VARIABLES))) { + if (!strncasecmp(CLUSTER_QUERY_PGSQL_VARIABLES, query_no_space, sizeof(CLUSTER_QUERY_PGSQL_VARIABLES) - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { pthread_mutex_lock(&GloVars.checksum_mutex); GloAdmin->flush_pgsql_variables___runtime_to_database(GloAdmin->admindb, false, false, false, true, true); @@ -3465,7 +3489,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("TRUNCATE ", query_no_space, strlen("TRUNCATE "))) { + if (!strncasecmp("TRUNCATE ", query_no_space, sizeof("TRUNCATE ") - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats if (strstr(query_no_space,"stats_mysql_query_digest")) { bool truncate_digest_table = false; @@ -3539,7 +3563,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { // handles 'PURGE stats_mysql_query_digest TO '. // any entry in stats_mysql_query_digest where last_seen is less than will be deleted. - if (!strncasecmp("PURGE ", query_no_space, strlen("PURGE ")) + if (!strncasecmp("PURGE ", query_no_space, sizeof("PURGE ") - 1) && sess->session_type == PROXYSQL_SESSION_ADMIN ) { auto result = parse_command_purge_query_digests(query_no_space, query_no_space_length); @@ -3586,13 +3610,13 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { * PROXYSQL_SIMULATOR mysql_error 1 127.0.0.1 3306 1234 * ``` */ - if (!strncasecmp("PROXYSQL_SIMULATOR ", query_no_space, strlen("PROXYSQL_SIMULATOR "))) { + if (!strncasecmp("PROXYSQL_SIMULATOR ", query_no_space, sizeof("PROXYSQL_SIMULATOR ") - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats proxy_warning("Received PROXYSQL_SIMULATOR command: %s\n", query_no_space); re2::RE2::Options opts = re2::RE2::Options(RE2::Quiet); re2::RE2 pattern("\\s*(\\w+) (\\d+) (\\d+\\.\\d+\\.\\d+\\.\\d+):(\\d+) (\\d+)\\s*\\;*", opts); - re2::StringPiece input(query_no_space + strlen("PROXYSQL_SIMULATOR")); + re2::StringPiece input(query_no_space + sizeof("PROXYSQL_SIMULATOR") - 1); std::string command, s_hg, srv_addr, s_port, s_errcode {}; bool c_res = re2::RE2::Consume(&input, pattern, &command, &s_hg, &srv_addr, &s_port, &s_errcode); @@ -3617,7 +3641,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { MySrvC* mysrvc = MyHGM->find_server_in_hg(i_hg, srv_addr, i_port); if (mysrvc != nullptr) { - int backup_shun_on_failures; + int backup_shun_on_failures; backup_shun_on_failures = mysql_thread___shun_on_failures; mysql_thread___shun_on_failures = 1; // Set the error twice to surpass 'mysql_thread___shun_on_failures' value. @@ -3669,7 +3693,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } #endif // DEBUG - if (!strncasecmp("PROXYSQLTEST ", query_no_space, strlen("PROXYSQLTEST "))) { + if (!strncasecmp("PROXYSQLTEST ", query_no_space, sizeof("PROXYSQLTEST ") - 1)) { if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; SPA->ProxySQL_Test_Handler(SPA, sess, query_no_space, run_query); @@ -3682,7 +3706,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } - if (!strncasecmp("SHOW GLOBAL VARIABLES LIKE 'read_only'", query_no_space, strlen("SHOW GLOBAL VARIABLES LIKE 'read_only'"))) { + if (!strncasecmp("SHOW GLOBAL VARIABLES LIKE 'read_only'", query_no_space, sizeof("SHOW GLOBAL VARIABLES LIKE 'read_only'") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT 'read_only' Variable_name, '%s' Value FROM global_variables WHERE Variable_name='admin-read_only'"; query_length=strlen(q)+5; @@ -3707,7 +3731,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("SELECT @@global.read_only", query_no_space, strlen("SELECT @@global.read_only"))) { + if (!strncasecmp("SELECT @@global.read_only", query_no_space, sizeof("SELECT @@global.read_only") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT 'read_only' Variable_name, '%s' Value FROM global_variables WHERE Variable_name='admin-read_only'"; query_length=strlen(q)+5; @@ -3760,7 +3784,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } - if ((query_no_space_length == strlen("SELECT GLOBAL_CHECKSUM()")) && (!strncasecmp("SELECT GLOBAL_CHECKSUM()", query_no_space, strlen("SELECT GLOBAL_CHECKSUM()")))) { + if ((query_no_space_length == sizeof("SELECT GLOBAL_CHECKSUM()") - 1) && (!strncasecmp("SELECT GLOBAL_CHECKSUM()", query_no_space, sizeof("SELECT GLOBAL_CHECKSUM()") - 1))) { char buf[32]; pthread_mutex_lock(&GloVars.checksum_mutex); sprintf(buf,"%lu",GloVars.checksums_values.global_checksum); @@ -3868,127 +3892,134 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { !strncmp("/*!50503 SET ", query_no_space, 13) || !strncmp("/*!50717 SET ", query_no_space, 13) || !strncmp("/*M!100100 SET ", query_no_space, 15) || - !strncmp("/*!50717 SELECT ", query_no_space, strlen("/*!50717 SELECT ")) || - !strncmp("/*!50717 PREPARE ", query_no_space, strlen("/*!50717 PREPARE ")) || - !strncmp("/*!50717 EXECUTE ", query_no_space, strlen("/*!50717 EXECUTE ")) || - !strncmp("/*!50717 DEALLOCATE ", query_no_space, strlen("/*!50717 DEALLOCATE ")) || - !strncmp("/*!50112 SET ", query_no_space, strlen("/*!50112 SET ")) || - !strncmp("/*!50112 PREPARE ", query_no_space, strlen("/*!50112 PREPARE ")) || - !strncmp("/*!50112 EXECUTE ", query_no_space, strlen("/*!50112 EXECUTE ")) || - !strncmp("/*!50112 DEALLOCATE ", query_no_space, strlen("/*!50112 DEALLOCATE ")) || - !strncmp("/*!40000 ALTER TABLE", query_no_space, strlen("/*!40000 ALTER TABLE")) + !strncmp("/*!50717 SELECT ", query_no_space, sizeof("/*!50717 SELECT ") - 1) || + !strncmp("/*!50717 PREPARE ", query_no_space, sizeof("/*!50717 PREPARE ") - 1) || + !strncmp("/*!50717 EXECUTE ", query_no_space, sizeof("/*!50717 EXECUTE ") - 1) || + !strncmp("/*!50717 DEALLOCATE ", query_no_space, sizeof("/*!50717 DEALLOCATE ") - 1) || + !strncmp("/*!50112 SET ", query_no_space, sizeof("/*!50112 SET ") - 1) || + !strncmp("/*!50112 PREPARE ", query_no_space, sizeof("/*!50112 PREPARE ") - 1) || + !strncmp("/*!50112 EXECUTE ", query_no_space, sizeof("/*!50112 EXECUTE ") - 1) || + !strncmp("/*!50112 DEALLOCATE ", query_no_space, sizeof("/*!50112 DEALLOCATE ") - 1) || + !strncmp("/*!40000 ALTER TABLE", query_no_space, sizeof("/*!40000 ALTER TABLE") - 1) || - !strncmp("/*!40100 SET @@SQL_MODE='' */", query_no_space, strlen("/*!40100 SET @@SQL_MODE='' */")) + !strncmp("/*!40100 SET @@SQL_MODE='' */", query_no_space, sizeof("/*!40100 SET @@SQL_MODE='' */") - 1) || - !strncmp("/*!40103 SET TIME_ZONE=", query_no_space, strlen("/*!40103 SET TIME_ZONE=")) + !strncmp("/*!40103 SET TIME_ZONE=", query_no_space, sizeof("/*!40103 SET TIME_ZONE=") - 1) || - !strncmp("LOCK TABLES", query_no_space, strlen("LOCK TABLES")) + !strncmp("LOCK TABLES", query_no_space, sizeof("LOCK TABLES") - 1) || - !strncmp("UNLOCK TABLES", query_no_space, strlen("UNLOCK TABLES")) + !strncmp("UNLOCK TABLES", query_no_space, sizeof("UNLOCK TABLES") - 1) || - !strncmp("SET SQL_QUOTE_SHOW_CREATE=1", query_no_space, strlen("SET SQL_QUOTE_SHOW_CREATE=1")) + !strncmp("SET SQL_QUOTE_SHOW_CREATE=1", query_no_space, sizeof("SET SQL_QUOTE_SHOW_CREATE=1") - 1) || - !strncmp("SET SESSION character_set_results", query_no_space, strlen("SET SESSION character_set_results")) + !strncmp("SET SESSION character_set_results", query_no_space, sizeof("SET SESSION character_set_results") - 1) || - !strncasecmp("FLUSH /*!40101 LOCAL */ TABLES", query_no_space, strlen("FLUSH /*!40101 LOCAL */ TABLES")) + !strncasecmp("FLUSH /*!40101 LOCAL */ TABLES", query_no_space, sizeof("FLUSH /*!40101 LOCAL */ TABLES") - 1) || - !strncasecmp("FLUSH /*!40101 LOCAL */ LOGS", query_no_space, strlen("FLUSH /*!40101 LOCAL */ LOGS")) + !strncasecmp("FLUSH /*!40101 LOCAL */ LOGS", query_no_space, sizeof("FLUSH /*!40101 LOCAL */ LOGS") - 1) || - !strncasecmp("FLUSH TABLES WITH READ LOCK", query_no_space, strlen("FLUSH TABLES WITH READ LOCK")) + !strncasecmp("FLUSH TABLES WITH READ LOCK", query_no_space, sizeof("FLUSH TABLES WITH READ LOCK") - 1) || - !strncasecmp("USE ", query_no_space, strlen("USE ")) // this applies to all clients, not only mysqldump + !strncasecmp("USE ", query_no_space, sizeof("USE ") - 1) // this applies to all clients, not only mysqldump ) { SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); run_query=false; goto __run_query; } - if (query_no_space_length == strlen("SHOW MASTER STATUS") && !strncasecmp("SHOW MASTER STATUS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW MASTER STATUS") - 1 && !strncasecmp("SHOW MASTER STATUS", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'File', 0 AS 'Position', '' AS 'Binlog_Do_DB', '' AS 'Binlog_Ignore_DB', '' AS 'Executed_Gtid_Set' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length == strlen("SHOW BINARY LOG STATUS") && !strncasecmp("SHOW BINARY LOG STATUS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW BINARY LOG STATUS") - 1 && !strncasecmp("SHOW BINARY LOG STATUS", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'File', 0 AS 'Position', '' AS 'Binlog_Do_DB', '' AS 'Binlog_Ignore_DB', '' AS 'Executed_Gtid_Set' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length >= strlen("SHOW FUNCTION STATUS") && !strncasecmp("SHOW FUNCTION STATUS", query_no_space, strlen("SHOW FUNCTION STATUS"))) { + if (query_no_space_length >= sizeof("SHOW FUNCTION STATUS") - 1 && !strncasecmp("SHOW FUNCTION STATUS", query_no_space, sizeof("SHOW FUNCTION STATUS") - 1)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'Db', '' AS 'Name', '' AS 'Type', '' AS 'Definer', '' AS 'Modified', '' AS 'Created', '' AS 'Security_type', '' AS 'Comment', '' AS 'character_set_client', '' AS 'collation_connection', '' AS 'Database Collation' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length >= strlen("SHOW PROCEDURE STATUS") && !strncasecmp("SHOW PROCEDURE STATUS", query_no_space, strlen("SHOW PROCEDURE STATUS"))) { + if (query_no_space_length >= sizeof("SHOW PROCEDURE STATUS") - 1 && !strncasecmp("SHOW PROCEDURE STATUS", query_no_space, sizeof("SHOW PROCEDURE STATUS") - 1)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'Db', '' AS 'Name', '' AS 'Type', '' AS 'Definer', '' AS 'Modified', '' AS 'Created', '' AS 'Security_type', '' AS 'Comment', '' AS 'character_set_client', '' AS 'collation_connection', '' AS 'Database Collation' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length >= strlen("SHOW TRIGGERS") && !strncasecmp("SHOW TRIGGERS", query_no_space, strlen("SHOW TRIGGERS"))) { + if (query_no_space_length >= sizeof("SHOW TRIGGERS") - 1 && !strncasecmp("SHOW TRIGGERS", query_no_space, sizeof("SHOW TRIGGERS") - 1)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'Trigger', '' AS 'Event', '' AS 'Table', '' AS 'Statement', '' AS 'Timing', '' AS 'Created', '' AS 'sql_mode', '' AS 'Definer', '' AS 'character_set_client', '' AS 'collation_connection', '' AS 'Database Collation' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length >= strlen("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS") && !strncasecmp("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS", query_no_space, strlen("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS"))) { + if (query_no_space_length >= sizeof("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS") - 1 && !strncasecmp("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS", query_no_space, sizeof("SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS") - 1)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'TRIGGER_NAME' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length >= strlen("SHOW EVENTS") && !strncasecmp("SHOW EVENTS", query_no_space, strlen("SHOW EVENTS"))) { + if (query_no_space_length >= sizeof("SHOW EVENTS") - 1 && !strncasecmp("SHOW EVENTS", query_no_space, sizeof("SHOW EVENTS") - 1)) { l_free(query_length, query); query = l_strdup("SELECT '' AS 'Db', '' AS 'Name', '' AS 'Definer', '' AS 'Time zone', '' AS 'Type', '' AS 'Execute at', '' AS 'Interval value', '' AS 'Interval field', '' AS 'Starts', '' AS 'Ends', '' AS 'Status', '' AS 'Originator', '' AS 'character_set_client', '' AS 'collation_connection', '' AS 'Database Collation' WHERE 1=0"); query_length = strlen(query) + 1; goto __run_query; } - if (!strncmp("SHOW STATUS LIKE 'binlog_snapshot_gtid_executed'", query_no_space, strlen("SHOW STATUS LIKE 'binlog_snapshot_gtid_executed'"))) { + if (!strncmp("SHOW STATUS LIKE 'binlog_snapshot_gtid_executed'", query_no_space, sizeof("SHOW STATUS LIKE 'binlog_snapshot_gtid_executed'") - 1)) { l_free(query_length, query); query = l_strdup("SELECT variable_name AS Variable_name, Variable_value AS Value FROM global_variables WHERE 1=0"); query_length = strlen(query)+1; goto __run_query; } - if (!strncmp("SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$.\"number-of-buckets-specified\"') FROM information_schema.COLUMN_STATISTICS", query_no_space, strlen("SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$.\"number-of-buckets-specified\"') FROM information_schema.COLUMN_STATISTICS"))) { + constexpr size_t select_column_statistics_len = + sizeof("SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$.\"number-of-buckets-specified\"') FROM information_schema.COLUMN_STATISTICS") - 1; + if ( + !strncmp( + "SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$.\"number-of-buckets-specified\"') FROM information_schema.COLUMN_STATISTICS", + query_no_space, + select_column_statistics_len) + ) { l_free(query_length, query); query = l_strdup("SELECT variable_name AS COLUMN_NAME, Variable_value AS 'JSON_EXTRACT(HISTOGRAM, ''$.\"number-of-buckets-specified\"'')' FROM global_variables WHERE 1=0"); query_length = strlen(query)+1; goto __run_query; } - if (!strncmp("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'session_variables'", query_no_space, strlen("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'session_variables'"))) { + if (!strncmp("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'session_variables'", query_no_space, sizeof("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'session_variables'") - 1)) { l_free(query_length,query); query=l_strdup("SELECT 0 as 'COUNT(*)'"); query_length=strlen(query)+1; goto __run_query; } - if (!strncmp("SHOW VARIABLES LIKE 'gtid\\_mode'", query_no_space, strlen("SHOW VARIABLES LIKE 'gtid\\_mode'"))) { + if (!strncmp("SHOW VARIABLES LIKE 'gtid\\_mode'", query_no_space, sizeof("SHOW VARIABLES LIKE 'gtid\\_mode'") - 1)) { l_free(query_length,query); query=l_strdup("SELECT variable_name Variable_name, Variable_value Value FROM global_variables WHERE Variable_name='gtid_mode'"); query_length=strlen(query)+1; goto __run_query; } - if (!strncmp("select @@collation_database", query_no_space, strlen("select @@collation_database"))) { + if (!strncmp("select @@collation_database", query_no_space, sizeof("select @@collation_database") - 1)) { l_free(query_length,query); query=l_strdup("SELECT Collation '@@collation_database' FROM mysql_collations WHERE Collation='utf8_general_ci' LIMIT 1"); query_length=strlen(query)+1; goto __run_query; } - if (!strncmp("SHOW VARIABLES LIKE 'ndbinfo\\_version'", query_no_space, strlen("SHOW VARIABLES LIKE 'ndbinfo\\_version'"))) { + if (!strncmp("SHOW VARIABLES LIKE 'ndbinfo\\_version'", query_no_space, sizeof("SHOW VARIABLES LIKE 'ndbinfo\\_version'") - 1)) { l_free(query_length,query); query=l_strdup("SELECT variable_name Variable_name, Variable_value Value FROM global_variables WHERE Variable_name='ndbinfo_version'"); query_length=strlen(query)+1; goto __run_query; } - if (!strncasecmp("show table status like '", query_no_space, strlen("show table status like '"))) { + if (!strncasecmp("show table status like '", query_no_space, sizeof("show table status like '") - 1)) { char *strA=query_no_space+24; int strAl=strlen(strA); if (strAl<2) { // error @@ -4002,7 +4033,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { run_query=false; goto __run_query; } - if (!strncasecmp("show fields from ", query_no_space, strlen("show fields from "))) { + if (!strncasecmp("show fields from ", query_no_space, sizeof("show fields from ") - 1)) { char *strA=query_no_space+17; int strAl=strlen(strA); if (strAl==0) { // error @@ -4026,7 +4057,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } // FIXME: this should be removed, it is just a POC for issue #253 . What is important is the call to GloMTH->signal_all_threads(); - if (!strncasecmp("SIGNAL MYSQL THREADS", query_no_space, strlen("SIGNAL MYSQL THREADS"))) { + if (!strncasecmp("SIGNAL MYSQL THREADS", query_no_space, sizeof("SIGNAL MYSQL THREADS") - 1)) { GloMTH->signal_all_threads(); proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; @@ -4051,7 +4082,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { const char *mb = skip_leading_sql_comments(query_no_space, query_no_space_length); // fix bug #442 - if (!strncmp("SET SQL_SAFE_UPDATES=1", mb, strlen("SET SQL_SAFE_UPDATES=1"))) { + if (!strncmp("SET SQL_SAFE_UPDATES=1", mb, sizeof("SET SQL_SAFE_UPDATES=1") - 1)) { SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); run_query=false; goto __run_query; @@ -4059,25 +4090,25 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { // fix bug #1047 if ( - (!strncasecmp("BEGIN", mb, strlen("BEGIN"))) + (!strncasecmp("BEGIN", mb, sizeof("BEGIN") - 1)) || - (!strncasecmp("START TRANSACTION", mb, strlen("START TRANSACTION"))) + (!strncasecmp("START TRANSACTION", mb, sizeof("START TRANSACTION") - 1)) || - (!strncasecmp("COMMIT", mb, strlen("COMMIT"))) + (!strncasecmp("COMMIT", mb, sizeof("COMMIT") - 1)) || - (!strncasecmp("ROLLBACK", mb, strlen("ROLLBACK"))) + (!strncasecmp("ROLLBACK", mb, sizeof("ROLLBACK") - 1)) || - (!strncasecmp("SET character_set_results", mb, strlen("SET character_set_results"))) + (!strncasecmp("SET character_set_results", mb, sizeof("SET character_set_results") - 1)) || - (!strncasecmp("SET SQL_AUTO_IS_NULL", mb, strlen("SET SQL_AUTO_IS_NULL"))) + (!strncasecmp("SET SQL_AUTO_IS_NULL", mb, sizeof("SET SQL_AUTO_IS_NULL") - 1)) || - (!strncasecmp("SET NAMES", mb, strlen("SET NAMES"))) + (!strncasecmp("SET NAMES", mb, sizeof("SET NAMES") - 1)) || - (!strncasecmp("SET AUTOCOMMIT", mb, strlen("SET AUTOCOMMIT"))) + (!strncasecmp("SET AUTOCOMMIT", mb, sizeof("SET AUTOCOMMIT") - 1)) || - (!strncasecmp("SET @@session.autocommit", mb, strlen("SET @@session.autocommit"))) + (!strncasecmp("SET @@session.autocommit", mb, sizeof("SET @@session.autocommit") - 1)) || - (!strncasecmp("SET LOCK_WAIT_TIMEOUT", mb, strlen("SET LOCK_WAIT_TIMEOUT"))) + (!strncasecmp("SET LOCK_WAIT_TIMEOUT", mb, sizeof("SET LOCK_WAIT_TIMEOUT") - 1)) ) { SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space); run_query=false; @@ -4086,7 +4117,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } // MySQL client check command for dollars quote support, starting at version '8.1.0'. See #4300. - if (!strncasecmp("SELECT $$", query_no_space, strlen("SELECT $$"))) { + if (!strncasecmp("SELECT $$", query_no_space, sizeof("SELECT $$") - 1)) { pair err_info { get_dollar_quote_error(mysql_thread___server_version) }; SPA->send_error_msg_to_client(sess, const_cast(err_info.second), err_info.first); run_query=false; @@ -4102,7 +4133,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp("select concat(@@version, ' ', @@version_comment)", query_no_space, strlen("select concat(@@version, ' ', @@version_comment)"))) { + if (!strncasecmp("select concat(@@version, ' ', @@version_comment)", query_no_space, sizeof("select concat(@@version, ' ', @@version_comment)") - 1)) { l_free(query_length,query); char *q = const_cast("SELECT '%s Admin Module'"); query_length = strlen(q) + strlen(PROXYSQL_VERSION) + 1; @@ -4138,7 +4169,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("select @@sql_mode", query_no_space, strlen("select @@sql_mode"))) { + if (!strncasecmp("select @@sql_mode", query_no_space, sizeof("select @@sql_mode") - 1)) { l_free(query_length,query); char *q = const_cast("SELECT \"\" as \"@@sql_mode\""); query_length = strlen(q) + strlen(PROXYSQL_VERSION) + 1; @@ -4148,7 +4179,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } // trivial implementation for 'connection_id()' to support 'mycli'. See #3247 - if (!strncasecmp("select connection_id()", query_no_space, strlen("select connection_id()"))) { + if (!strncasecmp("select connection_id()", query_no_space, sizeof("select connection_id()") - 1)) { l_free(query_length,query); // 'connection_id()' is always forced to be '0' query=l_strdup("SELECT 0 AS 'CONNECTION_ID()'"); @@ -4157,7 +4188,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } // implementation for 'SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP())' in order to support'csharp' connector. See #2543 - if (!strncasecmp("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP())", query_no_space, strlen("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP())"))) { + if (!strncasecmp("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP())", query_no_space, sizeof("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP())") - 1)) { l_free(query_length,query); char *query1=(char*)"SELECT '%s' as 'TIMEDIFF(NOW(), UTC_TIMESTAMP()'"; @@ -4183,7 +4214,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { !strncasecmp( "select @@max_allowed_packet, @@character_set_client, @@character_set_connection, @@license, @@sql_mode, @@lower_case_table_names", query_no_space, - strlen("select @@max_allowed_packet, @@character_set_client, @@character_set_connection, @@license, @@sql_mode, @@lower_case_table_names") + sizeof("select @@max_allowed_packet, @@character_set_client, @@character_set_connection, @@license, @@sql_mode, @@lower_case_table_names") - 1 ) ) { l_free(query_length,query); @@ -4219,13 +4250,13 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (!strncasecmp("SELECT @@version", query_no_space, strlen("SELECT @@version"))) { + if (!strncasecmp("SELECT @@version", query_no_space, sizeof("SELECT @@version") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT '%s' AS '@@version'"; if (GloMyLdapAuth == nullptr) { query_length=strlen(q)+20+strlen(PROXYSQL_VERSION); } else { - query_length=strlen(q)+20+strlen(PROXYSQL_VERSION)+strlen("-Enterprise"); + query_length=strlen(q)+20+strlen(PROXYSQL_VERSION)+sizeof("-Enterprise") - 1; } query=(char *)l_alloc(query_length); if (GloMyLdapAuth == nullptr) { @@ -4236,13 +4267,13 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("SELECT version()", query_no_space, strlen("SELECT version()"))) { + if (!strncasecmp("SELECT version()", query_no_space, sizeof("SELECT version()") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT '%s' AS 'version()'"; if (GloMyLdapAuth == nullptr) { query_length=strlen(q)+20+strlen(PROXYSQL_VERSION); } else { - query_length=strlen(q)+20+strlen(PROXYSQL_VERSION)+strlen("-Enterprise"); + query_length=strlen(q)+20+strlen(PROXYSQL_VERSION)+sizeof("-Enterprise") - 1; } query=(char *)l_alloc(query_length); if (GloMyLdapAuth == nullptr) { @@ -4253,9 +4284,9 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in", query_no_space, strlen("SHOW VARIABLES WHERE Variable_name in"))) { + if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in", query_no_space, sizeof("SHOW VARIABLES WHERE Variable_name in") - 1)) { // Allow MariaDB ConnectorJ to connect to Admin #743 - if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','sql_mode')", query_no_space, strlen("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','sql_mode')"))) { + if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','sql_mode')", query_no_space, sizeof("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','sql_mode')") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT 'max_allowed_packet' Variable_name,'4194304' Value UNION ALL SELECT 'sql_mode', 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION' UNION ALL SELECT 'system_time_zone', 'UTC' UNION ALL SELECT 'time_zone','SYSTEM'"; query_length=strlen(q)+20; @@ -4264,7 +4295,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } // Allow MariaDB ConnectorJ 2.4.1 to connect to Admin #2009 - if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','auto_increment_increment')", query_no_space, strlen("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','auto_increment_increment')"))) { + if (!strncasecmp("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','auto_increment_increment')", query_no_space, sizeof("SHOW VARIABLES WHERE Variable_name in ('max_allowed_packet','system_time_zone','time_zone','auto_increment_increment')") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT 'max_allowed_packet' Variable_name,'4194304' Value UNION ALL SELECT 'auto_increment_increment', '1' UNION ALL SELECT 'system_time_zone', 'UTC' UNION ALL SELECT 'time_zone','SYSTEM'"; query_length=strlen(q)+20; @@ -4366,154 +4397,154 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { char *error=NULL; int affected_rows=0; int cols=0; - if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL SERVERS") && !strncasecmp("CHECKSUM DISK MYSQL SERVERS", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MYSQL SERVERS") - 1 && !strncasecmp("CHECKSUM DISK MYSQL SERVERS", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM mysql_servers ORDER BY hostgroup_id, hostname, port"; tablename=(char *)"MYSQL SERVERS"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL USERS") && !strncasecmp("CHECKSUM DISK MYSQL USERS", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MYSQL USERS") - 1 && !strncasecmp("CHECKSUM DISK MYSQL USERS", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM mysql_users ORDER BY username"; tablename=(char *)"MYSQL USERS"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL QUERY RULES") && !strncasecmp("CHECKSUM DISK MYSQL QUERY RULES", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MYSQL QUERY RULES") - 1 && !strncasecmp("CHECKSUM DISK MYSQL QUERY RULES", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM mysql_query_rules ORDER BY rule_id"; tablename=(char *)"MYSQL QUERY RULES"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL VARIABLES") && !strncasecmp("CHECKSUM DISK MYSQL VARIABLES", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MYSQL VARIABLES") - 1 && !strncasecmp("CHECKSUM DISK MYSQL VARIABLES", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-%' ORDER BY variable_name"; tablename=(char *)"MYSQL VARIABLES"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM mysql_replication_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL REPLICATION HOSTGROUPS"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL SERVERS") && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL SERVERS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL SERVERS") && !strncasecmp("CHECKSUM MEM MYSQL SERVERS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL SERVERS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL SERVERS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL SERVERS") && !strncasecmp("CHECKSUM MYSQL SERVERS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL SERVERS") - 1 && !strncasecmp("CHECKSUM MYSQL SERVERS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_servers ORDER BY hostgroup_id, hostname, port"; tablename=(char *)"MYSQL SERVERS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL USERS") && !strncasecmp("CHECKSUM MEMORY MYSQL USERS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL USERS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL USERS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL USERS") && !strncasecmp("CHECKSUM MEM MYSQL USERS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL USERS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL USERS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL USERS") && !strncasecmp("CHECKSUM MYSQL USERS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL USERS") - 1 && !strncasecmp("CHECKSUM MYSQL USERS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_users ORDER BY username"; tablename=(char *)"MYSQL USERS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MEMORY MYSQL QUERY RULES", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL QUERY RULES") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL QUERY RULES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MEM MYSQL QUERY RULES", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL QUERY RULES") - 1 && !strncasecmp("CHECKSUM MEM MYSQL QUERY RULES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MYSQL QUERY RULES", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL QUERY RULES") - 1 && !strncasecmp("CHECKSUM MYSQL QUERY RULES", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_query_rules ORDER BY rule_id"; tablename=(char *)"MYSQL QUERY RULES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL VARIABLES") && !strncasecmp("CHECKSUM MEMORY MYSQL VARIABLES", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL VARIABLES") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL VARIABLES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL VARIABLES") && !strncasecmp("CHECKSUM MEM MYSQL VARIABLES", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL VARIABLES") - 1 && !strncasecmp("CHECKSUM MEM MYSQL VARIABLES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL VARIABLES") && !strncasecmp("CHECKSUM MYSQL VARIABLES", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL VARIABLES") - 1 && !strncasecmp("CHECKSUM MYSQL VARIABLES", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-%' ORDER BY variable_name"; tablename=(char *)"MYSQL VARIABLES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MYSQL REPLICATION HOSTGROUPS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_replication_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL REPLICATION HOSTGROUPS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL GROUP REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL GROUP REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL GROUP REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL GROUP REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL GROUP REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL GROUP REPLICATION HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MYSQL GROUP REPLICATION HOSTGROUPS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_group_replication_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL GROUP REPLICATION HOSTGROUPS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL GALERA HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL GALERA HOSTGROUPS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL GALERA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL GALERA HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL GALERA HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL GALERA HOSTGROUPS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL GALERA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL GALERA HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL GALERA HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL GALERA HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL GALERA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MYSQL GALERA HOSTGROUPS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_galera_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL GALERA HOSTGROUPS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL AURORA HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL AURORA HOSTGROUPS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL AURORA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL AURORA HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL AURORA HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL AURORA HOSTGROUPS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL AURORA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL AURORA HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL AURORA HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL AURORA HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL AURORA HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MYSQL AURORA HOSTGROUPS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_aws_aurora_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL AURORA HOSTGROUPS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL RDS BGD HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL RDS BGD HOSTGROUPS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL RDS BGD HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL RDS BGD HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL RDS BGD HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL RDS BGD HOSTGROUPS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL RDS BGD HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL RDS BGD HOSTGROUPS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL RDS BGD HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL RDS BGD HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL RDS BGD HOSTGROUPS") - 1 && !strncasecmp("CHECKSUM MYSQL RDS BGD HOSTGROUPS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_aws_rds_bgd_hostgroups ORDER BY writer_hostgroup"; tablename=(char *)"MYSQL RDS BGD HOSTGROUPS"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL HOSTGROUP ATTRIBUTES") && !strncasecmp("CHECKSUM MEMORY MYSQL HOSTGROUP ATTRIBUTES", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL HOSTGROUP ATTRIBUTES") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL HOSTGROUP ATTRIBUTES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL HOSTGROUP ATTRIBUTES") && !strncasecmp("CHECKSUM MEM MYSQL HOSTGROUP ATTRIBUTES", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL HOSTGROUP ATTRIBUTES") - 1 && !strncasecmp("CHECKSUM MEM MYSQL HOSTGROUP ATTRIBUTES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL HOSTGROUP ATTRIBUTES") && !strncasecmp("CHECKSUM MYSQL HOSTGROUP ATTRIBUTES", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL HOSTGROUP ATTRIBUTES") - 1 && !strncasecmp("CHECKSUM MYSQL HOSTGROUP ATTRIBUTES", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_hostgroup_attributes ORDER BY hostgroup_id"; tablename=(char *)"MYSQL HOSTGROUP ATTRIBUTES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS") - 1 && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MEM MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MYSQL SERVERS SSL PARAMS") - 1 && !strncasecmp("CHECKSUM MEM MYSQL SERVERS SSL PARAMS", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MYSQL SERVERS SSL PARAMS") - 1 && !strncasecmp("CHECKSUM MYSQL SERVERS SSL PARAMS", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM mysql_servers_ssl_params ORDER BY hostname, port, username"; tablename=(char *)"MYSQL HOSTGROUP ATTRIBUTES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } // MCP (Model Context Protocol) VARIABLES CHECKSUM - if (strlen(query_no_space)==strlen("CHECKSUM DISK MCP VARIABLES") && !strncasecmp("CHECKSUM DISK MCP VARIABLES", query_no_space, strlen(query_no_space))){ + if (query_no_space_length==sizeof("CHECKSUM DISK MCP VARIABLES") - 1 && !strncasecmp("CHECKSUM DISK MCP VARIABLES", query_no_space, query_no_space_length)){ char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mcp-%' ORDER BY variable_name"; tablename=(char *)"MCP VARIABLES"; SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } - if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MCP VARIABLES") && !strncasecmp("CHECKSUM MEMORY MCP VARIABLES", query_no_space, strlen(query_no_space))) + if ((query_no_space_length==sizeof("CHECKSUM MEMORY MCP VARIABLES") - 1 && !strncasecmp("CHECKSUM MEMORY MCP VARIABLES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MEM MCP VARIABLES") && !strncasecmp("CHECKSUM MEM MCP VARIABLES", query_no_space, strlen(query_no_space))) + (query_no_space_length==sizeof("CHECKSUM MEM MCP VARIABLES") - 1 && !strncasecmp("CHECKSUM MEM MCP VARIABLES", query_no_space, query_no_space_length)) || - (strlen(query_no_space)==strlen("CHECKSUM MCP VARIABLES") && !strncasecmp("CHECKSUM MCP VARIABLES", query_no_space, strlen(query_no_space)))){ + (query_no_space_length==sizeof("CHECKSUM MCP VARIABLES") - 1 && !strncasecmp("CHECKSUM MCP VARIABLES", query_no_space, query_no_space_length))){ char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mcp-%' ORDER BY variable_name"; tablename=(char *)"MCP VARIABLES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); @@ -4538,8 +4569,8 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("SELECT CONFIG INTO OUTFILE", query_no_space, strlen("SELECT CONFIG INTO OUTFILE"))) { - std::string fileName = query_no_space + strlen("SELECT CONFIG INTO OUTFILE"); + if (!strncasecmp("SELECT CONFIG INTO OUTFILE", query_no_space, sizeof("SELECT CONFIG INTO OUTFILE") - 1)) { + std::string fileName = query_no_space + sizeof("SELECT CONFIG INTO OUTFILE") - 1; fileName.erase(0, fileName.find_first_not_of("\t\n\v\f\r ")); fileName.erase(fileName.find_last_not_of("\t\n\v\f\r ") + 1); if (fileName.size() == 0) { @@ -4593,7 +4624,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (query_no_space_length==strlen("SELECT CONFIG FILE") && !strncasecmp("SELECT CONFIG FILE", query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SELECT CONFIG FILE") - 1 && !strncasecmp("SELECT CONFIG FILE", query_no_space, query_no_space_length)) { std::string data; data.reserve(100000); data += config_header; @@ -4633,7 +4664,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { // Handle PostgreSQL meta commands expanded by psql client // These commands are intercepted and converted to appropriate SQLite queries if constexpr (std::is_same_v) { - if (query_no_space_length >= strlen("SELECT") && !strncasecmp("SELECT", query_no_space, strlen("SELECT"))) { + if (query_no_space_length >= sizeof("SELECT") - 1 && !strncasecmp("SELECT", query_no_space, sizeof("SELECT") - 1)) { // Track if this query is the FIRST describe query (sets describe_mode) // and if it matches ANY describe pattern (prevents reset during sequence) bool is_describe_query = false; @@ -4734,8 +4765,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { temp_table[len] = '\0'; char* escaped = escape_string_single_quotes(temp_table, false); - strncpy(sess->describe_table_name, escaped, sizeof(sess->describe_table_name) - 1); - sess->describe_table_name[sizeof(sess->describe_table_name) - 1] = '\0'; + snprintf(sess->describe_table_name, sizeof(sess->describe_table_name), "%s", escaped); // Only free if escape_string_single_quotes allocated new memory if (escaped != temp_table) { free(escaped); @@ -4995,7 +5025,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __end_show_commands; // in the next block there are only SHOW commands } - if (!strncasecmp("SHOW PROMETHEUS METRICS", query_no_space, strlen("SHOW PROMETHEUS METRICS"))) { + if (!strncasecmp("SHOW PROMETHEUS METRICS", query_no_space, sizeof("SHOW PROMETHEUS METRICS") - 1)) { char* pta[1]; pta[0] = NULL; SQLite3_result* resultset = new SQLite3_result(1); @@ -5016,7 +5046,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (!strncasecmp("SHOW GLOBAL VARIABLES LIKE 'version'", query_no_space, strlen("SHOW GLOBAL VARIABLES LIKE 'version'"))) { + if (!strncasecmp("SHOW GLOBAL VARIABLES LIKE 'version'", query_no_space, sizeof("SHOW GLOBAL VARIABLES LIKE 'version'") - 1)) { l_free(query_length,query); char *q=(char *)"SELECT 'version' Variable_name, '%s' Value FROM global_variables WHERE Variable_name='admin-version'"; query_length=strlen(q)+20+strlen(PROXYSQL_VERSION); @@ -5026,21 +5056,21 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } - if (query_no_space_length==strlen("SHOW TABLES") && !strncasecmp("SHOW TABLES",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW TABLES") - 1 && !strncasecmp("SHOW TABLES",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT name AS tables FROM sqlite_master WHERE type='table' AND name NOT IN ('sqlite_sequence') ORDER BY name"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW CHARSET") && !strncasecmp("SHOW CHARSET",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW CHARSET") - 1 && !strncasecmp("SHOW CHARSET",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT Charset, Collation AS 'Default collation' FROM mysql_collations WHERE `Default`='Yes'"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW COLLATION") && !strncasecmp("SHOW COLLATION",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW COLLATION") - 1 && !strncasecmp("SHOW COLLATION",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT * FROM mysql_collations"); query_length=strlen(query)+1; @@ -5104,14 +5134,14 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (query_no_space_length==strlen("SHOW MYSQL USERS") && !strncasecmp("SHOW MYSQL USERS",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW MYSQL USERS") - 1 && !strncasecmp("SHOW MYSQL USERS",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT * FROM mysql_users ORDER BY username, active DESC, username ASC"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW MYSQL SERVERS") && !strncasecmp("SHOW MYSQL SERVERS",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW MYSQL SERVERS") - 1 && !strncasecmp("SHOW MYSQL SERVERS",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT * FROM mysql_servers ORDER BY hostgroup_id, hostname, port"); query_length=strlen(query)+1; @@ -5119,11 +5149,11 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if ( - (query_no_space_length==strlen("SHOW GLOBAL VARIABLES") && !strncasecmp("SHOW GLOBAL VARIABLES",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SHOW GLOBAL VARIABLES") - 1 && !strncasecmp("SHOW GLOBAL VARIABLES",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SHOW ALL VARIABLES") && !strncasecmp("SHOW ALL VARIABLES",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SHOW ALL VARIABLES") - 1 && !strncasecmp("SHOW ALL VARIABLES",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SHOW VARIABLES") && !strncasecmp("SHOW VARIABLES",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SHOW VARIABLES") - 1 && !strncasecmp("SHOW VARIABLES",query_no_space, query_no_space_length)) ) { l_free(query_length,query); query=l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables ORDER BY variable_name"); @@ -5132,7 +5162,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if (GloMyLdapAuth) { - if (query_no_space_length==strlen("SHOW LDAP VARIABLES") && !strncasecmp("SHOW LDAP VARIABLES",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW LDAP VARIABLES") - 1 && !strncasecmp("SHOW LDAP VARIABLES",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'ldap-\%' ORDER BY variable_name"); query_length=strlen(query)+1; @@ -5140,21 +5170,21 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } } - if (query_no_space_length==strlen("SHOW ADMIN VARIABLES") && !strncasecmp("SHOW ADMIN VARIABLES",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW ADMIN VARIABLES") - 1 && !strncasecmp("SHOW ADMIN VARIABLES",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'admin-\%' ORDER BY variable_name"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW MYSQL VARIABLES") && !strncasecmp("SHOW MYSQL VARIABLES",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW MYSQL VARIABLES") - 1 && !strncasecmp("SHOW MYSQL VARIABLES",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'mysql-\%' ORDER BY variable_name"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW MYSQL STATUS") && !strncasecmp("SHOW MYSQL STATUS",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW MYSQL STATUS") - 1 && !strncasecmp("SHOW MYSQL STATUS",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT Variable_Name AS Variable_name, Variable_Value AS Value FROM stats_mysql_global ORDER BY variable_name"); query_length=strlen(query)+1; @@ -5162,7 +5192,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (query_no_space_length == strlen("SHOW PGSQL VARIABLES") && !strncasecmp("SHOW PGSQL VARIABLES", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW PGSQL VARIABLES") - 1 && !strncasecmp("SHOW PGSQL VARIABLES", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'pgsql-\%' ORDER BY variable_name"); query_length = strlen(query) + 1; @@ -5170,7 +5200,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } #ifdef PROXYSQLTSDB - if (query_no_space_length == strlen("SHOW TSDB VARIABLES") && !strncasecmp("SHOW TSDB VARIABLES", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW TSDB VARIABLES") - 1 && !strncasecmp("SHOW TSDB VARIABLES", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'tsdb-%' ORDER BY variable_name"); query_length = strlen(query) + 1; @@ -5179,7 +5209,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { #endif #ifdef PROXYSQLTSDB - if (query_no_space_length == strlen("SHOW TSDB STATUS") && !strncasecmp("SHOW TSDB STATUS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW TSDB STATUS") - 1 && !strncasecmp("SHOW TSDB STATUS", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT Variable_Name AS Variable_name, Variable_Value AS Value FROM stats_tsdb ORDER BY Variable_name"); query_length = strlen(query) + 1; @@ -5188,7 +5218,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } #endif - if (query_no_space_length == strlen("SHOW PGSQL STATUS") && !strncasecmp("SHOW PGSQL STATUS", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW PGSQL STATUS") - 1 && !strncasecmp("SHOW PGSQL STATUS", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT Variable_Name AS Variable_name, Variable_Value AS Value FROM stats_pgsql_global ORDER BY variable_name"); query_length = strlen(query) + 1; @@ -5196,7 +5226,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (query_no_space_length == strlen("SHOW MCP VARIABLES") && !strncasecmp("SHOW MCP VARIABLES", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW MCP VARIABLES") - 1 && !strncasecmp("SHOW MCP VARIABLES", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT variable_name AS Variable_name, variable_value AS Value FROM global_variables WHERE variable_name LIKE 'mcp-%' ORDER BY variable_name"); query_length = strlen(query) + 1; @@ -5210,25 +5240,33 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { strBl=strlen(strB); char *dbh=NULL; char *tbh=NULL; + bool tbh_uses_l_alloc = false; c_split_2(query_no_space+strAl,".",&dbh,&tbh); - if (strlen(tbh)==0) { + if (std::string_view(tbh).empty()) { free(tbh); tbh=dbh; dbh=strdup("main"); } - if (strlen(tbh)>=3 && tbh[0]=='`' && tbh[strlen(tbh)-1]=='`') { // tablename is quoted - char *tbh_tmp=(char *)malloc(strlen(tbh)-1); - strncpy(tbh_tmp,tbh+1,strlen(tbh)-2); - tbh_tmp[strlen(tbh)-2]=0; - free(tbh); - tbh=tbh_tmp; - } + const size_t tbh_len = std::string_view(tbh).size(); + if (tbh_len>=3 && tbh[0]=='`' && tbh[tbh_len-1]=='`') { // tablename is quoted + char *tbh_tmp=(char *)l_alloc(tbh_len-1); + size_t quoted_len = tbh_len - 2; + memcpy(tbh_tmp,tbh+1,quoted_len); + tbh_tmp[quoted_len]=0; + free(tbh); + tbh=tbh_tmp; + tbh_uses_l_alloc = true; + } int l=strBl+strlen(tbh)*3+strlen(dbh)-8; char *buff=(char *)l_alloc(l+1); snprintf(buff,l+1,strB,tbh,tbh,dbh,tbh); buff[l]=0; - free(tbh); + if (tbh_uses_l_alloc) { + l_free(tbh_len-1,tbh); + } else { + free(tbh); + } free(dbh); l_free(query_length,query); query=buff; @@ -5237,9 +5275,9 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } if ( - (query_no_space_length==strlen("SHOW DATABASES") && !strncasecmp("SHOW DATABASES",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SHOW DATABASES") - 1 && !strncasecmp("SHOW DATABASES",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SHOW SCHEMAS") && !strncasecmp("SHOW SCHEMAS",query_no_space, query_no_space_length)) + (query_no_space_length==sizeof("SHOW SCHEMAS") - 1 && !strncasecmp("SHOW SCHEMAS",query_no_space, query_no_space_length)) ) { l_free(query_length,query); query=l_strdup("PRAGMA DATABASE_LIST"); @@ -5247,42 +5285,42 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { goto __run_query; } - if (query_no_space_length==strlen("SHOW FULL PROCESSLIST") && !strncasecmp("SHOW FULL PROCESSLIST",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW FULL PROCESSLIST") - 1 && !strncasecmp("SHOW FULL PROCESSLIST",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT * FROM stats_mysql_processlist"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length==strlen("SHOW PROCESSLIST") && !strncasecmp("SHOW PROCESSLIST",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SHOW PROCESSLIST") - 1 && !strncasecmp("SHOW PROCESSLIST",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT SessionID, user, db, hostgroup, command, time_ms, info FROM stats_mysql_processlist"); query_length=strlen(query)+1; goto __run_query; } - if (query_no_space_length == strlen("SHOW FULL PGSQL PROCESSLIST") && !strncasecmp("SHOW FULL PGSQL PROCESSLIST", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW FULL PGSQL PROCESSLIST") - 1 && !strncasecmp("SHOW FULL PGSQL PROCESSLIST", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT * FROM stats_pgsql_processlist"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length == strlen("SHOW FULL PGSQL ACTIVITY") && !strncasecmp("SHOW FULL PGSQL ACTIVITY", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW FULL PGSQL ACTIVITY") - 1 && !strncasecmp("SHOW FULL PGSQL ACTIVITY", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT * FROM stats_pgsql_stat_activity"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length == strlen("SHOW PGSQL PROCESSLIST") && !strncasecmp("SHOW PGSQL PROCESSLIST", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW PGSQL PROCESSLIST") - 1 && !strncasecmp("SHOW PGSQL PROCESSLIST", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT SessionID, user, database, hostgroup, backend_pid, backend_state, command, time_ms, info FROM stats_pgsql_processlist"); query_length = strlen(query) + 1; goto __run_query; } - if (query_no_space_length == strlen("SHOW PGSQL ACTIVITY") && !strncasecmp("SHOW PGSQL ACTIVITY", query_no_space, query_no_space_length)) { + if (query_no_space_length == sizeof("SHOW PGSQL ACTIVITY") - 1 && !strncasecmp("SHOW PGSQL ACTIVITY", query_no_space, query_no_space_length)) { l_free(query_length, query); query = l_strdup("SELECT datname, pid, usename, hostgroup, backend_pid, state, command, duration_ms, query FROM stats_pgsql_stat_activity"); query_length = strlen(query) + 1; @@ -5291,7 +5329,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { __end_show_commands: - if (query_no_space_length==strlen("SELECT DATABASE()") && !strncasecmp("SELECT DATABASE()",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SELECT DATABASE()") - 1 && !strncasecmp("SELECT DATABASE()",query_no_space, query_no_space_length)) { l_free(query_length,query); if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats query=l_strdup("SELECT \"admin\" AS 'DATABASE()'"); @@ -5303,7 +5341,7 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) { } // see issue #1022 - if (query_no_space_length==strlen("SELECT DATABASE() AS name") && !strncasecmp("SELECT DATABASE() AS name",query_no_space, query_no_space_length)) { + if (query_no_space_length==sizeof("SELECT DATABASE() AS name") - 1 && !strncasecmp("SELECT DATABASE() AS name",query_no_space, query_no_space_length)) { l_free(query_length,query); if (sess->session_type == PROXYSQL_SESSION_ADMIN) { // no stats query=l_strdup("SELECT \"admin\" AS 'name'"); diff --git a/lib/ClickHouse_Server.cpp b/lib/ClickHouse_Server.cpp index b58f4fdeb3..07fa164723 100644 --- a/lib/ClickHouse_Server.cpp +++ b/lib/ClickHouse_Server.cpp @@ -506,6 +506,49 @@ class ifaces_desc { class sqlite3server_main_loop_listeners { private: + struct tokenizer_owner { + tokenizer_t value; + + explicit tokenizer_owner(char *list) { + tokenizer(&value, list, ";", TOKENIZER_NO_EMPTIES); + } + + ~tokenizer_owner() { + free_tokenizer(&value); + } + + tokenizer_owner(const tokenizer_owner&) = delete; + tokenizer_owner& operator=(const tokenizer_owner&) = delete; + tokenizer_owner(tokenizer_owner&&) = delete; + tokenizer_owner& operator=(tokenizer_owner&&) = delete; + }; + + struct interface_array_owner { + char **value; + + explicit interface_array_owner(char **value_) : value(value_) {} + + ~interface_array_owner() { + if (value) { + for (int i = 0; i < MAX_IFACES; ++i) { + l_free(0, value[i]); + } + l_free(0, value); + } + } + + interface_array_owner(const interface_array_owner&) = delete; + interface_array_owner& operator=(const interface_array_owner&) = delete; + interface_array_owner(interface_array_owner&&) = delete; + interface_array_owner& operator=(interface_array_owner&&) = delete; + + char **release() { + char **released = value; + value = nullptr; + return released; + } + }; + int version; pthread_rwlock_t rwlock; @@ -566,19 +609,32 @@ class sqlite3server_main_loop_listeners { bool update_ifaces(char *list, char ***_ifaces) { wrlock(); - int i; - char **ifaces=*_ifaces; - tokenizer_t tok; - tokenizer( &tok, list, ";", TOKENIZER_NO_EMPTIES ); - const char* token; - ifaces=reset_ifaces(ifaces); - i=0; - for ( token = tokenize( &tok ) ; token && i < MAX_IFACES ; token = tokenize( &tok ) ) { - ifaces[i]=(char *)malloc(strlen(token)+1); - strcpy(ifaces[i],token); + char **old_ifaces = *_ifaces; + char **new_ifaces = (char **)l_alloc(MAX_IFACES * sizeof(char *)); + if (new_ifaces != nullptr) { + memset(new_ifaces, 0, MAX_IFACES * sizeof(char *)); + } + interface_array_owner replacement(new_ifaces); + if (replacement.value == nullptr) { + wrunlock(); + return false; + } + + tokenizer_owner tokens(list); + int i = 0; + for (const char *token = tokenize(&tokens.value); + token && i < MAX_IFACES; + token = tokenize(&tokens.value)) { + replacement.value[i] = strdup(token); + if (replacement.value[i] == nullptr) { + wrunlock(); + return false; + } i++; } - free_tokenizer( &tok ); + + interface_array_owner previous(old_ifaces); + *_ifaces = replacement.release(); version++; wrunlock(); return true; diff --git a/lib/GTID_Server_Data.cpp b/lib/GTID_Server_Data.cpp index 55a5d2b4f5..cc71c74914 100644 --- a/lib/GTID_Server_Data.cpp +++ b/lib/GTID_Server_Data.cpp @@ -355,14 +355,21 @@ bool GTID_Server_Data::read_next_gtid() { } j++; if (j%2 == 1) { // we are reading the uuid - char *p = uuid_server; - for (unsigned int k=0; k= sizeof(uuid_server)) { + invalid_msg = true; + break; + } + uuid_server[uuid_len++] = *uuid_char; } - *p = '\0'; + if (invalid_msg) { + break; + } + uuid_server[uuid_len] = '\0'; } else { // we are reading the trxid or trxid range TrxId_Interval iv(trxid_t(0)); if (!TrxId_Interval::parse(subtoken, &iv)) { @@ -391,70 +398,79 @@ bool GTID_Server_Data::read_next_gtid() { events_read++; } } else { - strncpy(rec_msg,data+pos,l); + if (l >= (int)sizeof(rec_msg)) { + pos += l + 1; + proxy_warning("GTID: oversized message from binlog reader on port %d for server %s:%d, disconnecting\n", + port, address, mysql_port); + active = false; + return false; + } + size_t rec_msg_len = (size_t)l; + memcpy(rec_msg, data + pos, rec_msg_len); pos += l+1; - rec_msg[l] = 0; + rec_msg[rec_msg_len] = 0; + if (rec_msg[0] != 'I') { + return true; + } bool invalid_msg = false; - if (rec_msg[0]=='I') { - char *a = NULL; - int ul = 0; - switch (rec_msg[1]) { - case '1': // single trxid with UUID - a = strchr(rec_msg+3,':'); - if (a == NULL) { - invalid_msg = true; - break; - } - ul = a-rec_msg-3; - strncpy(uuid_server,rec_msg+3,ul); - uuid_server[ul] = 0; - gtid_executed.add((std::string)uuid_server, (trxid_t)atoll(a+1)); - events_read++; - break; - case '2': // single trxid, reuse last UUID - gtid_executed.add((std::string)uuid_server, (trxid_t)atoll(rec_msg+3)); - events_read++; - break; - case '3': // trxid range with UUID - a = strchr(rec_msg+3,':'); - if (a == NULL) { - invalid_msg = true; - break; - } - ul = a-rec_msg-3; - strncpy(uuid_server,rec_msg+3,ul); - uuid_server[ul] = 0; - { - TrxId_Interval iv(trxid_t(0)); - if (!TrxId_Interval::parse(a+1, &iv)) { - invalid_msg = true; - break; - } - gtid_executed.add((std::string)uuid_server, iv); - } - events_read++; - break; - case '4': // trxid range, reuse last UUID - { - TrxId_Interval iv(trxid_t(0)); - if (!TrxId_Interval::parse(rec_msg+3, &iv)) { - invalid_msg = true; - break; - } - gtid_executed.add((std::string)uuid_server, iv); - } - events_read++; - break; - default: - invalid_msg = true; - } - - if (invalid_msg) { - proxy_warning("GTID: invalid or unsupported message (%s) from binlog reader on port %d for server %s:%d, disconnecting\n", - rec_msg, port, address, mysql_port); - active = false; + auto copy_uuid = [this, &rec_msg](char *delimiter) { + const int uuid_len = delimiter - (rec_msg + 3); + if (uuid_len < 0 || (size_t)uuid_len >= sizeof(uuid_server)) { return false; } + memcpy(uuid_server, rec_msg + 3, (size_t)uuid_len); + uuid_server[uuid_len] = 0; + return true; + }; + char *a = NULL; + switch (rec_msg[1]) { + case '1': // single trxid with UUID + a = strchr(rec_msg+3,':'); + if (a == NULL || !copy_uuid(a)) { + invalid_msg = true; + break; + } + gtid_executed.add((std::string)uuid_server, (trxid_t)atoll(a+1)); + events_read++; + break; + case '2': // single trxid, reuse last UUID + gtid_executed.add((std::string)uuid_server, (trxid_t)atoll(rec_msg+3)); + events_read++; + break; + case '3': { // trxid range with UUID + a = strchr(rec_msg+3,':'); + if (a == NULL || !copy_uuid(a)) { + invalid_msg = true; + break; + } + TrxId_Interval iv(trxid_t(0)); + if (!TrxId_Interval::parse(a+1, &iv)) { + invalid_msg = true; + break; + } + gtid_executed.add((std::string)uuid_server, iv); + events_read++; + break; + } + case '4': { // trxid range, reuse last UUID + TrxId_Interval iv(trxid_t(0)); + if (!TrxId_Interval::parse(rec_msg+3, &iv)) { + invalid_msg = true; + break; + } + gtid_executed.add((std::string)uuid_server, iv); + events_read++; + break; + } + default: + invalid_msg = true; + } + + if (invalid_msg) { + proxy_warning("GTID: invalid or unsupported message (%s) from binlog reader on port %d for server %s:%d, disconnecting\n", + rec_msg, port, address, mysql_port); + active = false; + return false; } } return true; diff --git a/lib/MySQLFFTO.cpp b/lib/MySQLFFTO.cpp index 551a88e08a..923881ab92 100644 --- a/lib/MySQLFFTO.cpp +++ b/lib/MySQLFFTO.cpp @@ -16,6 +16,7 @@ #include #include #include +#include extern class MySQL_Query_Processor* GloMyQPro; extern MySQL_HostGroups_Manager* MyHGM; @@ -271,16 +272,22 @@ void MySQLFFTO::report_query_stats(const std::string& query, unsigned long long ((query.length() < QUERY_DIGEST_BUF) ? qp.buf : NULL), &opts); if (digest_text) { qp.digest_text = digest_text; - const int digest_len = strnlen(digest_text, mysql_thread___query_digests_max_digest_length); + const int digest_len = static_cast(strnlen(digest_text, mysql_thread___query_digests_max_digest_length)); qp.digest = SpookyHash::Hash64(digest_text, digest_len, 0); - char* ca = (char*)""; - if (mysql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; + char* ca = (char*)""; + if (mysql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; uint64_t hash2; SpookyHash myhash; myhash.Init(19, 3); - myhash.Update(ui->username, strlen(ui->username)); + const std::string_view username_view = ui->username ? std::string_view{ui->username} : std::string_view{}; + const size_t username_len = username_view.size(); + myhash.Update(username_view.data(), username_len); myhash.Update(&qp.digest, sizeof(qp.digest)); - myhash.Update(schemaname, strlen(schemaname)); + const std::string_view schemaname_view = schemaname ? std::string_view{schemaname} : std::string_view{}; + const size_t schemaname_len = schemaname_view.size(); + myhash.Update(schemaname_view.data(), schemaname_len); myhash.Update(&m_session->current_hostgroup, sizeof(m_session->current_hostgroup)); - myhash.Update(ca, strlen(ca)); + const std::string_view ca_view = ca ? std::string_view{ca} : std::string_view{}; + const size_t ca_len = ca_view.size(); + myhash.Update(ca_view.data(), ca_len); myhash.Final(&qp.digest_total, &hash2); GloMyQPro->update_query_digest(qp.digest_total, qp.digest, qp.digest_text, m_session->current_hostgroup, ui, duration_us, m_session->thread->curtime, ca, affected_rows, rows_sent); if (digest_text != qp.buf) free(digest_text); diff --git a/lib/MySQL_PreparedStatement.cpp b/lib/MySQL_PreparedStatement.cpp index e729ae3513..ef947863ae 100644 --- a/lib/MySQL_PreparedStatement.cpp +++ b/lib/MySQL_PreparedStatement.cpp @@ -1,5 +1,6 @@ #include "proxysql.h" #include "cpp.h" +#include #ifndef SPOOKYV2 #include "SpookyV2.h" @@ -21,41 +22,38 @@ const int PS_GLOBAL_STATUS_FIELD_NUM = 9; static uint64_t stmt_compute_hash(char *user, char *schema, char *query, unsigned int query_length) { - int l = 0; - l += strlen(user); - l += strlen(schema); + size_t user_len = user ? std::string_view(user).size() : 0; + size_t schema_len = schema ? std::string_view(schema).size() : 0; // two random seperators #define _COMPUTE_HASH_DEL1_ "-ujhtgf76y576574fhYTRDFwdt-" #define _COMPUTE_HASH_DEL2_ "-8k7jrhtrgJHRgrefgreRFewg6-" - l += strlen(_COMPUTE_HASH_DEL1_); - l += strlen(_COMPUTE_HASH_DEL2_); - l += query_length; - char *buf = (char *)malloc(l); - l = 0; + size_t delimiter1_len = strlen(_COMPUTE_HASH_DEL1_); + size_t delimiter2_len = strlen(_COMPUTE_HASH_DEL2_); + size_t hash_input_length = user_len + schema_len + delimiter1_len + delimiter2_len + query_length; + + std::string hash_input; + hash_input.reserve(hash_input_length); // write user - strcpy(buf + l, user); - l += strlen(user); + if (user) { + hash_input.append(user, user_len); + } // write delimiter1 - strcpy(buf + l, _COMPUTE_HASH_DEL1_); - l += strlen(_COMPUTE_HASH_DEL1_); + hash_input.append(_COMPUTE_HASH_DEL1_); // write schema - strcpy(buf + l, schema); - l += strlen(schema); + if (schema) { + hash_input.append(schema, schema_len); + } // write delimiter2 - strcpy(buf + l, _COMPUTE_HASH_DEL2_); - l += strlen(_COMPUTE_HASH_DEL2_); + hash_input.append(_COMPUTE_HASH_DEL2_); // write query - memcpy(buf + l, query, query_length); - l += query_length; + hash_input.append(query, query_length); - uint64_t hash = SpookyHash::Hash64(buf, l, 0); - free(buf); - return hash; + return SpookyHash::Hash64(hash_input.data(), hash_input.size(), 0); } void MySQL_STMT_Global_info::compute_hash() { diff --git a/lib/MySQL_Query_Processor.cpp b/lib/MySQL_Query_Processor.cpp index 4578f236c8..0ca334b471 100644 --- a/lib/MySQL_Query_Processor.cpp +++ b/lib/MySQL_Query_Processor.cpp @@ -566,11 +566,11 @@ enum MYSQL_COM_QUERY_command MySQL_Query_Processor::query_parser_command_type(SQ return ret; } -bool MySQL_Query_Processor::_is_valid_gtid(char* gtid, size_t gtid_len) { +bool MySQL_Query_Processor::_is_valid_gtid(const char* gtid, size_t gtid_len) { if (gtid_len < 3) { return false; } - char* sep_pos = index(gtid, ':'); + const char* sep_pos = index(gtid, ':'); if (sep_pos == NULL) { return false; } diff --git a/lib/PgSQLFFTO.cpp b/lib/PgSQLFFTO.cpp index e00603d48c..e6d3238b06 100644 --- a/lib/PgSQLFFTO.cpp +++ b/lib/PgSQLFFTO.cpp @@ -15,6 +15,7 @@ #include #include #include +#include extern class PgSQL_Query_Processor* GloPgQPro; extern PgSQL_HostGroups_Manager* PgHGM; @@ -66,6 +67,14 @@ static uint64_t extract_pg_rows_affected(const unsigned char* payload, size_t le return rows; } +static size_t bounded_cstr_len(const char* s, size_t max_len) { + if (s == nullptr || max_len == 0) { + return 0; + } + const void* null_pos = memchr(s, '\0', max_len); + return null_pos ? static_cast(null_pos) - s : max_len; +} + PgSQLFFTO::PgSQLFFTO(PgSQL_Session* session) : m_session(session), m_state(IDLE), m_query_start_time(0), m_affected_rows(0), m_rows_sent(0) { m_client_buffer.reserve(1024); @@ -209,27 +218,27 @@ void PgSQLFFTO::process_client_message(char type, const unsigned char* payload, track_query(std::string(reinterpret_cast(payload), query_len), true); } else if (type == 'P') { const char* p = reinterpret_cast(payload); - size_t name_len = strnlen(p, len); + size_t name_len = bounded_cstr_len(p, len); if (name_len >= len) return; // No null terminator std::string stmt_name(p, name_len); const char* query_ptr = p + name_len + 1; size_t rem = len - (name_len + 1); - size_t query_text_len = strnlen(query_ptr, rem); + size_t query_text_len = bounded_cstr_len(query_ptr, rem); if (query_text_len >= rem) return; m_statements[stmt_name] = std::string(query_ptr, query_text_len); } else if (type == 'B') { const char* p = reinterpret_cast(payload); - size_t portal_len = strnlen(p, len); + size_t portal_len = bounded_cstr_len(p, len); if (portal_len >= len) return; std::string portal_name(p, portal_len); const char* stmt_ptr = p + portal_len + 1; size_t rem = len - (portal_len + 1); - size_t stmt_name_len = strnlen(stmt_ptr, rem); + size_t stmt_name_len = bounded_cstr_len(stmt_ptr, rem); if (stmt_name_len >= rem) return; m_portals[portal_name] = std::string(stmt_ptr, stmt_name_len); } else if (type == 'E') { const char* p = reinterpret_cast(payload); - size_t portal_len = strnlen(p, len); + size_t portal_len = bounded_cstr_len(p, len); if (portal_len >= len) return; if (len < portal_len + 1 + 4) return; // portal name + '\0' + max-rows std::string portal_name(p, portal_len); @@ -244,7 +253,7 @@ void PgSQLFFTO::process_client_message(char type, const unsigned char* payload, if (len < 2) return; char close_type = static_cast(payload[0]); const char* name_ptr = reinterpret_cast(payload) + 1; - size_t name_len = strnlen(name_ptr, len - 1); + size_t name_len = bounded_cstr_len(name_ptr, len - 1); if (name_len >= len - 1) return; std::string name(name_ptr, name_len); if (close_type == 'S') m_statements.erase(name); @@ -346,16 +355,22 @@ void PgSQLFFTO::report_query_stats(const std::string& query, unsigned long long ((query.length() < QUERY_DIGEST_BUF) ? qp.buf : NULL), &opts); if (digest_text) { qp.digest_text = digest_text; - const int digest_len = strnlen(digest_text, pgsql_thread___query_digests_max_digest_length); + const int digest_len = static_cast(strnlen(digest_text, pgsql_thread___query_digests_max_digest_length)); qp.digest = SpookyHash::Hash64(digest_text, digest_len, 0); char* ca = (char*)""; if (pgsql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; uint64_t hash2; SpookyHash myhash; myhash.Init(19, 3); - myhash.Update(ui->username, strlen(ui->username)); + const std::string_view username_view = ui->username ? std::string_view{ui->username} : std::string_view{}; + const size_t username_len = username_view.size(); + myhash.Update(username_view.data(), username_len); myhash.Update(&qp.digest, sizeof(qp.digest)); - myhash.Update(schemaname, strlen(schemaname)); + const std::string_view schemaname_view = schemaname ? std::string_view{schemaname} : std::string_view{}; + const size_t schemaname_len = schemaname_view.size(); + myhash.Update(schemaname_view.data(), schemaname_len); myhash.Update(&m_session->current_hostgroup, sizeof(m_session->current_hostgroup)); - myhash.Update(ca, strlen(ca)); + const std::string_view ca_view = ca ? std::string_view{ca} : std::string_view{}; + const size_t ca_len = ca_view.size(); + myhash.Update(ca_view.data(), ca_len); myhash.Final(&qp.digest_total, &hash2); GloPgQPro->update_query_digest(qp.digest_total, qp.digest, qp.digest_text, m_session->current_hostgroup, ui, duration_us, m_session->thread->curtime, ca, affected_rows, rows_sent); if (digest_text != qp.buf) free(digest_text); diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index e30fd15f74..8a1d617741 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -47,38 +48,31 @@ PgSQL_Connection_userinfo::~PgSQL_Connection_userinfo() { } uint64_t PgSQL_Connection_userinfo::compute_hash() { - int l=0; - if (username) - l+=strlen(username); - if (password) - l+=strlen(password); - if (dbname) - l+=strlen(dbname); + size_t username_len = username ? std::string_view(username).size() : 0; + size_t password_len = password ? std::string_view(password).size() : 0; + size_t dbname_len = dbname ? std::string_view(dbname).size() : 0; + size_t l = username_len + password_len + dbname_len; // two random seperator -#define _COMPUTE_HASH_DEL1_ "-ujhtgf76y576574fhYTRDF345wdt-" -#define _COMPUTE_HASH_DEL2_ "-8k7jrhtrgJHRgrefgreyhtRFewg6-" - l+=strlen(_COMPUTE_HASH_DEL1_); - l+=strlen(_COMPUTE_HASH_DEL2_); - char *buf=(char *)malloc(l+1); - l=0; + constexpr char delimiter1[] = "-ujhtgf76y576574fhYTRDF345wdt-"; + constexpr char delimiter2[] = "-8k7jrhtrgJHRgrefgreyhtRFewg6-"; + size_t delimiter1_len = sizeof(delimiter1) - 1; + size_t delimiter2_len = sizeof(delimiter2) - 1; + l += delimiter1_len + delimiter2_len; + + std::string hash_input; + hash_input.reserve(l); if (username) { - strcpy(buf+l,username); - l+=strlen(username); + hash_input.append(username, username_len); } - strcpy(buf+l,_COMPUTE_HASH_DEL1_); - l+=strlen(_COMPUTE_HASH_DEL1_); + hash_input.append(delimiter1); if (password) { - strcpy(buf+l,password); - l+=strlen(password); + hash_input.append(password, password_len); } if (dbname) { - strcpy(buf+l, dbname); - l+=strlen(dbname); + hash_input.append(dbname, dbname_len); } - strcpy(buf+l,_COMPUTE_HASH_DEL2_); - l+=strlen(_COMPUTE_HASH_DEL2_); - hash=SpookyHash::Hash64(buf,l,0); - free(buf); + hash_input.append(delimiter2); + hash = SpookyHash::Hash64(hash_input.data(), hash_input.size(), 0); return hash; } diff --git a/lib/PgSQL_Error_Helper.cpp b/lib/PgSQL_Error_Helper.cpp index 7b172ebf3c..06361bcbe6 100644 --- a/lib/PgSQL_Error_Helper.cpp +++ b/lib/PgSQL_Error_Helper.cpp @@ -281,8 +281,9 @@ void PgSQL_ErrorInfo_Ext::reset() { } void PgSQL_Error_Helper::fill_error_info(PgSQL_ErrorInfo& err_info, const char* code, const char* msg, const char* severity) { - strncpy(err_info.sqlstate, code, 5); - err_info.sqlstate[5] = '\0'; + size_t sqlstate_len = strnlen(code, 5); + memcpy(err_info.sqlstate, code, sqlstate_len); + err_info.sqlstate[sqlstate_len] = '\0'; err_info.severity = PgSQL_Error_Helper::identify_error_severity(severity); err_info.code = PgSQL_Error_Helper::identify_error_code(code); err_info.type = PgSQL_Error_Helper::identify_error_class(code); diff --git a/lib/PgSQL_HostGroups_Manager.cpp b/lib/PgSQL_HostGroups_Manager.cpp index 0e90a13c42..42c71f6485 100644 --- a/lib/PgSQL_HostGroups_Manager.cpp +++ b/lib/PgSQL_HostGroups_Manager.cpp @@ -129,8 +129,9 @@ PgSQL_Errors_stats::PgSQL_Errors_stats(int _hostgroup, const char* _hostname, in dbname = strdup((char*)""); } if (_sqlstate) { - strncpy(sqlstate, _sqlstate, 5); - sqlstate[5] = '\0'; + size_t sqlstate_len = strnlen(_sqlstate, 5); + memcpy(sqlstate, _sqlstate, sqlstate_len); + sqlstate[sqlstate_len] = '\0'; } else { sqlstate[0] = '\0'; } diff --git a/lib/PgSQL_Protocol.cpp b/lib/PgSQL_Protocol.cpp index 0c6c50f24c..5142c095ee 100644 --- a/lib/PgSQL_Protocol.cpp +++ b/lib/PgSQL_Protocol.cpp @@ -1,6 +1,8 @@ #include #include +#include +#include #include "proxysql.h" #include "cpp.h" #include "PgSQL_Authentication.h" @@ -22,6 +24,31 @@ extern PgSQL_Authentication* GloPgAuth; #define TEXTOID 25 #define NUMERICOID 1700 +static char *encode_bytea(const uint8_t *data, int length) { + if (length < 0 || (data == nullptr && length != 0)) { + return nullptr; + } + + const size_t byte_len = static_cast(length); + const size_t max_byte_len = (std::numeric_limits::max() - 3) / 2; + if (byte_len > max_byte_len) { + return nullptr; + } + + const size_t required = 2 + byte_len * 2 + 1; + char *encoded = (char *)l_alloc(required); + if (encoded == nullptr) { + return nullptr; + } + encoded[0] = '\\'; + encoded[1] = 'x'; + encoded[2] = '\0'; + for (size_t i = 0; i < byte_len; ++i) { + snprintf(encoded + 2 + i * 2, 3, "%02x", data[i]); + } + return encoded; +} + void PG_pkt::make_space(unsigned int len) { if (ownership == false) return; @@ -200,20 +227,11 @@ void PG_pkt::write_RowDescription(const char *tupdesc, ...) { void SQLite3_to_Postgres(PtrSizeArray *psa, SQLite3_result *result, char *error, int affected_rows, const char *query_type, bool send_ready_for_query, char txn_state) { assert(psa != NULL); - const char *fs = strchr(query_type, ' '); - int qtlen = strlen(query_type); - if (fs != NULL) { - qtlen = (fs - query_type) + 1; - } - char buf[qtlen]; - memcpy(buf,query_type, qtlen-1); - buf[qtlen-1] = 0; - { - char *s = buf; - while (*s) { - *s = toupper((unsigned char) *s); - s++; - } + const char *query = query_type ? query_type : ""; + const size_t command_len = strcspn(query, " \t\r\n"); + std::string buf(query, command_len); + for (char& c : buf) { + c = std::toupper(c, std::locale::classic()); } if (result) { int ncol = result->columns; @@ -250,12 +268,11 @@ void SQLite3_to_Postgres(PtrSizeArray *psa, SQLite3_result *result, char *error, pkt.to_PtrSizeArray(psa); } - if (strcmp(buf,"SELECT") == 0) { - char tmpbuf[128]; - sprintf(tmpbuf,"%s %d", buf, result->rows_count); - pkt.write_generic('C', "s", tmpbuf); + if (buf == "SELECT") { + const std::string completion_tag = buf + " " + std::to_string(result->rows_count); + pkt.write_generic('C', "s", completion_tag.c_str()); } else { - pkt.write_CommandComplete(buf); + pkt.write_CommandComplete(buf.c_str()); } pkt.to_PtrSizeArray(psa); if (send_ready_for_query) pkt.write_ReadyForQuery(txn_state); @@ -278,15 +295,14 @@ void SQLite3_to_Postgres(PtrSizeArray *psa, SQLite3_result *result, char *error, */ // see https://www.postgresql.org/docs/current/protocol-message-formats.html } else { - char tmpbuf[128]; - if (strcmp(buf,"INSERT") == 0) { - sprintf(tmpbuf,"%s 0 %d", buf, affected_rows); - pkt.write_generic('C', "s", tmpbuf); - } else if (strcmp(buf,"UPDATE") == 0 || strcmp(buf,"DELETE") == 0) { - sprintf(tmpbuf,"%s %d", buf, affected_rows); - pkt.write_generic('C', "s", tmpbuf); + if (buf == "INSERT") { + const std::string completion_tag = buf + " 0 " + std::to_string(affected_rows); + pkt.write_generic('C', "s", completion_tag.c_str()); + } else if (buf == "UPDATE" || buf == "DELETE") { + const std::string completion_tag = buf + " " + std::to_string(affected_rows); + pkt.write_generic('C', "s", completion_tag.c_str()); } else { - pkt.write_CommandComplete(buf); + pkt.write_CommandComplete(buf.c_str()); } } pkt.to_PtrSizeArray(psa); @@ -315,20 +331,11 @@ void PG_pkt::write_DataRow(const char *tupdesc, ...) { val = tmp; } else if (tupdesc[i] == 's') { val = va_arg(ap, char *); - } else if (tupdesc[i] == 'b') { - int blen = va_arg(ap, int); - if (blen >= 0) { - uint8_t *bval = va_arg(ap, uint8_t *); - size_t required = 2 + blen * 2 + 1; - tmp2 = (char *)malloc(required); - strcpy(tmp2, "\\x"); - for (int j = 0; j < blen; j++) - sprintf(tmp2 + (2 + j * 2), "%02x", bval[j]); - val = tmp2; - } else { - (void) va_arg(ap, uint8_t *); - val = NULL; - } + } else if (tupdesc[i] == 'b') { + const int blen = va_arg(ap, int); + const uint8_t *bval = va_arg(ap, uint8_t *); + tmp2 = encode_bytea(bval, blen); + val = tmp2; } else if (tupdesc[i] == 'T') { usec_t time = va_arg(ap, usec_t); val = format_time_s(time, tmp, sizeof(tmp)); @@ -342,7 +349,7 @@ void PG_pkt::write_DataRow(const char *tupdesc, ...) { put_uint32(len); put_bytes(val, len); if (tmp2 != NULL) { - free(tmp2); + l_free(0, tmp2); tmp2 = NULL; } } else { @@ -1032,8 +1039,8 @@ EXECUTION_STATE PgSQL_Protocol::process_handshake_response_packet(unsigned char* } PgCredentials stored_user_info{ '\0' }; - strncpy(stored_user_info.name, user, MAX_USERNAME); - strncpy(stored_user_info.passwd, password, MAX_PASSWORD); + snprintf(stored_user_info.name, sizeof(stored_user_info.name), "%.*s", (int)(sizeof(stored_user_info.name) - 1), user); + snprintf(stored_user_info.passwd, sizeof(stored_user_info.passwd), "%.*s", (int)(sizeof(stored_user_info.passwd) - 1), password); if (!(*myds)->scram_state->server_nonce) { /* process as SASLInitialResponse */ @@ -1610,6 +1617,9 @@ char* extract_tag_from_query(const char* query) { constexpr size_t deallocate_prepare_all_len = sizeof("DEALLOCATE PREPARE ALL") - 1; constexpr size_t discard_all_len = sizeof("DISCARD ALL") - 1; + if (query == nullptr) { + return strdup(""); + } size_t qtlen = strlen(query); if ((qtlen > create_table_len) && strncasecmp(query, "CREATE TABLE AS", create_table_len) == 0) { return strdup("SELECT"); @@ -1620,23 +1630,13 @@ char* extract_tag_from_query(const char* query) { } else if ((qtlen >= discard_all_len) && (strncasecmp(query, "DISCARD ALL", discard_all_len) == 0)) { return strdup("DISCARD ALL"); } else { - const char* fs = strchr(query, ' '); - - if (fs != NULL) { - qtlen = (fs - query) + 1; - } - char buf[qtlen]; - memcpy(buf, query, qtlen - 1); - buf[qtlen - 1] = 0; - { - char* s = buf; - while (*s) { - *s = toupper((unsigned char)*s); - s++; - } + qtlen = strcspn(query, " \t\r\n"); + std::string buf(query, qtlen); + for (char& c : buf) { + c = std::toupper(c, std::locale::classic()); } - return strdup(buf); + return strdup(buf.c_str()); } } diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index 35cdede51f..63492e3ed6 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -7530,7 +7530,7 @@ char* PgSQL_Session::get_current_query(int max_length) { memcpy(res, query_ptr, query_len - 3); memcpy(res + (query_len - 3), "...", 3); } else { - strncpy(res, query_ptr, query_len); + memcpy(res, query_ptr, query_len); } res[query_len] = '\0'; } diff --git a/lib/PgSQL_Variables_Validator.cpp b/lib/PgSQL_Variables_Validator.cpp index f6806ed00c..7281b4245b 100644 --- a/lib/PgSQL_Variables_Validator.cpp +++ b/lib/PgSQL_Variables_Validator.cpp @@ -2,6 +2,7 @@ #include "PgSQL_Variables_Validator.h" #include "PgSQL_Session.h" #include "cpp.h" +#include /** * @brief Validates a boolean variable for PostgreSQL. @@ -261,12 +262,12 @@ bool pgsql_variable_validate_maintenance_work_mem_v2(const char* value, const pa /* Parse unit part */ const char* unit_ptr = endptr; uint64_t multiplier; - char unit[3] = { 0 }; + const char* unit = "kB"; // default unit size_t unit_len = strlen(unit_ptr); + size_t actual_unit_len = 2; /* Handle default unit (kB) if no unit specified */ if (unit_len == 0) { - strcpy(unit, "kB"); multiplier = 1024; } else { @@ -277,23 +278,27 @@ bool pgsql_variable_validate_maintenance_work_mem_v2(const char* value, const pa /* Validate unit and set multiplier */ if (unit_len == 1 && u[0] == 'b') { - strcpy(unit, "B"); + unit = "B"; + actual_unit_len = 1; multiplier = 1; } else if (strcmp(u, "kb") == 0) { - strcpy(unit, "kB"); + unit = "kB"; multiplier = 1024; } else if (strcmp(u, "mb") == 0) { - strcpy(unit, "MB"); + unit = "MB"; + actual_unit_len = 2; multiplier = 1024 * 1024; } else if (strcmp(u, "gb") == 0) { - strcpy(unit, "GB"); + unit = "GB"; + actual_unit_len = 2; multiplier = 1024ULL * 1024 * 1024; } else if (strcmp(u, "tb") == 0) { - strcpy(unit, "TB"); + unit = "TB"; + actual_unit_len = 2; multiplier = 1024ULL * 1024 * 1024 * 1024; } else { @@ -301,7 +306,6 @@ bool pgsql_variable_validate_maintenance_work_mem_v2(const char* value, const pa } /* Validate unit length matches parsed characters */ - size_t actual_unit_len = (unit[1] == 'B') ? 2 : (unit[0] == 'B') ? 1 : 0; if (strlen(unit_ptr) != actual_unit_len) return false; } @@ -359,39 +363,44 @@ bool pgsql_variable_validate_maintenance_work_mem_v3(const char* value, const pa // Parse unit const char* unit_ptr = endptr; uint64_t multiplier; - char unit[3] = { 0 }; + const char* unit = "kB"; // default unit size_t unit_len = strlen(unit_ptr); + size_t actual_unit_len = 2; // Default to kB if no unit specified if (unit_len == 0) { - strcpy(unit, "kB"); multiplier = 1024; } else { // Convert unit to lowercase for validation char u[3] = { 0 }; - for (int i = 0; i < 2 && unit_ptr[i]; i++) + for (int i = 0; i < 2 && unit_ptr[i]; i++) { u[i] = ::tolower((unsigned char)unit_ptr[i]); + } // Validate units and set multipliers if (unit_len == 1 && u[0] == 'b') { - strcpy(unit, "B"); + unit = "B"; + actual_unit_len = 1; multiplier = 1; } else if (strcmp(u, "kb") == 0) { - strcpy(unit, "kB"); + unit = "kB"; multiplier = 1024; } else if (strcmp(u, "mb") == 0) { - strcpy(unit, "MB"); + unit = "MB"; + actual_unit_len = 2; multiplier = 1024 * 1024; } else if (strcmp(u, "gb") == 0) { - strcpy(unit, "GB"); + unit = "GB"; + actual_unit_len = 2; multiplier = 1024ULL * 1024 * 1024; } else if (strcmp(u, "tb") == 0) { - strcpy(unit, "TB"); + unit = "TB"; + actual_unit_len = 2; multiplier = 1024ULL * 1024 * 1024 * 1024; } else { @@ -399,9 +408,9 @@ bool pgsql_variable_validate_maintenance_work_mem_v3(const char* value, const pa } // Validate unit length matches parsed characters - size_t expected_len = (unit[1] == 'B') ? 2 : (unit[0] == 'B') ? 1 : 0; - if (strlen(unit_ptr) != expected_len) + if (std::string_view(unit_ptr).size() != actual_unit_len) { return false; + } } // Calculate total bytes with floating point @@ -459,11 +468,9 @@ bool pgsql_variable_validate_search_path(const char* value, const params_t* para size_t value_len = strlen(value); // NOSONAR if (value_len > SIZE_MAX - 1) return false; - char* normalized = (char*)malloc(value_len + 1); - if (normalized == nullptr) return false; - normalized[0] = '\0'; + std::string normalized; + normalized.reserve(value_len + 1); - size_t norm_pos = 0; bool first = true; bool result = true; @@ -529,18 +536,15 @@ bool pgsql_variable_validate_search_path(const char* value, const params_t* para if (!result) break; } - // add to normalized if (!first) { - normalized[norm_pos++] = ','; + normalized.push_back(','); } first = false; // append the part bytes if (part_len > 0) { - memcpy(normalized + norm_pos, part_start, part_len); - norm_pos += part_len; + normalized.append(part_start, part_len); } - normalized[norm_pos] = '\0'; // skip whitespace after part while (*token && fast_isspace(*token)) token++; @@ -557,12 +561,10 @@ bool pgsql_variable_validate_search_path(const char* value, const params_t* para if (result) { if (transformed_value) { - *transformed_value = normalized; + *transformed_value = strdup(normalized.c_str()); } else { - free(normalized); + // no output requested; keep as no-op } - } else { - free(normalized); } return result; diff --git a/lib/ProxySQL_Admin_Tests.cpp b/lib/ProxySQL_Admin_Tests.cpp index 4dc7af3d2b..bfff96a13c 100644 --- a/lib/ProxySQL_Admin_Tests.cpp +++ b/lib/ProxySQL_Admin_Tests.cpp @@ -6,6 +6,7 @@ #include #include // std::vector #include +#include #include "MySQL_Data_Stream.h" @@ -91,8 +92,11 @@ int ProxySQL_Test___GenerateRandomQueryInDigestTable(int n) { char * schemaname_buf = (char *)malloc(64); //ui.username = username_buf; //ui.schemaname = schemaname_buf; - strcpy(username_buf,"user_name_"); - strcpy(schemaname_buf,"shard_name_"); + static const char user_name_prefix[] = "user_name_"; + static const char schema_name_prefix[] = "shard_name_"; + // sizeof() includes terminating NULs, and these buffers are intentionally larger. + memcpy(username_buf, user_name_prefix, sizeof(user_name_prefix)); + memcpy(schemaname_buf, schema_name_prefix, sizeof(schema_name_prefix)); bool orig_norm = mysql_thread___query_digests_normalize_digest_text; for (int i=0; i #include // std::vector #include +#include #include "MySQL_Query_Processor.h" #include "PgSQL_Query_Processor.h" @@ -330,12 +331,14 @@ unsigned int ProxySQL_Admin::ProxySQL_Test___GenerateRandom_mysql_query_rules_fa char * schemaname_buf = (char *)malloc(256); //ui.username = username_buf; //ui.schemaname = schemaname_buf; + static const char user_name_prefix[] = "user_name_"; + static const char schema_name_prefix[] = "shard_name_"; if (empty==false) { - strcpy(username_buf,"user_name_"); + memcpy(username_buf, user_name_prefix, sizeof(user_name_prefix)); } else { - strcpy(username_buf,""); + *username_buf = '\0'; } - strcpy(schemaname_buf,"shard_name_"); + memcpy(schemaname_buf, schema_name_prefix, sizeof(schema_name_prefix)); int _k; for (unsigned int i=0; i #include #include +#include #include #include +static inline size_t safe_strlen(const char *s) { + if (s == nullptr) { + return 0; + } + size_t len = 0; + while (s[len] != '\0') { + ++len; + } + return len; +} + +template +static void format_query(char *query, size_t query_len, const char *format, Args... args) { + if (query == nullptr || query_len == 0) { + return; + } + + std::string formatted; + if (string_format(format, formatted, args...) < 0) { + query[0] = '\0'; + return; + } + + size_t copy_len = formatted.size(); + if (copy_len >= query_len) { + copy_len = query_len - 1; + } + memcpy(query, formatted.data(), copy_len); + query[copy_len] = '\0'; +} + +static void append_config_field(std::string& fields, std::string& values, + bool& is_first_field, const std::string& field_name, + const std::string& field_value, bool is_int) { + if (!is_first_field) { + fields += ", "; + values += ", "; + } else { + is_first_field = false; + } + fields += field_name; + + if (is_int) { + values += field_value; + return; + } + + char *cs = strdup(field_value.c_str()); + char *ecs = escape_string_single_quotes(cs, false); + const char* safe_escaped = ecs ? ecs : ""; + values += std::string("'") + safe_escaped + "'"; + if (cs != ecs) { + l_free(0, cs); + } + l_free(0, ecs); +} + const char* config_header = "########################################################################################\n" "# This config file is parsed using libconfig , and its grammar is described in:\n" "# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-File-Grammar\n" @@ -53,7 +111,7 @@ ProxySQL_Config:: ~ProxySQL_Config() { void ProxySQL_Config::addField(std::string& data, const char* name, const char* value, const char* dq) { std::stringstream ss; - if (!value || !strlen(value)) return; + if (value == NULL || value[0] == 0) return; // Escape the double quotes in all the fields contents std::string esc_value { value }; @@ -91,25 +149,27 @@ void ProxySQL_Config::addField(std::string& data, const char* name, const char* * @see ProxySQL_Config::Write_Global_Variables_to_configfile() */ int ProxySQL_Config::Read_Global_Variables_from_configfile(const char *prefix) { + if (prefix == NULL) return 0; const Setting& root = GloVars.confFile->cfg.getRoot(); - char *groupname=(char *)malloc(strlen(prefix)+strlen((char *)"_variables")+1); + const size_t prefix_len = safe_strlen(prefix); + const size_t suffix_len = sizeof("_variables") - 1; + char *groupname=(char *)l_alloc(prefix_len + suffix_len + 1); sprintf(groupname,"%s%s",prefix,"_variables"); if (root.exists(groupname)==false) { - free(groupname); + l_free(0, groupname); return 0; } const Setting &group = root[(const char *)groupname]; int count = group.getLength(); //fprintf(stderr, "Found %d %s_variables\n",count, prefix); int i; - size_t prefix_len = strlen(prefix); admindb->execute("PRAGMA foreign_keys = OFF"); // Prepare statement once for all inserts auto [rc, stmt] = admindb->prepare_v2("INSERT OR REPLACE INTO global_variables VALUES (?1, ?2)"); if (rc != SQLITE_OK) { proxy_error("Failed to prepare statement for global_variables insert: %d\n", rc); admindb->execute("PRAGMA foreign_keys = ON"); - free(groupname); + l_free(0, groupname); return 0; } for (i=0; i< count; i++) { @@ -146,7 +206,7 @@ int ProxySQL_Config::Read_Global_Variables_from_configfile(const char *prefix) { } // Statement automatically finalized when stmt goes out of scope admindb->execute("PRAGMA foreign_keys = ON"); - free(groupname); + l_free(0, groupname); return i; } @@ -240,12 +300,19 @@ int ProxySQL_Config::Read_MySQL_Users_from_configfile(std::string& error) { user.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(username.c_str())+strlen(password.c_str())+strlen(o)+strlen(attributes.c_str())+128); - sprintf(query,q, username.c_str(), password.c_str(), active, use_ssl, default_hostgroup, default_schema.c_str(), schema_locked, transaction_persistent, fast_forward, max_connections, attributes.c_str(), o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t password_len = password.size(); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t attributes_len = attributes.size(); + const size_t query_len = query_base_len + username_len + password_len + default_schema.size() + safe_comment_len + attributes_len + 128; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, username.c_str(), password.c_str(), active, use_ssl, default_hostgroup, default_schema.c_str(), schema_locked, transaction_persistent, fast_forward, max_connections, attributes.c_str(), safe_comment); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -347,20 +414,21 @@ int ProxySQL_Config::Read_Scheduler_from_configfile() { sched.lookupValue("comment", comment); - int query_len=0; - query_len+=strlen(q) + - strlen(std::to_string(id).c_str()) + - strlen(std::to_string(active).c_str()) + - strlen(std::to_string(interval_ms).c_str()) + - strlen(filename.c_str()) + - ( arg1_exists ? strlen(arg1.c_str()) : 0 ) + 4 + - ( arg2_exists ? strlen(arg2.c_str()) : 0 ) + 4 + - ( arg3_exists ? strlen(arg3.c_str()) : 0 ) + 4 + - ( arg4_exists ? strlen(arg4.c_str()) : 0 ) + 4 + - ( arg5_exists ? strlen(arg5.c_str()) : 0 ) + 4 + - strlen(comment.c_str()) + - 40; - char *query=(char *)malloc(query_len); + const size_t query_base_len = safe_strlen(q); + const string id_str = to_string(id); + const string active_str = to_string(active); + const string interval_ms_str = to_string(interval_ms); + const size_t filename_len = filename.size(); + const size_t arg1_len = arg1_exists ? arg1.size() : 0; + const size_t arg2_len = arg2_exists ? arg2.size() : 0; + const size_t arg3_len = arg3_exists ? arg3.size() : 0; + const size_t arg4_len = arg4_exists ? arg4.size() : 0; + const size_t arg5_len = arg5_exists ? arg5.size() : 0; + const size_t comment_len = comment.size(); + const size_t query_len = query_base_len + id_str.size() + active_str.size() + interval_ms_str.size() + + filename_len + (arg1_len + 4) + (arg2_len + 4) + (arg3_len + 4) + (arg4_len + 4) + (arg5_len + 4) + + comment_len + 40; + char *query=(char *)l_alloc(query_len); if (arg1_exists) arg1="\'" + arg1 + "\'"; else @@ -382,7 +450,7 @@ int ProxySQL_Config::Read_Scheduler_from_configfile() { else arg5 = "NULL"; - sprintf(query, q, + format_query(query, query_len, q, id, active, interval_ms, filename.c_str(), @@ -394,7 +462,7 @@ int ProxySQL_Config::Read_Scheduler_from_configfile() { comment.c_str() ); admindb->execute(query); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -518,22 +586,29 @@ int ProxySQL_Config::Read_Restapi_from_configfile() { char *comment_escaped = escape_string_single_quotes(comment_escaped_raw, false); const char *q = id_exists ? q_with_id : q_without_id; + const size_t query_base_len = safe_strlen(q); const std::string active_str = std::to_string(active); const std::string timeout_ms_str = std::to_string(timeout_ms); const std::string id_str = id_exists ? std::to_string(id) : std::string(); - int query_len=0; - query_len+=strlen(q) + - strlen(active_str.c_str()) + - strlen(timeout_ms_str.c_str()) + - strlen(method_escaped) + - strlen(uri_escaped) + - strlen(script_escaped) + - strlen(comment_escaped) + - 40; - if (id_exists) { - query_len += strlen(id_str.c_str()); - } - char *query=(char *)malloc(query_len); + const char* safe_method_escaped = method_escaped ? method_escaped : ""; + const char* safe_uri_escaped = uri_escaped ? uri_escaped : ""; + const char* safe_script_escaped = script_escaped ? script_escaped : ""; + const char* safe_comment_escaped = comment_escaped ? comment_escaped : ""; + const size_t safe_method_len = safe_strlen(safe_method_escaped); + const size_t safe_uri_len = safe_strlen(safe_uri_escaped); + const size_t safe_script_len = safe_strlen(safe_script_escaped); + const size_t safe_comment_len = safe_strlen(safe_comment_escaped); + size_t query_len = + query_base_len + + active_str.size() + + timeout_ms_str.size() + + safe_method_len + + safe_uri_len + + safe_script_len + + safe_comment_len + + 40 + + (id_exists ? id_str.size() : 0); + char *query=(char *)l_alloc(query_len); if (query == NULL) { proxy_error("Admin: unable to allocate memory while loading restapi routes from config file\n"); if (method_escaped != method_escaped_raw) free(method_escaped); @@ -547,22 +622,22 @@ int ProxySQL_Config::Read_Restapi_from_configfile() { continue; } if (id_exists) { - snprintf(query, query_len, q, + format_query(query, query_len, q, id, active, timeout_ms, - method_escaped, - uri_escaped, - script_escaped, - comment_escaped + safe_method_escaped, + safe_uri_escaped, + safe_script_escaped, + safe_comment_escaped ); } else { - snprintf(query, query_len, q, + format_query(query, query_len, q, active, timeout_ms, - method_escaped, - uri_escaped, - script_escaped, - comment_escaped + safe_method_escaped, + safe_uri_escaped, + safe_script_escaped, + safe_comment_escaped ); } admindb->execute(query); @@ -574,7 +649,7 @@ int ProxySQL_Config::Read_Restapi_from_configfile() { free(uri_escaped_raw); free(script_escaped_raw); free(comment_escaped_raw); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -902,47 +977,65 @@ int ProxySQL_Config::Read_MySQL_Query_Rules_from_configfile() { if (rule.lookupValue("attributes", attributes)) attributes_exists=true; - //if (user.lookupValue("default_schema", default_schema)==false) default_schema=""; - int query_len=0; - query_len+=strlen(q) + - strlen(std::to_string(rule_id).c_str()) + - strlen(std::to_string(active).c_str()) + - ( username_exists ? strlen(username.c_str()) : 0 ) + 4 + - ( schemaname_exists ? strlen(schemaname.c_str()) : 0 ) + 4 + - strlen(std::to_string(flagIN).c_str()) + 4 + - - ( client_addr_exists ? strlen(client_addr.c_str()) : 0 ) + 4 + - ( proxy_addr_exists ? strlen(proxy_addr.c_str()) : 0 ) + 4 + - strlen(std::to_string(proxy_port).c_str()) + 4 + - - ( match_digest_exists ? strlen(match_digest.c_str()) : 0 ) + 4 + - ( match_pattern_exists ? strlen(match_pattern.c_str()) : 0 ) + 4 + - strlen(std::to_string(negate_match_pattern).c_str()) + 4 + - ( re_modifiers_exists ? strlen(re_modifiers.c_str()) : 0 ) + 4 + - strlen(std::to_string(flagOUT).c_str()) + 4 + - ( replace_pattern_exists ? strlen(replace_pattern.c_str()) : 0 ) + 4 + - strlen(std::to_string(destination_hostgroup).c_str()) + 4 + - strlen(std::to_string(cache_ttl).c_str()) + 4 + - strlen(std::to_string(cache_empty_result).c_str()) + 4 + - strlen(std::to_string(cache_timeout).c_str()) + 4 + - strlen(std::to_string(reconnect).c_str()) + 4 + - strlen(std::to_string(timeout).c_str()) + 4 + - strlen(std::to_string(next_query_flagIN).c_str()) + 4 + - strlen(std::to_string(mirror_flagOUT).c_str()) + 4 + - strlen(std::to_string(mirror_hostgroup).c_str()) + 4 + - strlen(std::to_string(retries).c_str()) + 4 + - strlen(std::to_string(delay).c_str()) + 4 + - ( error_msg_exists ? strlen(error_msg.c_str()) : 0 ) + 4 + - ( OK_msg_exists ? strlen(OK_msg.c_str()) : 0 ) + 4 + - strlen(std::to_string(sticky_conn).c_str()) + 4 + - strlen(std::to_string(multiplex).c_str()) + 4 + - strlen(std::to_string(gtid_from_hostgroup).c_str()) + 4 + - strlen(std::to_string(log).c_str()) + 4 + - strlen(std::to_string(apply).c_str()) + 4 + - ( attributes_exists ? strlen(attributes.c_str()) : 0 ) + 4 + - ( comment_exists ? strlen(comment.c_str()) : 0 ) + 4 + - 64; - char *query=(char *)malloc(query_len); + //if (user.lookupValue("default_schema", default_schema)==false) default_schema=""; + const size_t query_base_len = safe_strlen(q); + const string rule_id_str = to_string(rule_id); + const string active_str = to_string(active); + const string flagIN_str = to_string(flagIN); + const string proxy_port_str = to_string(proxy_port); + const string negate_match_pattern_str = to_string(negate_match_pattern); + const string flagOUT_str = to_string(flagOUT); + const string destination_hostgroup_str = to_string(destination_hostgroup); + const string cache_ttl_str = to_string(cache_ttl); + const string cache_empty_result_str = to_string(cache_empty_result); + const string cache_timeout_str = to_string(cache_timeout); + const string reconnect_str = to_string(reconnect); + const string timeout_str = to_string(timeout); + const string next_query_flagIN_str = to_string(next_query_flagIN); + const string mirror_flagOUT_str = to_string(mirror_flagOUT); + const string mirror_hostgroup_str = to_string(mirror_hostgroup); + const string retries_str = to_string(retries); + const string delay_str = to_string(delay); + const string sticky_conn_str = to_string(sticky_conn); + const string multiplex_str = to_string(multiplex); + const string gtid_from_hostgroup_str = to_string(gtid_from_hostgroup); + const string log_str = to_string(log); + const string apply_str = to_string(apply); + size_t query_len = query_base_len + rule_id_str.size() + active_str.size() + flagIN_str.size() + + ( username_exists ? username.size() : 0 ) + 4 + + ( schemaname_exists ? schemaname.size() : 0 ) + 4 + + ( client_addr_exists ? client_addr.size() : 0 ) + 4 + + ( proxy_addr_exists ? proxy_addr.size() : 0 ) + 4 + + proxy_port_str.size() + 4 + + ( digest_exists ? digest.size() : 0 ) + 4 + + ( match_digest_exists ? match_digest.size() : 0 ) + 4 + + ( match_pattern_exists ? match_pattern.size() : 0 ) + 4 + + negate_match_pattern_str.size() + 4 + + ( re_modifiers_exists ? re_modifiers.size() : 0 ) + 4 + + flagOUT_str.size() + 4 + + ( replace_pattern_exists ? replace_pattern.size() : 0 ) + 4 + + destination_hostgroup_str.size() + 4 + + cache_ttl_str.size() + 4 + + cache_empty_result_str.size() + 4 + + cache_timeout_str.size() + 4 + + reconnect_str.size() + 4 + + timeout_str.size() + 4 + + next_query_flagIN_str.size() + 4 + + mirror_flagOUT_str.size() + 4 + + mirror_hostgroup_str.size() + 4 + + retries_str.size() + 4 + + delay_str.size() + 4 + + ( error_msg_exists ? error_msg.size() : 0 ) + 4 + + ( OK_msg_exists ? OK_msg.size() : 0 ) + 4 + + sticky_conn_str.size() + 4 + + multiplex_str.size() + 4 + + gtid_from_hostgroup_str.size() + 4 + + log_str.size() + 4 + + apply_str.size() + 4 + + ( attributes_exists ? attributes.size() : 0 ) + 4 + + ( comment_exists ? comment.size() : 0 ) + 4 + + 64; + char *query=(char *)l_alloc(query_len); if (username_exists) username="\"" + username + "\""; else @@ -999,7 +1092,7 @@ int ProxySQL_Config::Read_MySQL_Query_Rules_from_configfile() { comment = "NULL"; - sprintf(query, q, + format_query(query, query_len, q, rule_id, active, username.c_str(), schemaname.c_str(), @@ -1037,7 +1130,7 @@ int ProxySQL_Config::Read_MySQL_Query_Rules_from_configfile() { ); //fprintf(stderr, "%s\n", query); admindb->execute(query); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -1394,13 +1487,19 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { server.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(status.c_str())+strlen(address.c_str())+strlen(o)+128); - sprintf(query,q, address.c_str(), port, gtid_port, hostgroup, compression, weight, status.c_str(), max_connections, max_replication_lag, use_ssl, max_latency_ms, o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t status_len = status.size(); + const size_t address_len = address.size(); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + status_len + address_len + safe_comment_len + 128; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, address.c_str(), port, gtid_port, hostgroup, compression, weight, status.c_str(), max_connections, max_replication_lag, use_ssl, max_latency_ms, safe_comment); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -1437,23 +1536,30 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { } char *t1=strdup(check_type.c_str()); char *t=escape_string_single_quotes(t1, false); - char *query=(char *)malloc(strlen(q)+strlen(o)+strlen(t)+32); - sprintf(query,q, writer_hostgroup, reader_hostgroup, o, t); + const char* safe_comment = o ? o : ""; + const char* safe_check_type = t ? t : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t safe_check_type_len = safe_strlen(safe_check_type); + const size_t query_len = query_base_len + safe_comment_len + safe_check_type_len + 32; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, reader_hostgroup, safe_comment, safe_check_type); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o!=o1) free(o); free(o1); if (t!=t1) free(t); free(t1); - free(query); + l_free(0, query); rows++; } } - if (root.exists("mysql_servers_ssl_params")==true) { // mysql_servers_ssl_params - const Setting &mysql_servers_ssl_params = root["mysql_servers_ssl_params"]; - int count = mysql_servers_ssl_params.getLength(); - char *q=(char *)"INSERT OR REPLACE INTO mysql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')"; - for (i=0; i< count; i++) { + if (root.exists("mysql_servers_ssl_params")==true) { // mysql_servers_ssl_params + const Setting &mysql_servers_ssl_params = root["mysql_servers_ssl_params"]; + int count = mysql_servers_ssl_params.getLength(); + char *q=(char *)"INSERT OR REPLACE INTO mysql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')"; + const size_t q_len = safe_strlen(q); + for (i=0; i< count; i++) { const Setting &line = mysql_servers_ssl_params[i]; string hostname = ""; int port = 3306; @@ -1484,71 +1590,88 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { line.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc( - strlen(q) - + hostname.length() + username.length() - + ssl_ca.length() + ssl_cert.length() + ssl_key.length() + ssl_capath.length() - + ssl_crl.length() + ssl_crlpath.length() + ssl_cipher.length() + tls_version.length() - + strlen(o) + 32); - sprintf(query, q, + const size_t hostname_len = hostname.length(); + const size_t username_len = username.length(); + const size_t ssl_ca_len = ssl_ca.length(); + const size_t ssl_cert_len = ssl_cert.length(); + const size_t ssl_key_len = ssl_key.length(); + const size_t ssl_capath_len = ssl_capath.length(); + const size_t ssl_crl_len = ssl_crl.length(); + const size_t ssl_crlpath_len = ssl_crlpath.length(); + const size_t ssl_cipher_len = ssl_cipher.length(); + const size_t tls_version_len = tls_version.length(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + const size_t query_len = + q_len + + hostname_len + username_len + + ssl_ca_len + ssl_cert_len + ssl_key_len + ssl_capath_len + + ssl_crl_len + ssl_crlpath_len + ssl_cipher_len + tls_version_len + + escaped_comment_len + 32; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, hostname.c_str() , port , username.c_str() , ssl_ca.c_str() , ssl_cert.c_str() , ssl_key.c_str() , ssl_capath.c_str() , ssl_crl.c_str() , ssl_crlpath.c_str() , ssl_cipher.c_str() , tls_version.c_str() , - o); + safe_comment); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } - if (root.exists("mysql_group_replication_hostgroups")==true) { - const Setting &mysql_group_replication_hostgroups = root["mysql_group_replication_hostgroups"]; - int count = mysql_group_replication_hostgroups.getLength(); - char *q=(char *)"INSERT OR REPLACE INTO mysql_group_replication_hostgroups (writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, comment) VALUES (%d, %d, %d, %d, %d, %d, %d, %d, '%s')"; - for (i=0; i< count; i++) { - const Setting &line = mysql_group_replication_hostgroups[i]; - int writer_hostgroup; - int backup_writer_hostgroup; - int reader_hostgroup; - int offline_hostgroup; - int active=1; // default - int max_writers; - int writer_is_also_reader; - int max_transactions_behind; - std::string comment=""; - if (line.lookupValue("writer_hostgroup", writer_hostgroup)==false) { - proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory writer_hostgroup\n"); - continue; - } - if (line.lookupValue("backup_writer_hostgroup", backup_writer_hostgroup)==false) { - proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory backup_writer_hostgroup\n"); - continue; - } - if (line.lookupValue("reader_hostgroup", reader_hostgroup)==false) { - proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory reader_hostgroup\n"); - continue; - } - if (line.lookupValue("offline_hostgroup", offline_hostgroup)==false) { - proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory offline_hostgroup\n"); - continue; - } + if (root.exists("mysql_group_replication_hostgroups")==true) { + const Setting &mysql_group_replication_hostgroups = root["mysql_group_replication_hostgroups"]; + int count = mysql_group_replication_hostgroups.getLength(); + char *q=(char *)"INSERT OR REPLACE INTO mysql_group_replication_hostgroups (writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, comment) VALUES (%d, %d, %d, %d, %d, %d, %d, %d, '%s')"; + for (i=0; i< count; i++) { + const Setting &line = mysql_group_replication_hostgroups[i]; + int writer_hostgroup; + int backup_writer_hostgroup; + int reader_hostgroup; + int offline_hostgroup; + int active=1; // default + int max_writers; + int writer_is_also_reader; + int max_transactions_behind; + std::string comment=""; + if (line.lookupValue("writer_hostgroup", writer_hostgroup)==false) { + proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory writer_hostgroup\n"); + continue; + } + if (line.lookupValue("backup_writer_hostgroup", backup_writer_hostgroup)==false) { + proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory backup_writer_hostgroup\n"); + continue; + } + if (line.lookupValue("reader_hostgroup", reader_hostgroup)==false) { + proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory reader_hostgroup\n"); + continue; + } + if (line.lookupValue("offline_hostgroup", offline_hostgroup)==false) { + proxy_error("Admin: detected a mysql_group_replication_hostgroups in config file without a mandatory offline_hostgroup\n"); + continue; + } if (line.lookupValue("max_writers", max_writers)==false) max_writers=1; - if (line.lookupValue("writer_is_also_reader", writer_is_also_reader)==false) writer_is_also_reader=0; - if (line.lookupValue("max_transactions_behind", max_transactions_behind)==false) max_transactions_behind=0; - line.lookupValue("comment", comment); - char *o1=strdup(comment.c_str()); - char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(o)+128); // 128 vs sizeof(int)*8 - sprintf(query,q, writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, o); - //fprintf(stderr, "%s\n", query); - admindb->execute(query); - if (o!=o1) free(o); - free(o1); - free(query); - rows++; - } - } + if (line.lookupValue("writer_is_also_reader", writer_is_also_reader)==false) writer_is_also_reader=0; + if (line.lookupValue("max_transactions_behind", max_transactions_behind)==false) max_transactions_behind=0; + line.lookupValue("comment", comment); + char *o1=strdup(comment.c_str()); + char *o=escape_string_single_quotes(o1, false); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + safe_comment_len + 128; // 128 vs sizeof(int)*8 + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, safe_comment); + //fprintf(stderr, "%s\n", query); + admindb->execute(query); + if (o!=o1) free(o); + free(o1); + l_free(0, query); + rows++; + } + } if (root.exists("mysql_galera_hostgroups")==true) { const Setting &mysql_galera_hostgroups = root["mysql_galera_hostgroups"]; int count = mysql_galera_hostgroups.getLength(); @@ -1586,13 +1709,17 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { line.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(o)+128); // 128 vs sizeof(int)*8 - sprintf(query,q, writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + safe_comment_len + 128; // 128 vs sizeof(int)*8 + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, safe_comment); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -1641,15 +1768,21 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { char *o=escape_string_single_quotes(o1, false); char *p1=strdup(domain_name.c_str()); char *p=escape_string_single_quotes(p1, false); - char *query=(char *)malloc(strlen(q)+strlen(o)+strlen(p)+256); // 128 vs sizeof(int)*8 - sprintf(query,q, writer_hostgroup, reader_hostgroup, active, aurora_port, p, max_lag_ms, check_interval_ms, check_timeout_ms, writer_is_also_reader, new_reader_weight, add_lag_ms, min_lag_ms, lag_num_checks, autopurge_missing_checks, o); + const char* safe_comment = o ? o : ""; + const char* safe_domain = p ? p : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t safe_domain_len = safe_strlen(safe_domain); + const size_t query_len = query_base_len + safe_comment_len + safe_domain_len + 256; // 128 vs sizeof(int)*8 + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, reader_hostgroup, active, aurora_port, safe_domain, max_lag_ms, check_interval_ms, check_timeout_ms, writer_is_also_reader, new_reader_weight, add_lag_ms, min_lag_ms, lag_num_checks, autopurge_missing_checks, safe_comment); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o!=o1) free(o); free(o1); if (p!=p1) free(p); free(p1); - free(query); + l_free(0, query); rows++; } } @@ -1678,17 +1811,17 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { proxy_error("Admin: detected a mysql_aws_rds_bgd_hostgroups in config file without a mandatory reader_hostgroup\n"); continue; } - char green_writer_str[24]; - char green_reader_str[24]; + std::string green_writer_str; + std::string green_reader_str; if (line.lookupValue("green_writer_hostgroup", green_writer_hostgroup)==false) { - strcpy(green_writer_str, "NULL"); + green_writer_str = "NULL"; } else { - snprintf(green_writer_str, sizeof(green_writer_str), "%d", green_writer_hostgroup); + green_writer_str = std::to_string(green_writer_hostgroup); } if (line.lookupValue("green_reader_hostgroup", green_reader_hostgroup)==false) { - strcpy(green_reader_str, "NULL"); + green_reader_str = "NULL"; } else { - snprintf(green_reader_str, sizeof(green_reader_str), "%d", green_reader_hostgroup); + green_reader_str = std::to_string(green_reader_hostgroup); } if (line.lookupValue("active", active)==false) active=1; if (line.lookupValue("writer_is_also_reader", writer_is_also_reader)==false) writer_is_also_reader=0; @@ -1697,12 +1830,16 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { line.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(o)+256); // 128 vs sizeof(int)*8 - sprintf(query,q, writer_hostgroup, reader_hostgroup, green_writer_str, green_reader_str, active, writer_is_also_reader, check_interval_ms, check_timeout_ms, o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + safe_comment_len + 256; // 128 vs sizeof(int)*8 + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, reader_hostgroup, green_writer_str.c_str(), green_reader_str.c_str(), active, writer_is_also_reader, check_interval_ms, check_timeout_ms, safe_comment); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -1719,72 +1856,50 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile(std::string& error) { std::string fields = ""; std::string values = ""; - auto process_field = [&](const std::string &field_name, const std::string &field_value, int is_int) { - if (!is_first_field) { - fields += ", "; - values += ", "; - } - else { - is_first_field = false; - } - fields += field_name; - - if (is_int) { - values += field_value; - } - else { - char *cs = strdup(field_value.c_str()); - char *ecs = escape_string_single_quotes(cs, false); - values += std::string("'") + ecs + "'"; - if (cs != ecs) free(cs); - free(ecs); - } - }; - // Only inserting/updating fields which are in configuration file. // Fields default will be from table schema. // Parsing integer field if (hostgroup_attributes.lookupValue("hostgroup_id", integer_val) ) { - process_field("hostgroup_id", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "hostgroup_id", to_string(integer_val), true); } else { proxy_error("Admin: detected a mysql_hostgroup_attributes in config file without a mandatory hostgroup_id.\n"); continue; } if (hostgroup_attributes.lookupValue("max_num_online_servers", integer_val)) { - process_field("max_num_online_servers", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "max_num_online_servers", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("autocommit", integer_val)) { - process_field("autocommit", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "autocommit", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("free_connections_pct", integer_val)) { - process_field("free_connections_pct", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "free_connections_pct", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("multiplex", integer_val)) { - process_field("multiplex", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "multiplex", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("connection_warming", integer_val)) { - process_field("connection_warming", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "connection_warming", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("throttle_connections_per_sec", integer_val)) { - process_field("throttle_connections_per_sec", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "throttle_connections_per_sec", to_string(integer_val), true); } // Parsing string field if (hostgroup_attributes.lookupValue("init_connect", string_val)) { - process_field("init_connect", string_val, false); + append_config_field(fields, values, is_first_field, "init_connect", string_val, false); } if (hostgroup_attributes.lookupValue("ignore_session_variables", string_val)) { - process_field("ignore_session_variables", string_val, false); + append_config_field(fields, values, is_first_field, "ignore_session_variables", string_val, false); } if (hostgroup_attributes.lookupValue("hostgroup_settings", string_val)) { - process_field("hostgroup_settings", string_val, false); + append_config_field(fields, values, is_first_field, "hostgroup_settings", string_val, false); } if (hostgroup_attributes.lookupValue("servers_defaults", string_val)) { - process_field("servers_defaults", string_val, false); + append_config_field(fields, values, is_first_field, "servers_defaults", string_val, false); } if (hostgroup_attributes.lookupValue("comment", string_val)) { - process_field("comment", string_val, false); + append_config_field(fields, values, is_first_field, "comment", string_val, false); } std::string s_query = "INSERT OR REPLACE INTO mysql_hostgroup_attributes ("; @@ -1869,14 +1984,19 @@ int ProxySQL_Config::Read_ProxySQL_Servers_from_configfile(std::string& error) { server.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - char *query=(char *)malloc(strlen(q)+strlen(address.c_str())+strlen(o)+128); - sprintf(query, q, address.c_str(), port, weight, o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t address_len = address.size(); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + address_len + safe_comment_len + 128; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, address.c_str(), port, weight, safe_comment); proxy_info("Cluster: Adding ProxySQL Servers %s:%d from config file\n", address.c_str(), port); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o!=o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -1895,34 +2015,31 @@ int ProxySQL_Config::Write_Global_Variables_to_configfile(std::string& data) { if (error) { proxy_error("Error on read from global_variables : %s\n", error); return -1; - } else { - if (sqlite_resultset) { - std::string prefix; - - for (auto r : sqlite_resultset->rows) { - std::string input(r->fields[0]); - std::string p1 = input.substr(0, input.find("-")); - if (prefix.empty()) { - prefix = input.substr(0, input.find("-")); - data += prefix + "_variables =\n{\n"; - } else { - if (p1.compare(prefix)) { - prefix = p1; - data += "}\n\n" + prefix + "_variables = \n{\n"; - } - } - if (r->fields[1] && strlen(r->fields[1])) { - std::stringstream ss; - ss << "\t" << r->fields[0] + p1.size() + 1 << "=\"" << r->fields[1] << "\"\n"; - data += ss.str(); - } - } + } + if (sqlite_resultset == nullptr) + return 0; - if (!prefix.empty()) - data += "}\n"; + std::string prefix; + for (auto r : sqlite_resultset->rows) { + std::string input(r->fields[0]); + std::string p1 = input.substr(0, input.find("-")); + if (prefix.empty()) { + prefix = p1; + data += prefix + "_variables =\n{\n"; + } else if (p1.compare(prefix)) { + prefix = p1; + data += "}\n\n" + prefix + "_variables = \n{\n"; + } + if (r->fields[1] && r->fields[1][0] != '\0') { + std::stringstream ss; + ss << "\t" << r->fields[0] + p1.size() + 1 << "=\"" << r->fields[1] << "\"\n"; + data += ss.str(); } } + if (!prefix.empty()) + data += "}\n"; + if (sqlite_resultset) delete sqlite_resultset; @@ -2135,13 +2252,19 @@ int ProxySQL_Config::Read_PgSQL_Servers_from_configfile(std::string& error) { server.lookupValue("comment", comment); char* o1 = strdup(comment.c_str()); char* o = escape_string_single_quotes(o1, false); - char* query = (char*)malloc(strlen(q) + strlen(status.c_str()) + strlen(address.c_str()) + strlen(o) + 128); - sprintf(query, q, address.c_str(), port, hostgroup, compression, weight, status.c_str(), max_connections, max_replication_lag, use_ssl, max_latency_ms, o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t status_len = status.size(); + const size_t address_len = address.size(); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t query_len = query_base_len + status_len + address_len + safe_comment_len + 128; + char* query = (char*)l_alloc(query_len); + format_query(query, query_len, q, address.c_str(), port, hostgroup, compression, weight, status.c_str(), max_connections, max_replication_lag, use_ssl, max_latency_ms, safe_comment); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -2178,15 +2301,21 @@ int ProxySQL_Config::Read_PgSQL_Servers_from_configfile(std::string& error) { } char* t1 = strdup(check_type.c_str()); char* t = escape_string_single_quotes(t1, false); - char* query = (char*)malloc(strlen(q) + strlen(o) + strlen(t) + 32); - sprintf(query, q, writer_hostgroup, reader_hostgroup, o, t); + const char* safe_comment = o ? o : ""; + const char* safe_check_type = t ? t : ""; + const size_t query_base_len = safe_strlen(q); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t safe_check_type_len = safe_strlen(safe_check_type); + const size_t query_len = query_base_len + safe_comment_len + safe_check_type_len + 32; + char* query = (char*)l_alloc(query_len); + format_query(query, query_len, q, writer_hostgroup, reader_hostgroup, safe_comment, safe_check_type); //fprintf(stderr, "%s\n", query); admindb->execute(query); if (o != o1) free(o); free(o1); if (t != t1) free(t); free(t1); - free(query); + l_free(0, query); rows++; } } @@ -2202,66 +2331,45 @@ int ProxySQL_Config::Read_PgSQL_Servers_from_configfile(std::string& error) { std::string fields = ""; std::string values = ""; - auto process_field = [&](const std::string &field_name, const std::string &field_value, int is_int) { - if (!is_first_field) { - fields += ", "; - values += ", "; - } - else { - is_first_field = false; - } - fields += field_name; - if (is_int) { - values += field_value; - } - else { - char *cs = strdup(field_value.c_str()); - char *ecs = escape_string_single_quotes(cs, false); - values += std::string("'") + ecs + "'"; - if (cs != ecs) free(cs); - free(ecs); - } - }; - if (hostgroup_attributes.lookupValue("hostgroup_id", integer_val)) { - process_field("hostgroup_id", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "hostgroup_id", to_string(integer_val), true); } else { proxy_error("Admin: detected a pgsql_hostgroup_attributes in config file without a mandatory hostgroup_id.\n"); continue; } if (hostgroup_attributes.lookupValue("max_num_online_servers", integer_val)) { - process_field("max_num_online_servers", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "max_num_online_servers", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("autocommit", integer_val)) { - process_field("autocommit", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "autocommit", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("free_connections_pct", integer_val)) { - process_field("free_connections_pct", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "free_connections_pct", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("multiplex", integer_val)) { - process_field("multiplex", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "multiplex", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("connection_warming", integer_val)) { - process_field("connection_warming", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "connection_warming", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("throttle_connections_per_sec", integer_val)) { - process_field("throttle_connections_per_sec", to_string(integer_val), true); + append_config_field(fields, values, is_first_field, "throttle_connections_per_sec", to_string(integer_val), true); } if (hostgroup_attributes.lookupValue("init_connect", string_val)) { - process_field("init_connect", string_val, false); + append_config_field(fields, values, is_first_field, "init_connect", string_val, false); } if (hostgroup_attributes.lookupValue("ignore_session_variables", string_val)) { - process_field("ignore_session_variables", string_val, false); + append_config_field(fields, values, is_first_field, "ignore_session_variables", string_val, false); } if (hostgroup_attributes.lookupValue("hostgroup_settings", string_val)) { - process_field("hostgroup_settings", string_val, false); + append_config_field(fields, values, is_first_field, "hostgroup_settings", string_val, false); } if (hostgroup_attributes.lookupValue("servers_defaults", string_val)) { - process_field("servers_defaults", string_val, false); + append_config_field(fields, values, is_first_field, "servers_defaults", string_val, false); } if (hostgroup_attributes.lookupValue("comment", string_val)) { - process_field("comment", string_val, false); + append_config_field(fields, values, is_first_field, "comment", string_val, false); } std::string s_query = "INSERT OR REPLACE INTO pgsql_hostgroup_attributes ("; @@ -2278,6 +2386,7 @@ int ProxySQL_Config::Read_PgSQL_Servers_from_configfile(std::string& error) { const Setting &pgsql_servers_ssl_params = root["pgsql_servers_ssl_params"]; int count = pgsql_servers_ssl_params.getLength(); char *q=(char *)"INSERT OR REPLACE INTO pgsql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_crl, ssl_crlpath, ssl_protocol_version_range, comment) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')"; + const size_t q_len = safe_strlen(q); for (i=0; i< count; i++) { const Setting &line = pgsql_servers_ssl_params[i]; string hostname = ""; @@ -2305,18 +2414,28 @@ int ProxySQL_Config::Read_PgSQL_Servers_from_configfile(std::string& error) { line.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); + const size_t hostname_len = hostname.length(); + const size_t username_len = username.length(); + const size_t ssl_ca_len = ssl_ca.length(); + const size_t ssl_cert_len = ssl_cert.length(); + const size_t ssl_key_len = ssl_key.length(); + const size_t ssl_crl_len = ssl_crl.length(); + const size_t ssl_crlpath_len = ssl_crlpath.length(); + const size_t ssl_protocol_version_range_len = ssl_protocol_version_range.length(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); size_t query_len = ( - strlen(q) - + hostname.length() + username.length() - + ssl_ca.length() + ssl_cert.length() + ssl_key.length() - + ssl_crl.length() + ssl_crlpath.length() + ssl_protocol_version_range.length() + strlen(o) + 64 + q_len + + hostname_len + username_len + + ssl_ca_len + ssl_cert_len + ssl_key_len + + ssl_crl_len + ssl_crlpath_len + ssl_protocol_version_range_len + escaped_comment_len + 64 ); - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, hostname.c_str(), port, username.c_str(), ssl_ca.c_str(), ssl_cert.c_str(), ssl_key.c_str(), ssl_crl.c_str(), ssl_crlpath.c_str(), ssl_protocol_version_range.c_str(), o); + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, hostname.c_str(), port, username.c_str(), ssl_ca.c_str(), ssl_cert.c_str(), ssl_key.c_str(), ssl_crl.c_str(), ssl_crlpath.c_str(), ssl_protocol_version_range.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -2409,12 +2528,19 @@ int ProxySQL_Config::Read_PgSQL_Users_from_configfile(std::string& error) { user.lookupValue("comment", comment); char* o1 = strdup(comment.c_str()); char* o = escape_string_single_quotes(o1, false); - char* query = (char*)malloc(strlen(q) + strlen(username.c_str()) + strlen(password.c_str()) + strlen(o) + strlen(attributes.c_str()) + 128); - sprintf(query, q, username.c_str(), password.c_str(), active, use_ssl, default_hostgroup, transaction_persistent, fast_forward, max_connections, attributes.c_str(), o); + const char* safe_comment = o ? o : ""; + const size_t query_base_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t password_len = password.size(); + const size_t safe_comment_len = safe_strlen(safe_comment); + const size_t attributes_len = attributes.size(); + const size_t query_len = query_base_len + username_len + password_len + safe_comment_len + attributes_len + 128; + char* query = (char*)l_alloc(query_len); + format_query(query, query_len, q, username.c_str(), password.c_str(), active, use_ssl, default_hostgroup, transaction_persistent, fast_forward, max_connections, attributes.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -2622,45 +2748,66 @@ int ProxySQL_Config::Read_PgSQL_Query_Rules_from_configfile() { //if (user.lookupValue("default_schema", default_schema)==false) default_schema=""; - int query_len = 0; - query_len += strlen(q) + - strlen(std::to_string(rule_id).c_str()) + - strlen(std::to_string(active).c_str()) + - (username_exists ? strlen(username.c_str()) : 0) + 4 + - (database_exists ? strlen(database.c_str()) : 0) + 4 + - strlen(std::to_string(flagIN).c_str()) + 4 + - - (client_addr_exists ? strlen(client_addr.c_str()) : 0) + 4 + - (proxy_addr_exists ? strlen(proxy_addr.c_str()) : 0) + 4 + - strlen(std::to_string(proxy_port).c_str()) + 4 + - - (match_digest_exists ? strlen(match_digest.c_str()) : 0) + 4 + - (match_pattern_exists ? strlen(match_pattern.c_str()) : 0) + 4 + - strlen(std::to_string(negate_match_pattern).c_str()) + 4 + - (re_modifiers_exists ? strlen(re_modifiers.c_str()) : 0) + 4 + - strlen(std::to_string(flagOUT).c_str()) + 4 + - (replace_pattern_exists ? strlen(replace_pattern.c_str()) : 0) + 4 + - strlen(std::to_string(destination_hostgroup).c_str()) + 4 + - strlen(std::to_string(cache_ttl).c_str()) + 4 + - strlen(std::to_string(cache_empty_result).c_str()) + 4 + - strlen(std::to_string(cache_timeout).c_str()) + 4 + - strlen(std::to_string(reconnect).c_str()) + 4 + - strlen(std::to_string(timeout).c_str()) + 4 + - strlen(std::to_string(next_query_flagIN).c_str()) + 4 + - strlen(std::to_string(mirror_flagOUT).c_str()) + 4 + - strlen(std::to_string(mirror_hostgroup).c_str()) + 4 + - strlen(std::to_string(retries).c_str()) + 4 + - strlen(std::to_string(delay).c_str()) + 4 + - (error_msg_exists ? strlen(error_msg.c_str()) : 0) + 4 + - (OK_msg_exists ? strlen(OK_msg.c_str()) : 0) + 4 + - strlen(std::to_string(sticky_conn).c_str()) + 4 + - strlen(std::to_string(multiplex).c_str()) + 4 + - strlen(std::to_string(log).c_str()) + 4 + - strlen(std::to_string(apply).c_str()) + 4 + - (attributes_exists ? strlen(attributes.c_str()) : 0) + 4 + - (comment_exists ? strlen(comment.c_str()) : 0) + 4 + + const std::string rule_id_str = std::to_string(rule_id); + const std::string active_str = std::to_string(active); + const std::string flagIN_str = std::to_string(flagIN); + const std::string proxy_port_str = std::to_string(proxy_port); + const std::string negate_match_pattern_str = std::to_string(negate_match_pattern); + const std::string flagOUT_str = std::to_string(flagOUT); + const std::string destination_hostgroup_str = std::to_string(destination_hostgroup); + const std::string cache_ttl_str = std::to_string(cache_ttl); + const std::string cache_empty_result_str = std::to_string(cache_empty_result); + const std::string cache_timeout_str = std::to_string(cache_timeout); + const std::string reconnect_str = std::to_string(reconnect); + const std::string timeout_str = std::to_string(timeout); + const std::string next_query_flagIN_str = std::to_string(next_query_flagIN); + const std::string mirror_flagOUT_str = std::to_string(mirror_flagOUT); + const std::string mirror_hostgroup_str = std::to_string(mirror_hostgroup); + const std::string retries_str = std::to_string(retries); + const std::string delay_str = std::to_string(delay); + const std::string sticky_conn_str = std::to_string(sticky_conn); + const std::string multiplex_str = std::to_string(multiplex); + const std::string log_str = std::to_string(log); + const std::string apply_str = std::to_string(apply); + const size_t q_len = safe_strlen(q); + size_t query_len = + q_len + + rule_id_str.size() + + active_str.size() + + flagIN_str.size() + + (username_exists ? username.size() : 0) + 4 + + (database_exists ? database.size() : 0) + 4 + + (client_addr_exists ? client_addr.size() : 0) + 4 + + (proxy_addr_exists ? proxy_addr.size() : 0) + 4 + + proxy_port_str.size() + 4 + + (digest_exists ? digest.size() : 0) + 4 + + (match_digest_exists ? match_digest.size() : 0) + 4 + + (match_pattern_exists ? match_pattern.size() : 0) + 4 + + negate_match_pattern_str.size() + 4 + + (re_modifiers_exists ? re_modifiers.size() : 0) + 4 + + flagOUT_str.size() + 4 + + (replace_pattern_exists ? replace_pattern.size() : 0) + 4 + + destination_hostgroup_str.size() + 4 + + cache_ttl_str.size() + 4 + + cache_empty_result_str.size() + 4 + + cache_timeout_str.size() + 4 + + reconnect_str.size() + 4 + + timeout_str.size() + 4 + + next_query_flagIN_str.size() + 4 + + mirror_flagOUT_str.size() + 4 + + mirror_hostgroup_str.size() + 4 + + retries_str.size() + 4 + + delay_str.size() + 4 + + (error_msg_exists ? error_msg.size() : 0) + 4 + + (OK_msg_exists ? OK_msg.size() : 0) + 4 + + sticky_conn_str.size() + 4 + + multiplex_str.size() + 4 + + log_str.size() + 4 + + apply_str.size() + 4 + + (attributes_exists ? attributes.size() : 0) + 4 + + (comment_exists ? comment.size() : 0) + 4 + 64; - char* query = (char*)malloc(query_len); + char* query = (char*)l_alloc(query_len); if (username_exists) username = "\"" + username + "\""; else @@ -2717,7 +2864,7 @@ int ProxySQL_Config::Read_PgSQL_Query_Rules_from_configfile() { comment = "NULL"; - sprintf(query, q, + format_query(query, query_len, q, rule_id, active, username.c_str(), database.c_str(), @@ -2754,7 +2901,7 @@ int ProxySQL_Config::Read_PgSQL_Query_Rules_from_configfile() { ); //fprintf(stderr, "%s\n", query); admindb->execute(query); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -2896,13 +3043,18 @@ int ProxySQL_Config::Read_MySQL_Query_Rules_Fast_Routing_from_configfile() { rule.lookupValue("comment", comment); char *o1 = strdup(comment.c_str()); char *o = escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(schemaname.c_str()) + strlen(o) + 64; - char *query = (char *)malloc(query_len); - snprintf(query, query_len, q, username.c_str(), schemaname.c_str(), flagIN, destination_hostgroup, o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t schemaname_len = schemaname.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + schemaname_len + escaped_comment_len + 64; + char *query = (char *)l_alloc(query_len); + format_query(query, query_len, q, username.c_str(), schemaname.c_str(), flagIN, destination_hostgroup, safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -2932,13 +3084,18 @@ int ProxySQL_Config::Read_PgSQL_Query_Rules_Fast_Routing_from_configfile() { rule.lookupValue("comment", comment); char *o1 = strdup(comment.c_str()); char *o = escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(database.c_str()) + strlen(o) + 64; - char *query = (char *)malloc(query_len); - snprintf(query, query_len, q, username.c_str(), database.c_str(), flagIN, destination_hostgroup, o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t database_len = database.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + database_len + escaped_comment_len + 64; + char *query = (char *)l_alloc(query_len); + format_query(query, query_len, q, username.c_str(), database.c_str(), flagIN, destination_hostgroup, safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } admindb->execute("PRAGMA foreign_keys = ON"); @@ -2968,13 +3125,19 @@ int ProxySQL_Config::Read_MySQL_Firewall_from_configfile() { u.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(client_address.c_str()) + strlen(mode.c_str()) + strlen(o) + 32; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, username.c_str(), client_address.c_str(), mode.c_str(), o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t client_address_len = client_address.size(); + const size_t mode_len = mode.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + client_address_len + mode_len + escaped_comment_len + 32; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, username.c_str(), client_address.c_str(), mode.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -3001,13 +3164,20 @@ int ProxySQL_Config::Read_MySQL_Firewall_from_configfile() { r.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(client_address.c_str()) + strlen(schemaname.c_str()) + strlen(digest.c_str()) + strlen(o) + 64; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, username.c_str(), client_address.c_str(), schemaname.c_str(), flagIN, digest.c_str(), o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t client_address_len = client_address.size(); + const size_t schemaname_len = schemaname.size(); + const size_t digest_len = digest.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + client_address_len + schemaname_len + digest_len + escaped_comment_len + 64; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, username.c_str(), client_address.c_str(), schemaname.c_str(), flagIN, digest.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -3022,11 +3192,13 @@ int ProxySQL_Config::Read_MySQL_Firewall_from_configfile() { std::string fingerprint=""; f.lookupValue("active", active); f.lookupValue("fingerprint", fingerprint); - size_t query_len = strlen(q) + strlen(fingerprint.c_str()) + 16; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, fingerprint.c_str()); + const size_t q_len = safe_strlen(q); + const size_t fingerprint_len = fingerprint.size(); + size_t query_len = q_len + fingerprint_len + 16; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, fingerprint.c_str()); admindb->execute(query); - free(query); + l_free(0, query); rows++; } } @@ -3058,13 +3230,19 @@ int ProxySQL_Config::Read_PgSQL_Firewall_from_configfile() { u.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(client_address.c_str()) + strlen(mode.c_str()) + strlen(o) + 32; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, username.c_str(), client_address.c_str(), mode.c_str(), o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t client_address_len = client_address.size(); + const size_t mode_len = mode.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + client_address_len + mode_len + escaped_comment_len + 32; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, username.c_str(), client_address.c_str(), mode.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -3091,13 +3269,20 @@ int ProxySQL_Config::Read_PgSQL_Firewall_from_configfile() { r.lookupValue("comment", comment); char *o1=strdup(comment.c_str()); char *o=escape_string_single_quotes(o1, false); - size_t query_len = strlen(q) + strlen(username.c_str()) + strlen(client_address.c_str()) + strlen(database.c_str()) + strlen(digest.c_str()) + strlen(o) + 64; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, username.c_str(), client_address.c_str(), database.c_str(), flagIN, digest.c_str(), o); + const size_t q_len = safe_strlen(q); + const size_t username_len = username.size(); + const size_t client_address_len = client_address.size(); + const size_t database_len = database.size(); + const size_t digest_len = digest.size(); + const char* safe_comment = o ? o : ""; + const size_t escaped_comment_len = safe_strlen(safe_comment); + size_t query_len = q_len + username_len + client_address_len + database_len + digest_len + escaped_comment_len + 64; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, username.c_str(), client_address.c_str(), database.c_str(), flagIN, digest.c_str(), safe_comment); admindb->execute(query); if (o != o1) free(o); free(o1); - free(query); + l_free(0, query); rows++; } } @@ -3112,11 +3297,13 @@ int ProxySQL_Config::Read_PgSQL_Firewall_from_configfile() { std::string fingerprint=""; f.lookupValue("active", active); f.lookupValue("fingerprint", fingerprint); - size_t query_len = strlen(q) + strlen(fingerprint.c_str()) + 16; - char *query=(char *)malloc(query_len); - snprintf(query, query_len, q, active, fingerprint.c_str()); + const size_t q_len = safe_strlen(q); + const size_t fingerprint_len = fingerprint.size(); + size_t query_len = q_len + fingerprint_len + 16; + char *query=(char *)l_alloc(query_len); + format_query(query, query_len, q, active, fingerprint.c_str()); admindb->execute(query); - free(query); + l_free(0, query); rows++; } } diff --git a/lib/QP_query_digest_stats.cpp b/lib/QP_query_digest_stats.cpp index 8bea932d30..ec961562e3 100644 --- a/lib/QP_query_digest_stats.cpp +++ b/lib/QP_query_digest_stats.cpp @@ -25,6 +25,19 @@ static void my_itoa(char s[], unsigned long long n) reverse(s); } +static char *store_or_duplicate_query_digest_value(char *fixed_buf, size_t fixed_buf_len, const char *input) { + if (input == NULL) { + return NULL; + } + size_t input_len = std::string_view(input).size(); + if (input_len < fixed_buf_len) { + memcpy(fixed_buf, input, input_len); + fixed_buf[input_len] = '\0'; + return fixed_buf; + } + return strdup(input); +} + QP_query_digest_stats::QP_query_digest_stats(const char* _user, const char* _schema, uint64_t _digest, const char* _digest_text, int _hid, const char* _client_addr, int query_digests_max_digest_length) { @@ -33,24 +46,9 @@ QP_query_digest_stats::QP_query_digest_stats(const char* _user, const char* _sch if (_digest_text) { digest_text=strndup(_digest_text, query_digests_max_digest_length); } - if (strlen(_user) < sizeof(username_buf)) { - strcpy(username_buf, _user); - username = username_buf; - } else { - username = strdup(_user); - } - if (strlen(_schema) < sizeof(schemaname_buf)) { - strcpy(schemaname_buf, _schema); - schemaname = schemaname_buf; - } else { - schemaname = strdup(_schema); - } - if (strlen(_client_addr) < sizeof(client_address_buf)) { - strcpy(client_address_buf, _client_addr); - client_address = client_address_buf; - } else { - client_address = strdup(_client_addr); - } + username = store_or_duplicate_query_digest_value(username_buf, sizeof(username_buf), _user); + schemaname = store_or_duplicate_query_digest_value(schemaname_buf, sizeof(schemaname_buf), _schema); + client_address = store_or_duplicate_query_digest_value(client_address_buf, sizeof(client_address_buf), _client_addr); count_star = 0; first_seen = 0; last_seen = 0; diff --git a/lib/c_tokenizer.cpp b/lib/c_tokenizer.cpp index 9e696406d5..fe53de7861 100644 --- a/lib/c_tokenizer.cpp +++ b/lib/c_tokenizer.cpp @@ -12,21 +12,30 @@ extern __thread int mysql_thread___query_digests_grouping_limit; extern __thread int mysql_thread___query_digests_groups_grouping_limit; extern __thread bool mysql_thread___query_digests_keep_comment; +static inline size_t tokenizer_strlen(const char* s) { + size_t len = 0; + if (s == NULL) return 0; + while (s[len]) { + ++len; + } + return len; +} + void tokenizer(tokenizer_t *result, const char* s, const char* delimiters, int empties ) { //tokenizer_t result; - result->s_length = ( (s && delimiters) ? strlen(s) : 0 ); - result->s = NULL; - if (result->s_length) { + result->s_length = ( (s && delimiters) ? tokenizer_strlen(s) : 0 ); + result->s = NULL; + if (result->s_length) { if (result->s_length > (PROXYSQL_TOKENIZER_BUFFSIZE-1)) { result->s = strdup(s); } else { - strcpy(result->buffer,s); + snprintf(result->buffer, sizeof(result->buffer), "%.*s", (int)result->s_length, s); result->s = result->buffer; } - } + } result->delimiters = delimiters; result->current = NULL; result->next = result->s; @@ -37,7 +46,7 @@ void tokenizer(tokenizer_t *result, const char* s, const char* delimiters, int e const char* free_tokenizer( tokenizer_t* tokenizer ) { - if (tokenizer->s_length > (PROXYSQL_TOKENIZER_BUFFSIZE-1)) { + if (tokenizer->s && tokenizer->s != tokenizer->buffer) { free(tokenizer->s); } tokenizer->s = NULL; @@ -2641,4 +2650,3 @@ char* mysql_query_strip_comments(char *s, int _len, bool lowercase) { return r; } - diff --git a/lib/debug.cpp b/lib/debug.cpp index 842f92d477..af6ea00f44 100644 --- a/lib/debug.cpp +++ b/lib/debug.cpp @@ -242,14 +242,21 @@ extern "C" void proxy_debug_func( sscanf(strings[i], "%*[^(](%100[^+]", debugbuff); int status; char *realname=NULL; - realname=abi::__cxa_demangle(debugbuff, 0, 0, &status); - if (realname) { - sprintf(debugbuff," ---- %s : %s\n", strings[i], realname); - strcat(longdebugbuff2,debugbuff); + realname=abi::__cxa_demangle(debugbuff, 0, 0, &status); + if (realname && strnlen(longdebugbuff2, sizeof(longdebugbuff2)) < sizeof(longdebugbuff2) - 1) { + size_t longdebugbuff2_len = strnlen(longdebugbuff2, sizeof(longdebugbuff2)); + snprintf( + longdebugbuff2 + longdebugbuff2_len, + sizeof(longdebugbuff2) - longdebugbuff2_len, + " ---- %s : %s\n", + strings[i], + realname + ); + } + free(realname); // NOSONAR: __cxa_demangle returns memory allocated by malloc. } + free(strings); } - free(strings); - } #endif pthread_mutex_lock(&debug_mutex); if (debugdb_disk == NULL) { diff --git a/lib/gen_utils.cpp b/lib/gen_utils.cpp index 96febcabb1..57f84a9cb8 100644 --- a/lib/gen_utils.cpp +++ b/lib/gen_utils.cpp @@ -8,10 +8,19 @@ using std::vector; using std::unique_ptr; +static inline size_t util_strlen(const char* s) { + size_t len = 0; + if (s == NULL) return 0; + while (s[len]) { + ++len; + } + return len; +} + char *escape_string_single_quotes(char *input, bool free_it) { int i,j,l; char *o=NULL; // output string, if any - l=strlen(input); + l=util_strlen(input); j=0; for (i=0;i str && isspace(*end)) end--; // Write new null terminator @@ -106,7 +116,8 @@ char *trim_spaces_and_quotes_in_place(char *str) { if(*str == 0) // All spaces? return str; // Trim trailing space - end = str + strlen(str) - 1; + const size_t str_len = util_strlen(str); + end = str + str_len - 1; while(end > str && (isspace(*end) || *end=='\"' || *end=='\'' || *end==';')) end--; // Write new null terminator *(end+1) = 0; @@ -412,13 +423,20 @@ time_t realtime_to_monotonic_time(time_t rt) { */ std::string strip_schema_from_query(const char* query, const char* schema, const std::vector& tables, bool ansi_quotes) { - if (!query || strlen(query) == 0) { + if (!query) { + return ""; + } + + const int query_len = static_cast(util_strlen(query)); + if (query_len == 0) { return ""; } - int query_len = strlen(query); + if (schema == NULL) { + return std::string(query, query_len); + } - int schema_len = strlen(schema); + int schema_len = static_cast(util_strlen(schema)); if (schema_len == 0) { return std::string(query, query_len); } diff --git a/lib/network.cpp b/lib/network.cpp index d62d75fb5b..d74d3c36ab 100644 --- a/lib/network.cpp +++ b/lib/network.cpp @@ -88,6 +88,20 @@ int listen_on_unix(char *path, int backlog) { int sd; int r; + if (path == nullptr) { + errno = EINVAL; + proxy_error("Cannot listen on a null Unix Socket path\n"); + return -1; + } + + const size_t path_len = strnlen(path, sizeof(serveraddr.sun_path)); + if (path_len >= sizeof(serveraddr.sun_path)) { + errno = ENAMETOOLONG; + proxy_error("Unix Socket path is too long: %.*s\n", + static_cast(path_len), path); + return -1; + } + // remove the socket r=unlink(path); if ( (r==-1) && (errno!=ENOENT) ) { @@ -104,7 +118,7 @@ int listen_on_unix(char *path, int backlog) { memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sun_family = AF_UNIX; - strncpy(serveraddr.sun_path, path, sizeof(serveraddr.sun_path) - 1); + memcpy(serveraddr.sun_path, path, path_len + 1); // call bind() to bind the socket on the specified file if ( bind(sd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_un)) != 0 ) { diff --git a/lib/proxy_protocol_info.cpp b/lib/proxy_protocol_info.cpp index d078092d3f..cfcaedfee7 100644 --- a/lib/proxy_protocol_info.cpp +++ b/lib/proxy_protocol_info.cpp @@ -259,22 +259,20 @@ bool ProxyProtocolInfo::is_in_network(const struct sockaddr* client_addr, const bool ProxyProtocolInfo::is_client_in_any_subnet(const struct sockaddr* client_addr, const char* subnet_list) { // Create a copy of the subnet list to avoid modifying the original string - char* subnet_list_copy = new char[strlen(subnet_list) + 1]; - strcpy(subnet_list_copy, subnet_list); + std::string subnet_list_copy(subnet_list); - char* token = strtok(subnet_list_copy, ","); // Get the first subnet + char* saveptr = nullptr; + char* token = strtok_r(&subnet_list_copy[0], ",", &saveptr); // Get the first subnet while (token != NULL) { if (DEBUG_ProxyProtocolInfo==true) std::cout << "Checking subnet: " << token << std::endl; if (is_in_network(client_addr, token)) { if (DEBUG_ProxyProtocolInfo==true) std::cout << "Client is in subnet: " << token << std::endl; - delete[] subnet_list_copy; // Deallocate the copy return true; // Client is in at least one subnet } - token = strtok(NULL, ","); // Get the next subnet + token = strtok_r(nullptr, ",", &saveptr); // Get the next subnet } - delete[] subnet_list_copy; // Deallocate the copy return false; // Client is not in any of the subnets } @@ -368,21 +366,19 @@ bool ProxyProtocolInfo::is_valid_subnet_list(const char* subnet_list) { } // Create a copy of the string to avoid modifying the original - char* subnet_list_copy = new char[strlen(subnet_list) + 1]; - strcpy(subnet_list_copy, subnet_list); + std::string subnet_list_copy(subnet_list); // Tokenize the string using ',' as the delimiter - char* token = strtok(subnet_list_copy, ","); + char* saveptr = nullptr; + char* token = strtok_r(&subnet_list_copy[0], ",", &saveptr); while (token != NULL) { // Check if the token is a valid subnet if (!is_valid_subnet(token)) { - delete[] subnet_list_copy; // Deallocate the copy return false; // Invalid subnet found } - token = strtok(NULL, ","); // Get the next token + token = strtok_r(nullptr, ",", &saveptr); // Get the next token } - delete[] subnet_list_copy; // Deallocate the copy return true; // All subnets are valid } diff --git a/lib/proxysql_find_charset.cpp b/lib/proxysql_find_charset.cpp index a28556877d..456aa215e4 100644 --- a/lib/proxysql_find_charset.cpp +++ b/lib/proxysql_find_charset.cpp @@ -7,6 +7,7 @@ #include "proxysql_structs.h" /////////////////////////////////////////////////////////////////////////////// +#include #include const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr) { @@ -88,11 +89,10 @@ MARIADB_CHARSET_INFO * proxysql_find_charset_collate_names(const char *csname_, } else { csname = csname_; } - if (strncasecmp(collatename_,(const char *)"utf8mb3", 7)==0) { - memcpy(buf,(const char *)"utf8",4); - strcpy(buf+4,collatename_+7); - collatename = buf; - } else { + if (strncasecmp(collatename_,(const char *)"utf8mb3", 7)==0) { + snprintf(buf, sizeof(buf), "utf8%s", collatename_ + 7); + collatename = buf; + } else { collatename = collatename_; } do { diff --git a/lib/proxysql_utils.cpp b/lib/proxysql_utils.cpp index 3e92bb338b..c27defdba2 100644 --- a/lib/proxysql_utils.cpp +++ b/lib/proxysql_utils.cpp @@ -873,7 +873,7 @@ std::string mysql_result_to_string(MYSQL_RES* result) { std::vector widths(num_fields); for (int i = 0; i < num_fields; i++) { - widths[i] = strlen(fields[i].name); + widths[i] = fields[i].name_length; } for (const auto& r : rows) { for (int i = 0; i < num_fields; i++) { @@ -897,8 +897,9 @@ std::string mysql_result_to_string(MYSQL_RES* result) { append_border(); s = "|"; for (int i = 0; i < num_fields; i++) { - size_t len = strlen(fields[i].name); - s += " "; s += fields[i].name; + const char* safe_name = fields[i].name ? fields[i].name : ""; + const size_t len = fields[i].name_length; + s += " "; s += safe_name; for (size_t j = 0; j < widths[i] - len + 1; j++) s += " "; s += "|"; } diff --git a/plugins/genai/include/MCP_Thread.h b/plugins/genai/include/MCP_Thread.h index b91168b375..a8d443dfa9 100644 --- a/plugins/genai/include/MCP_Thread.h +++ b/plugins/genai/include/MCP_Thread.h @@ -270,7 +270,9 @@ class MCP_Threads_Handler * * @param name The name of the variable (without 'mcp-' prefix) * @param val Output buffer to store the value - * @return 0 on success, -1 if variable not found + * @param val_size Size of the output buffer in bytes + * @return 0 on success, -1 if the variable is unknown, the arguments are + * null/invalid, or the value does not fit in `val_size` bytes * * @deprecated The unbounded sprintf into `val` is a stack-buffer * overflow risk for variables that hold arbitrary-length values @@ -278,7 +280,7 @@ class MCP_Threads_Handler * operators). Prefer `get_variable_string()` below. Retained * for callers that haven't been updated yet. */ - int get_variable(const char* name, char* val); + int get_variable(const char* name, char* val, size_t val_size); /** * @brief Get the value of a variable as a std::string. diff --git a/plugins/genai/src/AI_Features_Manager.cpp b/plugins/genai/src/AI_Features_Manager.cpp index b1198959bb..7e7ea3aa00 100644 --- a/plugins/genai/src/AI_Features_Manager.cpp +++ b/plugins/genai/src/AI_Features_Manager.cpp @@ -43,7 +43,8 @@ int AI_Features_Manager::init_vector_db() { proxy_info("AI: Initializing vector storage at %s\n", GloGATH->variables.genai_vector_db_path); // Ensure directory exists - std::string path_copy(GloGATH->variables.genai_vector_db_path); + std::string db_path(GloGATH->variables.genai_vector_db_path); + std::string path_copy = db_path; char* dir = dirname(&path_copy[0]); struct stat st; if (stat(dir, &st) != 0) { @@ -64,10 +65,7 @@ int AI_Features_Manager::init_vector_db() { } vector_db = new SQLite3DB(); - char path_buf[512]; - strncpy(path_buf, GloGATH->variables.genai_vector_db_path, sizeof(path_buf) - 1); - path_buf[sizeof(path_buf) - 1] = '\0'; - int rc = vector_db->open(path_buf, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + int rc = vector_db->open(&db_path[0], SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); if (rc != SQLITE_OK) { proxy_error("AI: Failed to open vector database: %s\n", GloGATH->variables.genai_vector_db_path); delete vector_db; diff --git a/plugins/genai/src/Discovery_Schema.cpp b/plugins/genai/src/Discovery_Schema.cpp index e72d9a06e2..c4f6433a7c 100644 --- a/plugins/genai/src/Discovery_Schema.cpp +++ b/plugins/genai/src/Discovery_Schema.cpp @@ -56,9 +56,8 @@ Discovery_Schema::~Discovery_Schema() { int Discovery_Schema::init() { // Initialize database connection db = new SQLite3DB(); - char path_buf[db_path.size() + 1]; - strcpy(path_buf, db_path.c_str()); - int rc = db->open(path_buf, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + std::string path_buf = db_path; + int rc = db->open(&path_buf[0], SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); if (rc != SQLITE_OK) { proxy_error("Failed to open discovery catalog database at %s: %d\n", db_path.c_str(), rc); return -1; diff --git a/plugins/genai/src/MCP_Thread.cpp b/plugins/genai/src/MCP_Thread.cpp index ceace02026..881b4b896d 100644 --- a/plugins/genai/src/MCP_Thread.cpp +++ b/plugins/genai/src/MCP_Thread.cpp @@ -168,51 +168,21 @@ void MCP_Threads_Handler::wrunlock() { pthread_rwlock_unlock(&rwlock); } -int MCP_Threads_Handler::get_variable(const char* name, char* val) { - if (!name || !val) +int MCP_Threads_Handler::get_variable(const char* name, char* val, size_t val_size) { + if (!name || !val || val_size == 0) return -1; - pthread_rwlock_rdlock(&rwlock); - std::string out; - int rc = 0; - if (!strcmp(name, "enabled")) { - out = variables.mcp_enabled ? "true" : "false"; - } else if (!strcmp(name, "port")) { - out = std::to_string(variables.mcp_port); - } else if (!strcmp(name, "use_ssl")) { - out = variables.mcp_use_ssl ? "true" : "false"; - } else if (!strcmp(name, "config_endpoint_auth")) { - out = variables.mcp_config_endpoint_auth ? variables.mcp_config_endpoint_auth : ""; - } else if (!strcmp(name, "stats_endpoint_auth")) { - out = variables.mcp_stats_endpoint_auth ? variables.mcp_stats_endpoint_auth : ""; - } else if (!strcmp(name, "query_endpoint_auth")) { - out = variables.mcp_query_endpoint_auth ? variables.mcp_query_endpoint_auth : ""; - } else if (!strcmp(name, "admin_endpoint_auth")) { - out = variables.mcp_admin_endpoint_auth ? variables.mcp_admin_endpoint_auth : ""; - } else if (!strcmp(name, "cache_endpoint_auth")) { - out = variables.mcp_cache_endpoint_auth ? variables.mcp_cache_endpoint_auth : ""; - } else if (!strcmp(name, "ai_endpoint_auth")) { - out = variables.mcp_ai_endpoint_auth ? variables.mcp_ai_endpoint_auth : ""; - } else if (!strcmp(name, "rag_endpoint_auth")) { - out = variables.mcp_rag_endpoint_auth ? variables.mcp_rag_endpoint_auth : ""; - } else if (!strcmp(name, "timeout_ms")) { - out = std::to_string(variables.mcp_timeout_ms); - } else if (!strcmp(name, "stats_show_queries_max_rows")) { - out = std::to_string(variables.mcp_stats_show_queries_max_rows); - } else if (!strcmp(name, "stats_show_processlist_max_rows")) { - out = std::to_string(variables.mcp_stats_show_processlist_max_rows); - } else if (!strcmp(name, "stats_enable_debug_tools")) { - out = variables.mcp_stats_enable_debug_tools ? "true" : "false"; - } else { - rc = -1; - } - pthread_rwlock_unlock(&rwlock); + if (!get_variable_string(name, out)) + return -1; - if (rc == 0) { - sprintf(val, "%s", out.c_str()); + if (out.size() >= val_size) { + val[0] = '\0'; + return -1; } - return rc; + + memcpy(val, out.c_str(), out.size() + 1); + return 0; } int MCP_Threads_Handler::set_variable(const char* name, const char* value) { diff --git a/plugins/genai/src/MySQL_Catalog.cpp b/plugins/genai/src/MySQL_Catalog.cpp index c40da19077..a2a9932f12 100644 --- a/plugins/genai/src/MySQL_Catalog.cpp +++ b/plugins/genai/src/MySQL_Catalog.cpp @@ -26,6 +26,7 @@ #include "proxysql.h" #include #include +#include #include "../deps/json/json.hpp" // ============================================================ @@ -55,9 +56,8 @@ MySQL_Catalog::~MySQL_Catalog() { int MySQL_Catalog::init() { // Initialize database connection db = new SQLite3DB(); - char path_buf[db_path.size() + 1]; - strcpy(path_buf, db_path.c_str()); - int rc = db->open(path_buf, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + std::string path_buf = db_path; + int rc = db->open(&path_buf[0], SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); if (rc != SQLITE_OK) { proxy_error("Failed to open catalog database at %s: %d\n", db_path.c_str(), rc); return -1; diff --git a/plugins/genai/src/MySQL_FTS.cpp b/plugins/genai/src/MySQL_FTS.cpp index 01021ddd12..621c5121f9 100644 --- a/plugins/genai/src/MySQL_FTS.cpp +++ b/plugins/genai/src/MySQL_FTS.cpp @@ -26,9 +26,8 @@ MySQL_FTS::~MySQL_FTS() { int MySQL_FTS::init() { // Initialize database connection db = new SQLite3DB(); - std::vector path_buf(db_path.size() + 1); - strcpy(path_buf.data(), db_path.c_str()); - int rc = db->open(path_buf.data(), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + std::string path_buf = db_path; + int rc = db->open(&path_buf[0], SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); if (rc != SQLITE_OK) { proxy_error("Failed to open FTS database at %s: %d\n", db_path.c_str(), rc); delete db; diff --git a/plugins/genai/src/tool_handlers/Config_Tool_Handler.cpp b/plugins/genai/src/tool_handlers/Config_Tool_Handler.cpp index c330a6038e..f8e91c8f16 100644 --- a/plugins/genai/src/tool_handlers/Config_Tool_Handler.cpp +++ b/plugins/genai/src/tool_handlers/Config_Tool_Handler.cpp @@ -420,8 +420,8 @@ json Config_Tool_Handler::handle_get_config(const std::string& var_name) { return create_error_response("MCP handler not initialized"); } - char val[1024]; - if (mcp_handler->get_variable(var_name.c_str(), val) == 0) { + std::string val; + if (mcp_handler->get_variable_string(var_name.c_str(), val)) { json result; result["variable_name"] = var_name; result["value"] = val; @@ -547,8 +547,8 @@ json Config_Tool_Handler::handle_list_variables(const std::string& filter) { } } - char val[1024]; - if (mcp_handler->get_variable(var_name.c_str(), val) == 0) { + std::string val; + if (mcp_handler->get_variable_string(var_name.c_str(), val)) { json var; var["name"] = var_name; var["value"] = val; diff --git a/src/SQLite3_Server.cpp b/src/SQLite3_Server.cpp index ee3ebb4085..d2e7d3414f 100644 --- a/src/SQLite3_Server.cpp +++ b/src/SQLite3_Server.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #ifndef SPOOKYV2 #include "SpookyV2.h" @@ -38,6 +39,22 @@ using std::string; +#if defined(TEST_AURORA) || defined(TEST_GALERA) || defined(TEST_GROUPREP) || defined(TEST_READONLY) || defined(TEST_REPLICATIONLAG) || defined(TEST_RDS_BGD) +static int random_replication_lag_seconds() { + static thread_local std::random_device random_source; + static thread_local std::uniform_int_distribution distribution(10, 39); + return distribution(random_source); +} +#endif + +#ifdef TEST_REPLICATIONLAG +static void ensure_replicationlag_table_loaded(SQLite3_Server* server, MySQL_Session* sess) { + if (server->replicationlag_map_size() == 0) { + server->load_replicationlag_table(sess); + } +} +#endif + #define SELECT_VERSION_COMMENT "select @@version_comment limit 1" #define SELECT_VERSION_COMMENT_LEN 32 #define SELECT_DB_USER "select DATABASE(), USER() limit 1" @@ -224,18 +241,41 @@ class sqlite3server_main_loop_listeners { bool update_ifaces(char *list, char ***_ifaces) { wrlock(); - int i; - char **ifaces=*_ifaces; + int i = 0; + char **old_ifaces = *_ifaces; + char **new_ifaces = (char **)l_alloc(MAX_IFACES * sizeof(char *)); + if (new_ifaces != NULL) { + memset(new_ifaces, 0, MAX_IFACES * sizeof(char *)); + } tokenizer_t tok; tokenizer( &tok, list, ";", TOKENIZER_NO_EMPTIES ); const char* token; - ifaces=reset_ifaces(ifaces); - i=0; + if (new_ifaces == NULL) { + free_tokenizer( &tok ); + wrunlock(); + return false; + } for ( token = tokenize( &tok ) ; token && i < MAX_IFACES ; token = tokenize( &tok ) ) { - ifaces[i]=(char *)malloc(strlen(token)+1); - strcpy(ifaces[i],token); - i++; + char *token_copy = strdup(token); + if (token_copy == NULL) { + for (int j = 0; j < i; ++j) { + l_free(0, new_ifaces[j]); + } + l_free(0, new_ifaces); + free_tokenizer( &tok ); + wrunlock(); + return false; + } + new_ifaces[i]=token_copy; + i++; + } + if (old_ifaces != NULL) { + for (int j = 0; j < MAX_IFACES; ++j) { + l_free(0, old_ifaces[j]); + } + l_free(0, old_ifaces); } + *_ifaces = new_ifaces; free_tokenizer( &tok ); version++; wrunlock(); @@ -245,6 +285,14 @@ class sqlite3server_main_loop_listeners { static sqlite3server_main_loop_listeners S_amll; +#if defined(TEST_READONLY) || defined(TEST_RDS_BGD) +static void ensure_readonly_table(SQLite3_Server *server, MySQL_Session *sess) { + if (server->readonly_map_size() == 0) { + server->load_readonly_table(sess); + } +} +#endif + #ifdef TEST_GROUPREP /** * @brief Helper function that checks if the supplied string @@ -374,6 +422,17 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p query=(char *)l_alloc(query_length); memcpy(query,(char *)pkt->ptr+sizeof(mysql_hdr)+1,query_length-1); query[query_length-1]=0; + constexpr size_t k_select_version_len = sizeof("SELECT @@version") - 1; + constexpr size_t k_select_version_fn_len = sizeof("SELECT version()") - 1; + constexpr size_t k_select_dollar_len = sizeof("SELECT $$") - 1; + constexpr size_t k_show_tables_len = sizeof("SHOW TABLES") - 1; + constexpr size_t k_show_tables_from_len = sizeof("SHOW TABLES FROM ") - 1; + constexpr size_t k_show_tables_like_len = sizeof("SHOW TABLES LIKE ") - 1; + constexpr size_t k_show_databases_len = sizeof("SHOW DATABASES") - 1; + constexpr size_t k_show_schemas_len = sizeof("SHOW SCHEMAS") - 1; + [[maybe_unused]] constexpr size_t k_select_read_only_len = sizeof("SELECT @@global.read_only read_only ") - 1; + [[maybe_unused]] constexpr size_t k_select_slave_status_len = sizeof("SELECT SLAVE STATUS ") - 1; + [[maybe_unused]] constexpr size_t k_select_replica_status_len = sizeof("SELECT REPLICA STATUS ") - 1; #if defined(TEST_AURORA) || defined(TEST_GALERA) || defined(TEST_GROUPREP) || defined(TEST_READONLY) || defined(TEST_REPLICATIONLAG) || defined(TEST_RDS_BGD) if (sess->client_myds->proxy_addr.addr == NULL) { @@ -572,9 +631,18 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p if (!strncasecmp(SELECT_VERSION_COMMENT, query_no_space, query_no_space_length)) { l_free(query_length,query); #if defined(TEST_AURORA) || defined(TEST_GALERA) || defined(TEST_GROUPREP) || defined(TEST_READONLY) || defined(TEST_REPLICATIONLAG) || defined(TEST_RDS_BGD) - char *a = (char *)"SELECT '(ProxySQL Automated Test Server) - %s'"; - query = (char *)malloc(strlen(a)+strlen(sess->client_myds->proxy_addr.addr)); - sprintf(query,a,sess->client_myds->proxy_addr.addr); + const char* proxy_addr = sess->client_myds->proxy_addr.addr; + const std::string formatted_query = cstr_format( + "SELECT '(ProxySQL Automated Test Server) - %s'", + proxy_addr ? proxy_addr : "" + ).str; + query = l_strdup(formatted_query.c_str()); + if (query == NULL) { + GloSQLite3Server->send_MySQL_ERR(&sess->client_myds->myprot, 1105, "Out of memory"); + run_query = false; + goto __run_query; + } + query_length = formatted_query.size() + 1; #else query=l_strdup("SELECT '(ProxySQL SQLite3 Server)'"); #endif // TEST_AURORA || TEST_GALERA || TEST_GROUPREP || TEST_READONLY || TEST_REPLICATIONLAG || TEST_RDS_BGD @@ -585,16 +653,23 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p if (query_no_space_length==SELECT_DB_USER_LEN) { if (!strncasecmp(SELECT_DB_USER, query_no_space, query_no_space_length)) { - l_free(query_length,query); - char *query1=(char *)"SELECT \"admin\" AS 'DATABASE()', \"%s\" AS 'USER()'"; - char *query2=(char *)malloc(strlen(query1)+strlen(sess->client_myds->myconn->userinfo->username)+10); - sprintf(query2,query1,sess->client_myds->myconn->userinfo->username); - query=l_strdup(query2); - query_length=strlen(query2)+1; - free(query2); - goto __run_query; + l_free(query_length,query); + query = NULL; + const char* username = sess->client_myds->myconn->userinfo->username; + const std::string formatted_query = cstr_format( + "SELECT \"admin\" AS 'DATABASE()', \"%s\" AS 'USER()'", + username ? username : "" + ).str; + query = l_strdup(formatted_query.c_str()); + if (query == NULL) { + GloSQLite3Server->send_MySQL_ERR(&sess->client_myds->myprot, 1105, "Out of memory"); + run_query = false; + goto __run_query; + } + query_length = formatted_query.size() + 1; + goto __run_query; + } } - } if (query_no_space_length==SELECT_CHARSET_VARIOUS_LEN) { if (!strncasecmp(SELECT_CHARSET_VARIOUS, query_no_space, query_no_space_length)) { @@ -606,26 +681,26 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p } } - if (!strncasecmp("SELECT @@version", query_no_space, strlen("SELECT @@version"))) { - l_free(query_length,query); - char *q=(char *)"SELECT '%s' AS '@@version'"; - query_length=strlen(q)+strlen(PROXYSQL_VERSION)+20; - query=(char *)l_alloc(query_length); - sprintf(query,q,PROXYSQL_VERSION); - goto __run_query; - } + if (!strncasecmp("SELECT @@version", query_no_space, k_select_version_len)) { + l_free(query_length,query); + char *q=(char *)"SELECT '%s' AS '@@version'"; + query_length=strlen(q)+strlen(PROXYSQL_VERSION)+20; + query=(char *)l_alloc(query_length); + snprintf(query, query_length, q, PROXYSQL_VERSION); + goto __run_query; + } - if (!strncasecmp("SELECT version()", query_no_space, strlen("SELECT version()"))) { - l_free(query_length,query); - char *q=(char *)"SELECT '%s' AS 'version()'"; - query_length=strlen(q)+strlen(PROXYSQL_VERSION)+20; - query=(char *)l_alloc(query_length); - sprintf(query,q,PROXYSQL_VERSION); - goto __run_query; - } + if (!strncasecmp("SELECT version()", query_no_space, k_select_version_fn_len)) { + l_free(query_length,query); + char *q=(char *)"SELECT '%s' AS 'version()'"; + query_length=strlen(q)+strlen(PROXYSQL_VERSION)+20; + query=(char *)l_alloc(query_length); + snprintf(query, query_length, q, PROXYSQL_VERSION); + goto __run_query; + } // MySQL client check command for dollars quote support, starting at version '8.1.0'. See #4300. - if (!strncasecmp("SELECT $$", query_no_space, strlen("SELECT $$"))) { + if (!strncasecmp("SELECT $$", query_no_space, k_select_dollar_len)) { pair err_info { get_dollar_quote_error(mysql_thread___server_version) }; GloSQLite3Server->send_MySQL_ERR(&sess->client_myds->myprot, const_cast(err_info.second)); run_query=false; @@ -636,15 +711,15 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p goto __end_show_commands; // in the next block there are only SHOW commands } - if (query_no_space_length==strlen("SHOW TABLES") && !strncasecmp("SHOW TABLES",query_no_space, query_no_space_length)) { + if (query_no_space_length==k_show_tables_len && !strncasecmp("SHOW TABLES",query_no_space, query_no_space_length)) { l_free(query_length,query); query=l_strdup("SELECT name AS tables FROM sqlite_master WHERE type='table' AND name NOT IN ('sqlite_sequence') ORDER BY name"); query_length=strlen(query)+1; goto __run_query; } - if ((query_no_space_length>17) && (!strncasecmp("SHOW TABLES FROM ", query_no_space, 17))) { - strA=query_no_space+17; + if ((query_no_space_length > k_show_tables_from_len) && (!strncasecmp("SHOW TABLES FROM ", query_no_space, k_show_tables_from_len))) { + strA=query_no_space+k_show_tables_from_len; strAl=strlen(strA); strB=(char *)"SELECT name AS tables FROM %s.sqlite_master WHERE type='table' AND name NOT IN ('sqlite_sequence') ORDER BY name"; strBl=strlen(strB); @@ -658,8 +733,8 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p goto __run_query; } - if ((query_no_space_length>17) && (!strncasecmp("SHOW TABLES LIKE ", query_no_space, 17))) { - strA=query_no_space+17; + if ((query_no_space_length > k_show_tables_like_len) && (!strncasecmp("SHOW TABLES LIKE ", query_no_space, k_show_tables_like_len))) { + strA=query_no_space+k_show_tables_like_len; strAl=strlen(strA); strB=(char *)"SELECT name AS tables FROM sqlite_master WHERE type='table' AND name LIKE '%s'"; strBl=strlen(strB); @@ -686,23 +761,25 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p } strA=(char *)"SHOW CREATE TABLE "; + strAl = sizeof("SHOW CREATE TABLE ") - 1; strB=(char *)"SELECT name AS 'table' , REPLACE(REPLACE(sql,' , ', X'2C0A20202020'),'CREATE TABLE %s (','CREATE TABLE %s ('||X'0A20202020') AS 'Create Table' FROM %s.sqlite_master WHERE type='table' AND name='%s'"; - strAl=strlen(strA); - if (strncasecmp("SHOW CREATE TABLE ", query_no_space, strAl)==0) { + if (strncasecmp("SHOW CREATE TABLE ", query_no_space, strAl)==0) { strBl=strlen(strB); char *dbh=NULL; char *tbh=NULL; c_split_2(query_no_space+strAl,".",&dbh,&tbh); - if (strlen(tbh)==0) { + if (std::string_view(tbh).empty()) { free(tbh); tbh=dbh; dbh=strdup("main"); } - if (strlen(tbh)>=3 && tbh[0]=='`' && tbh[strlen(tbh)-1]=='`') { // tablename is quoted - char *tbh_tmp=(char *)malloc(strlen(tbh)-1); - strncpy(tbh_tmp,tbh+1,strlen(tbh)-2); - tbh_tmp[strlen(tbh)-2]=0; + size_t tbh_len = std::string_view(tbh).size(); + if (tbh_len>=3 && tbh[0]=='`' && tbh[tbh_len-1]=='`') { // tablename is quoted + const size_t quoted_len = tbh_len - 2; + char *tbh_tmp=(char *)l_alloc(quoted_len + 1); + memcpy(tbh_tmp, tbh + 1, quoted_len); + tbh_tmp[quoted_len] = 0; free(tbh); tbh=tbh_tmp; } @@ -719,9 +796,9 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p } if ( - (query_no_space_length==strlen("SHOW DATABASES") && !strncasecmp("SHOW DATABASES",query_no_space, query_no_space_length)) + (query_no_space_length==k_show_databases_len && !strncasecmp("SHOW DATABASES",query_no_space, query_no_space_length)) || - (query_no_space_length==strlen("SHOW SCHEMAS") && !strncasecmp("SHOW SCHEMAS",query_no_space, query_no_space_length)) + (query_no_space_length==k_show_schemas_len && !strncasecmp("SHOW SCHEMAS",query_no_space, query_no_space_length)) ) { l_free(query_length,query); query=l_strdup("PRAGMA DATABASE_LIST"); @@ -841,9 +918,16 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p delete control_result; if (run_query && rds_bgd_table_check) { + const char* topology_sql = topology_present ? "SELECT 1" : "SELECT 1 WHERE 0"; + static constexpr size_t topology_sql_len = + sizeof("SELECT 1") - 1; + const size_t topology_len = + topology_present ? + topology_sql_len : + (sizeof("SELECT 1 WHERE 0") - 1); l_free(query_length,query); - query=l_strdup(topology_present ? "SELECT 1" : "SELECT 1 WHERE 0"); - query_length=strlen(query)+1; + query=l_strdup(topology_sql); + query_length=topology_len + 1; } else if (run_query && (configured_error != 0 || !topology_present)) { const uint16_t error_code = configured_error ? static_cast(configured_error) : 1146; @@ -861,45 +945,46 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p }; l_free(query_length,query); query=l_strdup(topology_query.c_str()); - query_length=strlen(query)+1; + query_length=topology_query.length()+1; } } } } #endif // TEST_RDS_BGD -#ifdef TEST_AURORA - if (strstr(query_no_space,(char *)"REPLICA_HOST_STATUS")) { - pthread_mutex_lock(&GloSQLite3Server->aurora_mutex); + #ifdef TEST_AURORA + if (strstr(query_no_space,(char *)"REPLICA_HOST_STATUS")) { + pthread_mutex_lock(&GloSQLite3Server->aurora_mutex); - if (strcasestr(query_no_space, TEST_AURORA_MONITOR_BASE_QUERY)) { - string s_whg { query_no_space + strlen(TEST_AURORA_MONITOR_BASE_QUERY) }; - uint32_t whg = atoi(s_whg.c_str()); + if (strcasestr(query_no_space, TEST_AURORA_MONITOR_BASE_QUERY)) { + string s_whg { query_no_space + (sizeof(TEST_AURORA_MONITOR_BASE_QUERY) - 1) }; + uint32_t whg = atoi(s_whg.c_str()); - GloSQLite3Server->populate_aws_aurora_table(sess, whg); - vector hgs_info { get_hgs_info(GloAdmin->admindb) }; + GloSQLite3Server->populate_aws_aurora_table(sess, whg); + vector hgs_info { get_hgs_info(GloAdmin->admindb) }; - const auto match_writer = [&whg](const aurora_hg_info_t& hg_info) { - return std::get(hg_info) == whg; - }; - const auto hg_info_it = std::find_if(hgs_info.begin(), hgs_info.end(), match_writer); - string select_query { - "SELECT SERVER_ID,SESSION_ID,LAST_UPDATE_TIMESTAMP,REPLICA_LAG_IN_MILLISECONDS,CPU" - " FROM REPLICA_HOST_STATUS " - }; + const auto match_writer = [&whg](const aurora_hg_info_t& hg_info) { + return std::get(hg_info) == whg; + }; + const auto hg_info_it = std::find_if(hgs_info.begin(), hgs_info.end(), match_writer); + string select_query { + "SELECT SERVER_ID,SESSION_ID,LAST_UPDATE_TIMESTAMP,REPLICA_LAG_IN_MILLISECONDS,CPU" + " FROM REPLICA_HOST_STATUS " + }; - if (hg_info_it == hgs_info.end()) { - select_query += " LIMIT 0"; - } else { - const string& domain_name { std::get(*hg_info_it) }; - select_query += " WHERE DOMAIN_NAME='" + domain_name + "' ORDER BY SERVER_ID"; - } + if (hg_info_it == hgs_info.end()) { + select_query += " LIMIT 0"; + } else { + const string& domain_name { std::get(*hg_info_it) }; + select_query += " WHERE DOMAIN_NAME='" + domain_name + "' ORDER BY SERVER_ID"; + } - free(query); - query = static_cast(malloc(select_query.length() + 1)); - strcpy(query, select_query.c_str()); + free(query); + query = static_cast(malloc(select_query.length() + 1)); + memcpy(query, select_query.c_str(), select_query.length()); + query[select_query.length()] = '\0'; + } } - } #endif // TEST_AURORA #ifdef TEST_GALERA if (strstr(query_no_space,(char *)"HOST_STATUS_GALERA")) { @@ -944,63 +1029,58 @@ void SQLite3_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t *p ); query = static_cast(malloc(select_as_query.length() + 1)); - strcpy(query, select_as_query.c_str()); + memcpy(query, select_as_query.c_str(), select_as_query.length()); + query[select_as_query.length()] = '\0'; } } #endif // TEST_GROUPREP #if defined(TEST_READONLY) || defined(TEST_RDS_BGD) - if (strncasecmp("SELECT @@global.read_only read_only ",query_no_space, strlen("SELECT @@global.read_only read_only "))==0) { - if (strlen(query_no_space) > strlen("SELECT @@global.read_only read_only ")+5) { - pthread_mutex_lock(&GloSQLite3Server->test_readonly_mutex); - // the current test doesn't try to simulate failures, therefore it will return immediately - if (GloSQLite3Server->readonly_map_size() == 0) { - // probably never initialized - GloSQLite3Server->load_readonly_table(sess); + if (strncasecmp("SELECT @@global.read_only read_only ",query_no_space, k_select_read_only_len)==0 + && query_no_space_length > k_select_read_only_len+5) { + pthread_mutex_lock(&GloSQLite3Server->test_readonly_mutex); + // the current test doesn't try to simulate failures, therefore it will return immediately + // Load the test table lazily on its first use. + ensure_readonly_table(GloSQLite3Server, sess); + int rc = GloSQLite3Server->readonly_test_value(query_no_space+k_select_read_only_len); + l_free(query_length, query); + const std::string formatted_query = cstr_format("SELECT %d as read_only", rc).str; + query = l_strdup(formatted_query.c_str()); + query_length = formatted_query.size() + 1; + pthread_mutex_unlock(&GloSQLite3Server->test_readonly_mutex); } - int rc = GloSQLite3Server->readonly_test_value(query_no_space+strlen("SELECT @@global.read_only read_only ")); - free(query); - char *a = (char *)"SELECT %d as read_only"; - query = (char *)malloc(strlen(a)+2); - sprintf(query,a,rc); - pthread_mutex_unlock(&GloSQLite3Server->test_readonly_mutex); - } - } #endif // TEST_READONLY || TEST_RDS_BGD #ifdef TEST_REPLICATIONLAG - if ( - strncasecmp("SELECT SLAVE STATUS ", query_no_space, strlen("SELECT SLAVE STATUS ")) == 0 - || strncasecmp("SELECT REPLICA STATUS ", query_no_space, strlen("SELECT REPLICA STATUS ")) == 0 - ) { - uint64_t addr_offset { - strstr(query_no_space, "REPLICA") ? strlen("SELECT REPLICA STATUS ") : strlen("SELECT SLAVE STATUS ") + const bool replica_status = strncasecmp("SELECT REPLICA STATUS ", query_no_space, k_select_replica_status_len) == 0; + const uint64_t addr_offset { + replica_status ? k_select_replica_status_len : k_select_slave_status_len }; - if (strlen(query_no_space) > strlen("SELECT SLAVE STATUS ") + 5) { - pthread_mutex_lock(&GloSQLite3Server->test_replicationlag_mutex); - // the current test doesn't try to simulate failures, therefore it will return immediately - if (GloSQLite3Server->replicationlag_map_size() == 0) { - // probably never initialized - GloSQLite3Server->load_replicationlag_table(sess); - } + if ((strncasecmp("SELECT SLAVE STATUS ", query_no_space, k_select_slave_status_len) == 0 + || replica_status) + && query_no_space_length > addr_offset + 5) { + pthread_mutex_lock(&GloSQLite3Server->test_replicationlag_mutex); + // the current test doesn't try to simulate failures, therefore it will return immediately + ensure_replicationlag_table_loaded(GloSQLite3Server, sess); const int* rc = GloSQLite3Server->replicationlag_test_value(query_no_space + addr_offset); - free(query); + l_free(query_length, query); - string SELECT { "SELECT " + (rc ? std::to_string(*rc) : string { "null" }) + " AS " }; - SELECT += strstr(query_no_space, "REPLICA") ? "Seconds_Behind_Source" : "Seconds_Behind_Master"; + string SELECT { "SELECT " + (rc ? std::to_string(*rc) : string { "null" }) + " AS " }; + SELECT += replica_status ? "Seconds_Behind_Source" : "Seconds_Behind_Master"; - query = static_cast(malloc(SELECT.size() + 1)); - sprintf(query, SELECT.c_str()); + query = l_strdup(SELECT.c_str()); + query_length = SELECT.size() + 1; pthread_mutex_unlock(&GloSQLite3Server->test_replicationlag_mutex); } - } #endif // TEST_REPLICATIONLAG - if (strstr(query_no_space,(char *)"Seconds_Behind_Master")) { - free(query); - char *a = (char *)"SELECT %d as Seconds_Behind_Master"; - query = (char *)malloc(strlen(a)+4); - sprintf(query,a,rand()%30+10); + if (strstr(query_no_space,(char *)"Seconds_Behind_Master")) { + l_free(query_length, query); + const std::string formatted_query = cstr_format( + "SELECT %d as Seconds_Behind_Master", random_replication_lag_seconds() + ).str; + query = l_strdup(formatted_query.c_str()); + query_length = formatted_query.size() + 1; + } } - } #endif // TEST_AURORA || TEST_GALERA || TEST_GROUPREP || TEST_READONLY || TEST_REPLICATIONLAG || TEST_RDS_BGD if (!run_query) { l_free(pkt->size-sizeof(mysql_hdr),query_no_space); @@ -1537,7 +1617,7 @@ void SQLite3_Server::populate_galera_table(MySQL_Session *sess) { cluster_id--; int hg_id = 2270+(cluster_id*10)+1; char buf[1024]; - sprintf(buf, (char *)"SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); + snprintf(buf, sizeof(buf), "SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); sessdb->execute_statement(buf, &error , &cols , &affected_rows , &resultset); if (resultset->rows_count==0) { //sessdb->execute("DELETE FROM HOST_STATUS_GALERA"); diff --git a/src/main.cpp b/src/main.cpp index 3221949120..d126ce662a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,13 @@ using json = nlohmann::json; #include "proxy_protocol_info.h" #endif // DEBUG +static char *make_path(const char *directory, const char *filename) { + std::string path(directory); + path += '/'; + path += filename; + return strdup(path.c_str()); +} + /* extern "C" MySQL_LDAP_Authentication * create_MySQL_LDAP_Authentication_func() { @@ -889,30 +896,24 @@ void ProxySQL_Main_process_global_variables(int argc, const char **argv) { } free(t); - GloVars.admindb=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.db")+2); - sprintf(GloVars.admindb,"%s/%s",GloVars.datadir, (char *)"proxysql.db"); + GloVars.admindb = make_path(GloVars.datadir, "proxysql.db"); - GloVars.sqlite3serverdb=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"sqlite3server.db")+2); - sprintf(GloVars.sqlite3serverdb,"%s/%s",GloVars.datadir, (char *)"sqlite3server.db"); + GloVars.sqlite3serverdb = make_path(GloVars.datadir, "sqlite3server.db"); - GloVars.statsdb_disk=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql_stats.db")+2); - sprintf(GloVars.statsdb_disk,"%s/%s",GloVars.datadir, (char *)"proxysql_stats.db"); + GloVars.statsdb_disk = make_path(GloVars.datadir, "proxysql_stats.db"); if (GloVars.errorlog == NULL) { - GloVars.errorlog=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.log")+2); - sprintf(GloVars.errorlog,"%s/%s",GloVars.datadir, (char *)"proxysql.log"); + GloVars.errorlog = make_path(GloVars.datadir, "proxysql.log"); } if (GloVars.pid == NULL) { - GloVars.pid=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.pid")+2); - sprintf(GloVars.pid,"%s/%s",GloVars.datadir, (char *)"proxysql.pid"); + GloVars.pid = make_path(GloVars.datadir, "proxysql.pid"); } if (GloVars.__cmd_proxysql_initial==true) { std::cerr << "Renaming database file " << GloVars.admindb << endl; - char *newpath=(char *)malloc(strlen(GloVars.admindb)+8); - sprintf(newpath,"%s.bak",GloVars.admindb); - rename(GloVars.admindb,newpath); // FIXME: should we check return value, or ignore whatever it successed or not? + const std::string newpath = std::string(GloVars.admindb) + ".bak"; + rename(GloVars.admindb, newpath.c_str()); // FIXME: should we check return value, or ignore whatever it successed or not? } GloVars.confFile->ReadGlobals(); @@ -2046,9 +2047,8 @@ bool ProxySQL_daemonize_phase3() { // Honor --initial after a crash , see #4659 if (GloVars.__cmd_proxysql_initial==true) { std::cerr << "Renaming database file " << GloVars.admindb << endl; - char *newpath=(char *)malloc(strlen(GloVars.admindb)+8); - sprintf(newpath,"%s.bak",GloVars.admindb); - rename(GloVars.admindb,newpath); // FIXME: should we check return value, or ignore whatever it successed or not? + const std::string newpath = std::string(GloVars.admindb) + ".bak"; + rename(GloVars.admindb, newpath.c_str()); // FIXME: should we check return value, or ignore whatever it successed or not? } parent_close_error_log(); return false; @@ -3122,8 +3122,7 @@ int main(int argc, const char * argv[]) { // Resolve symlinks to get the real path char resolved[PATH_MAX]; if (realpath(buff, resolved) != NULL) { - strncpy(buff, resolved, sizeof(buff) - 1); - buff[sizeof(buff) - 1] = '\0'; + snprintf(buff, sizeof(buff), "%s", resolved); } len = strlen(buff); } @@ -3147,7 +3146,7 @@ int main(int argc, const char * argv[]) { memset(binary_sha1, 0, SHA_DIGEST_LENGTH*2+1); char buf[SHA_DIGEST_LENGTH*2 + 1]; for (int i=0; i < SHA_DIGEST_LENGTH; i++) { - sprintf((char*)&(buf[i*2]), "%02x", temp[i]); + snprintf((char*)&(buf[i*2]), 3, "%02x", temp[i]); } memcpy(binary_sha1, buf, SHA_DIGEST_LENGTH*2); munmap(fb,statbuf.st_size); diff --git a/src/proxy_tls.cpp b/src/proxy_tls.cpp index 38acc553fa..41bf36c1fc 100644 --- a/src/proxy_tls.cpp +++ b/src/proxy_tls.cpp @@ -40,6 +40,11 @@ static char * load_file (const char *filename) { return buffer; } +static char *make_ssl_path(const char *datadir, const char *filename) { + const std::string path = std::string(datadir) + "/" + filename; + return l_strdup(path.c_str()); +} + // absolute path of ssl files static char *ssl_key_fp = NULL; static char *ssl_cert_fp = NULL; @@ -233,24 +238,39 @@ int ssl_mkit(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days, boo // check if files exists if (bootstrap == true) { - ssl_key_fp = (char *)malloc(strlen(GloVars.datadir)+strlen(ssl_key_rp)+8); - sprintf(ssl_key_fp,"%s/%s",GloVars.datadir,ssl_key_rp); + ssl_key_fp = make_ssl_path(GloVars.datadir, ssl_key_rp); + if (ssl_key_fp == NULL) { + msg = "Unable to allocate memory for the TLS key path"; + return 1; + } } if (access(ssl_key_fp, R_OK)) { ssl_key_exists = false; } if (bootstrap == true) { - ssl_cert_fp = (char *)malloc(strlen(GloVars.datadir)+strlen(ssl_cert_rp)+8); - sprintf(ssl_cert_fp,"%s/%s",GloVars.datadir,ssl_cert_rp); + ssl_cert_fp = make_ssl_path(GloVars.datadir, ssl_cert_rp); + if (ssl_cert_fp == NULL) { + l_free(0, ssl_key_fp); + ssl_key_fp = NULL; + msg = "Unable to allocate memory for the TLS certificate path"; + return 1; + } } if (access(ssl_cert_fp, R_OK)) { ssl_cert_exists = false; } if (bootstrap == true) { - ssl_ca_fp = (char *)malloc(strlen(GloVars.datadir)+strlen(ssl_ca_rp)+8); - sprintf(ssl_ca_fp,"%s/%s",GloVars.datadir,ssl_ca_rp); + ssl_ca_fp = make_ssl_path(GloVars.datadir, ssl_ca_rp); + if (ssl_ca_fp == NULL) { + l_free(0, ssl_key_fp); + l_free(0, ssl_cert_fp); + ssl_key_fp = NULL; + ssl_cert_fp = NULL; + msg = "Unable to allocate memory for the TLS CA path"; + return 1; + } } if (access(ssl_ca_fp, R_OK)) { ssl_ca_exists = false; diff --git a/test/PrepStmt/client10.cpp b/test/PrepStmt/client10.cpp index b0a147c4d0..85cfdf1efb 100644 --- a/test/PrepStmt/client10.cpp +++ b/test/PrepStmt/client10.cpp @@ -96,7 +96,7 @@ void * mysql_thread(const std::string& username, int tid) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); return NULL; } - sprintf(buff,"SELECT %u + ?",(uint32_t)mt_rand()%NUMPRO); + bl = (unsigned int)snprintf(buff,sizeof(buff),"SELECT %u + ?",(uint32_t)mt_rand()%NUMPRO); if (mysql_stmt_prepare(stmt, buff, bl)) { // the prepared statement is created fprintf(stderr, " mysql_stmt_prepare(), failed: %s\n" , mysql_stmt_error(stmt)); diff --git a/test/PrepStmt/client2.cpp b/test/PrepStmt/client2.cpp index ad9f744d9d..443420d9c6 100644 --- a/test/PrepStmt/client2.cpp +++ b/test/PrepStmt/client2.cpp @@ -75,6 +75,10 @@ int main() { } int i; stmt=(MYSQL_STMT **)malloc(sizeof(MYSQL_STMT*)*NUMPREP); + if (stmt == NULL) { + fprintf(stderr, "Unable to allocate statement handles\n"); + exit(EXIT_FAILURE); + } { cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); - if (a==NULL) { - if (mysql_stmt_prepare(stmt[i], buff, bl)) { - fprintf(stderr, " mysql_stmt_prepare(), failed: %s\n" , mysql_stmt_error(stmt[i])); - exit(EXIT_FAILURE); - } - uint32_t stmid=GloMyStmt->add_prepared_statement(0,(char *)USER,(char *)SCHEMA,buff,bl,stmt[i]); - if (NUMPRO < 32) - fprintf(stdout, "SERVER_statement_id=%lu , PROXY_statement_id=%u\n", stmt[i]->stmt_id, stmid); - local_stmts->insert(stmid,stmt[i]); - } + if (a != NULL) + continue; + if (mysql_stmt_prepare(stmt[i], buff, bl)) { + fprintf(stderr, " mysql_stmt_prepare(), failed: %s\n" , mysql_stmt_error(stmt[i])); + exit(EXIT_FAILURE); + } + uint32_t stmid=GloMyStmt->add_prepared_statement(0,(char *)USER,(char *)SCHEMA,buff,bl,stmt[i]); + if (NUMPRO < 32) + fprintf(stdout, "SERVER_statement_id=%lu , PROXY_statement_id=%u\n", stmt[i]->stmt_id, stmid); + local_stmts->insert(stmid,stmt[i]); } fprintf(stdout, "Prepared statements: %u client, %u proxy/server. ", NUMPREP, GloMyStmt->total_prepared_statements()); fprintf(stdout, "Created in: "); @@ -105,7 +109,7 @@ int main() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -117,7 +121,7 @@ int main() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -129,7 +133,7 @@ int main() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -141,7 +145,7 @@ int main() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -159,7 +163,7 @@ int main() { // for comparison, we run also queries in TEXT protocol cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -120,7 +120,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -132,7 +132,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -144,7 +144,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -156,7 +156,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -176,7 +176,7 @@ void * mysql_thread(int tid) { // for comparison, we run also queries in TEXT protocol cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -112,7 +112,7 @@ void * mysql_thread() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -124,7 +124,7 @@ void * mysql_thread() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -136,7 +136,7 @@ void * mysql_thread() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -148,7 +148,7 @@ void * mysql_thread() { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -166,7 +166,7 @@ void * mysql_thread() { // for comparison, we run also queries in TEXT protocol cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -133,7 +133,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -145,7 +145,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -157,7 +157,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -172,7 +172,7 @@ void * mysql_thread(int tid) { unsigned int executed=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); diff --git a/test/PrepStmt/client6.cpp b/test/PrepStmt/client6.cpp index f2e2b12bce..0a6d760c3d 100644 --- a/test/PrepStmt/client6.cpp +++ b/test/PrepStmt/client6.cpp @@ -130,7 +130,7 @@ void * mysql_thread(int tid) { } for (i=0; i<16; i++) { MySQL_Session *sess=SESS[i]; - sprintf(buff+5,"SELECT %u + ?",(uint32_t)mt_rand()%NUMPRO); + snprintf(buff+5,sizeof(buff)-5,"SELECT %u + ?",(uint32_t)mt_rand()%NUMPRO); bl=strlen(buff+5); mysql_hdr hdr; hdr.pkt_id=0; diff --git a/test/PrepStmt/client7.cpp b/test/PrepStmt/client7.cpp index 470669a73b..667b82ae10 100644 --- a/test/PrepStmt/client7.cpp +++ b/test/PrepStmt/client7.cpp @@ -168,7 +168,7 @@ void * mysql_thread(int tid) { cpu_timer t; // in this loop we create only some the prepared statements for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -209,7 +209,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -221,7 +221,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); //MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -233,7 +233,7 @@ void * mysql_thread(int tid) { unsigned int founds=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); @@ -248,7 +248,7 @@ void * mysql_thread(int tid) { unsigned int executed=0; cpu_timer t; for (i=0; icompute_hash(0,(char *)USER,(char *)SCHEMA,buff,bl); MySQL_STMT_Global_info *a=GloMyStmt->find_prepared_statement_by_hash(hash); diff --git a/test/PrepStmt/client9.cpp b/test/PrepStmt/client9.cpp index e2b2a67e77..bc3f78d9c9 100644 --- a/test/PrepStmt/client9.cpp +++ b/test/PrepStmt/client9.cpp @@ -64,7 +64,11 @@ void run(MYSQL *mysql) { uint32_t r=(uint32_t)mt_rand(); r=r%3000; char *query=(char *)malloc(strlen(QUERY1)+16); - sprintf(query,QUERY1,r); + if (query == NULL) { + fprintf(stderr, "Unable to allocate statement query\n"); + exit(EXIT_FAILURE); + } + snprintf(query,strlen(QUERY1)+16,QUERY1,r); if (DBG) { fprintf(stdout,"%s\n",query); } diff --git a/test/tap/tap/SQLite3_Server.cpp b/test/tap/tap/SQLite3_Server.cpp index 74b8820d4a..5b3d857a07 100644 --- a/test/tap/tap/SQLite3_Server.cpp +++ b/test/tap/tap/SQLite3_Server.cpp @@ -194,18 +194,40 @@ class sqlite3server_main_loop_listeners { bool update_ifaces(char *list, char ***_ifaces) { wrlock(); - int i; - char **ifaces=*_ifaces; + int i = 0; + char **old_ifaces = *_ifaces; + char **new_ifaces = (char **)l_alloc(MAX_IFACES * sizeof(char *)); + if (new_ifaces != NULL) { + memset(new_ifaces, 0, MAX_IFACES * sizeof(char *)); + } tokenizer_t tok; tokenizer( &tok, list, ";", TOKENIZER_NO_EMPTIES ); const char* token; - ifaces=reset_ifaces(ifaces); - i=0; + if (new_ifaces == NULL) { + free_tokenizer( &tok ); + wrunlock(); + return false; + } for ( token = tokenize( &tok ) ; token && i < MAX_IFACES ; token = tokenize( &tok ) ) { - ifaces[i]=(char *)malloc(strlen(token)+1); - strcpy(ifaces[i],token); + new_ifaces[i] = strdup(token); + if (new_ifaces[i] == NULL) { + for (int j = 0; j < i; ++j) { + l_free(0, new_ifaces[j]); + } + l_free(0, new_ifaces); + free_tokenizer( &tok ); + wrunlock(); + return false; + } i++; } + if (old_ifaces != NULL) { + for (int j = 0; j < MAX_IFACES; ++j) { + l_free(0, old_ifaces[j]); + } + l_free(0, old_ifaces); + } + *_ifaces = new_ifaces; free_tokenizer( &tok ); version++; wrunlock(); diff --git a/test/tap/tap/tap.cpp b/test/tap/tap/tap.cpp index c5df26bf22..74bb4d02cb 100644 --- a/test/tap/tap/tap.cpp +++ b/test/tap/tap/tap.cpp @@ -435,28 +435,40 @@ static ulong start_timer(void) static void nice_time(double sec,char *buff, my_bool part_second) { ulong tmp; + size_t remaining = 53; // per comment above: 52 chars + '\0' + char *p = buff; + if (sec >= 3600.0*24) { tmp=(ulong) (sec/(3600.0*24)); sec-=3600.0*24*tmp; - buff+= sprintf(buff, "%ld %s", tmp, tmp > 1 ? " days " : " day "); + int n = snprintf(p, remaining, "%lu %s", tmp, tmp > 1 ? " days " : " day "); + if (n < 0 || (size_t)n >= remaining) return; + p += n; + remaining -= n; } if (sec >= 3600.0) { tmp=(ulong) (sec/3600.0); sec-=3600.0*tmp; - buff+= sprintf(buff, "%ld %s", tmp, tmp > 1 ? " hours " : " hour "); + int n = snprintf(p, remaining, "%lu %s", tmp, tmp > 1 ? " hours " : " hour "); + if (n < 0 || (size_t)n >= remaining) return; + p += n; + remaining -= n; } if (sec >= 60.0) { tmp=(ulong) (sec/60.0); sec-=60.0*tmp; - buff+= sprintf(buff, "%ld min ", tmp); + int n = snprintf(p, remaining, "%lu min ", tmp); + if (n < 0 || (size_t)n >= remaining) return; + p += n; + remaining -= n; } if (part_second) - sprintf(buff,"%.2f sec",sec); + snprintf(p, remaining, "%.2f sec",sec); else - sprintf(buff,"%d sec",(int) sec); + snprintf(p, remaining,"%d sec",(int) sec); } diff --git a/test/tap/tests/admin_show_fields_from-t.cpp b/test/tap/tests/admin_show_fields_from-t.cpp index 5e7b5847ae..00eb8d5133 100644 --- a/test/tap/tests/admin_show_fields_from-t.cpp +++ b/test/tap/tests/admin_show_fields_from-t.cpp @@ -74,17 +74,22 @@ int main() { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); return -1; } - char *query = (char *) malloc(strlen(queries[0]) + it->length() + 8); for (std::vector::iterator it2 = queries.begin(); it2 != queries.end(); it2++) { - sprintf(query,*it2, it->c_str()); - diag("Running query: %s", query); - MYSQL_QUERY(proxysql_admin, query); + std::string query(*it2); + const size_t placeholder = query.find("%s"); + if (placeholder == std::string::npos) { + fprintf(stderr, "Query template is missing its table placeholder\n"); + mysql_close(proxysql_admin); + return -1; + } + query.replace(placeholder, 2, *it); + diag("Running query: %s", query.c_str()); + MYSQL_QUERY(proxysql_admin, query.c_str()); MYSQL_RES* proxy_res = mysql_store_result(proxysql_admin); unsigned long rows = proxy_res->row_count; ok(rows > 0 , "Number of rows in %s = %lu", it->c_str(), rows); mysql_free_result(proxy_res); } - free(query); mysql_close(proxysql_admin); } diff --git a/test/tap/tests/admin_show_table_status-t.cpp b/test/tap/tests/admin_show_table_status-t.cpp index ace170af3d..dde72e3014 100644 --- a/test/tap/tests/admin_show_table_status-t.cpp +++ b/test/tap/tests/admin_show_table_status-t.cpp @@ -74,17 +74,22 @@ int main() { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); return -1; } - char *query = (char *) malloc(strlen(queries[0]) + it->length() + 8); for (std::vector::iterator it2 = queries.begin(); it2 != queries.end(); it2++) { - sprintf(query,*it2, it->c_str()); - diag("Running query: %s", query); - MYSQL_QUERY(proxysql_admin, query); + std::string query(*it2); + const size_t placeholder = query.find("%s"); + if (placeholder == std::string::npos) { + fprintf(stderr, "Query template is missing its table placeholder\n"); + mysql_close(proxysql_admin); + return -1; + } + query.replace(placeholder, 2, *it); + diag("Running query: %s", query.c_str()); + MYSQL_QUERY(proxysql_admin, query.c_str()); MYSQL_RES* proxy_res = mysql_store_result(proxysql_admin); unsigned long rows = proxy_res->row_count; ok(rows == 1 , "SHOW TABLE STATUS %s generated %lu row(s)", it->c_str(), rows); mysql_free_result(proxy_res); } - free(query); mysql_close(proxysql_admin); } diff --git a/test/tap/tests/aurora.cpp b/test/tap/tests/aurora.cpp index ea155edb1f..97a7b0dd0d 100644 --- a/test/tap/tests/aurora.cpp +++ b/test/tap/tests/aurora.cpp @@ -10,6 +10,7 @@ #include "MySQL_Data_Stream.h" #include "query_processor.h" #include "SQLite3_Server.h" +#include "proxysql_utils.h" #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -41,6 +43,12 @@ extern SQLite3_Server *GloSQLite3Server; +static int random_replication_lag_seconds() { + static thread_local std::random_device random_source; + static thread_local std::uniform_int_distribution distribution(10, 39); + return distribution(random_source); +} + void SQLite3_Server::init_aurora_ifaces_string(std::string& s) { if(!s.empty()) s += ";"; @@ -256,10 +264,16 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p if (query_no_space_length==SELECT_VERSION_COMMENT_LEN) { if (!strncasecmp(SELECT_VERSION_COMMENT, query_no_space, query_no_space_length)) { l_free(query_length,query); - char *a = (char *)"SELECT '(ProxySQL Automated Test Server) - %s'"; - query = (char *)malloc(strlen(a)+strlen(sess->client_myds->proxy_addr.addr)); - sprintf(query,a,sess->client_myds->proxy_addr.addr); - query_length=strlen(query)+1; + const char* proxy_addr = sess->client_myds->proxy_addr.addr; + const std::string query_text = + std::string("SELECT '(ProxySQL Automated Test Server) - ") + + (proxy_addr ? proxy_addr : "") + "'"; + query = l_strdup(query_text.c_str()); + if (!query) { + l_free(pkt->size-sizeof(mysql_hdr), query_no_space); + return; + } + query_length = query_text.size() + 1; goto __run_query; } } @@ -267,12 +281,16 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p if (query_no_space_length==SELECT_DB_USER_LEN) { if (!strncasecmp(SELECT_DB_USER, query_no_space, query_no_space_length)) { l_free(query_length,query); - char *query1=(char *)"SELECT \"admin\" AS 'DATABASE()', \"%s\" AS 'USER()'"; - char *query2=(char *)malloc(strlen(query1)+strlen(sess->client_myds->myconn->userinfo->username)+10); - sprintf(query2,query1,sess->client_myds->myconn->userinfo->username); - query=l_strdup(query2); - query_length=strlen(query2)+1; - free(query2); + const char* username = sess->client_myds->myconn->userinfo->username; + const std::string query_text = + std::string("SELECT \"admin\" AS 'DATABASE()', \"") + + (username ? username : "") + "\" AS 'USER()'"; + query = l_strdup(query_text.c_str()); + if (!query) { + l_free(pkt->size-sizeof(mysql_hdr), query_no_space); + return; + } + query_length = query_text.size() + 1; goto __run_query; } } @@ -292,7 +310,7 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p char *q=(char *)"SELECT '%s' AS '@@version'"; query_length=strlen(q)+20; query=(char *)l_alloc(query_length); - sprintf(query,q,PROXYSQL_VERSION); + snprintf(query, query_length, q, PROXYSQL_VERSION); goto __run_query; } @@ -301,7 +319,7 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p char *q=(char *)"SELECT '%s' AS 'version()'"; query_length=strlen(q)+20; query=(char *)l_alloc(query_length); - sprintf(query,q,PROXYSQL_VERSION); + snprintf(query, query_length, q, PROXYSQL_VERSION); goto __run_query; } @@ -367,27 +385,40 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p char *tbh=NULL; c_split_2(query_no_space+strAl,".",&dbh,&tbh); - if (strlen(tbh)==0) { - free(tbh); + if (std::string_view(tbh).empty()) { + l_free(0, tbh); tbh=dbh; dbh=strdup("main"); } - if (strlen(tbh)>=3 && tbh[0]=='`' && tbh[strlen(tbh)-1]=='`') { // tablename is quoted - char *tbh_tmp=(char *)malloc(strlen(tbh)-1); - strncpy(tbh_tmp,tbh+1,strlen(tbh)-2); - tbh_tmp[strlen(tbh)-2]=0; + size_t tbh_len = std::string_view(tbh).size(); + if (tbh_len>=3 && tbh[0]=='`' && tbh[tbh_len-1]=='`') { // tablename is quoted + size_t db_len = tbh_len - 2; + const std::string unquoted_table(tbh + 1, db_len); free(tbh); - tbh=tbh_tmp; + tbh = l_strdup(unquoted_table.c_str()); + if (!tbh) { + free(dbh); + l_free(query_length, query); + return; + } } - int l=strBl+strlen(tbh)*3+strlen(dbh)-8; - char *buff=(char *)l_alloc(l+1); - snprintf(buff,l+1,strB,tbh,tbh,dbh,tbh); - buff[l]=0; - free(tbh); - free(dbh); + const std::string table_query = + std::string("SELECT name AS 'table' , REPLACE(REPLACE(sql,' , ', X'2C0A20202020'),") + + "'CREATE TABLE " + tbh + " (','CREATE TABLE " + tbh + + " ('||X'0A20202020') AS 'Create Table' FROM " + dbh + + ".sqlite_master WHERE type='table' AND name='" + tbh + "'"; + char *buff = l_strdup(table_query.c_str()); + if (!buff) { + l_free(0, tbh); + l_free(0, dbh); + l_free(query_length, query); + return; + } + l_free(0, tbh); + l_free(0, dbh); l_free(query_length,query); query=buff; - query_length=l+1; + query_length=table_query.size()+1; goto __run_query; } @@ -439,10 +470,11 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p GloSQLite3Server->populate_aws_aurora_table(sess); } if (strstr(query_no_space,(char *)"Seconds_Behind_Master")) { - free(query); - char *a = (char *)"SELECT %d as Seconds_Behind_Master"; - query = (char *)malloc(strlen(a)+4); - sprintf(query,a,rand()%30+10); + l_free(0, query); + const std::string formatted_query = cstr_format( + "SELECT %d as Seconds_Behind_Master", random_replication_lag_seconds() + ).str; + query = l_strdup(formatted_query.c_str()); } } SQLite3_Session *sqlite_sess = (SQLite3_Session *)sess->thread->gen_args; diff --git a/test/tap/tests/galera_1_timeout_count.cpp b/test/tap/tests/galera_1_timeout_count.cpp index 58ab87c15a..96798c1366 100644 --- a/test/tap/tests/galera_1_timeout_count.cpp +++ b/test/tap/tests/galera_1_timeout_count.cpp @@ -23,12 +23,19 @@ #include #include #include +#include #include #include #include "tap.h" +static int random_replication_lag_seconds() { + static thread_local std::random_device random_source; + static thread_local std::uniform_int_distribution distribution(10, 39); + return distribution(random_source); +} + #define SELECT_VERSION_COMMENT "select @@version_comment limit 1" #define SELECT_VERSION_COMMENT_LEN 32 #define SELECT_DB_USER "select DATABASE(), USER() limit 1" @@ -84,7 +91,7 @@ void SQLite3_Server::populate_galera_table(MySQL_Session *sess) { cluster_id--; int hg_id = 2270+(cluster_id*10)+1; char buf[1024]; - sprintf(buf, (char *)"SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); + snprintf(buf, sizeof(buf), "SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); sessdb->execute_statement(buf, &error , &cols , &affected_rows , &resultset); if (resultset->rows_count==0) { //sessdb->execute("DELETE FROM HOST_STATUS_GALERA"); @@ -194,10 +201,11 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p GloSQLite3Server->populate_galera_table(sess); } if (strstr(query_no_space,(char *)"Seconds_Behind_Master")) { - free(query); - char *a = (char *)"SELECT %d as Seconds_Behind_Master"; - query = (char *)malloc(strlen(a)+4); - sprintf(query,a,rand()%30+10); + l_free(0, query); + const std::string formatted_query = cstr_format( + "SELECT %d as Seconds_Behind_Master", random_replication_lag_seconds() + ).str; + query = l_strdup(formatted_query.c_str()); } } SQLite3_Session *sqlite_sess = (SQLite3_Session *)sess->thread->gen_args; diff --git a/test/tap/tests/galera_2_timeout_no_count.cpp b/test/tap/tests/galera_2_timeout_no_count.cpp index d558ec292f..fad570a740 100644 --- a/test/tap/tests/galera_2_timeout_no_count.cpp +++ b/test/tap/tests/galera_2_timeout_no_count.cpp @@ -23,12 +23,19 @@ #include #include #include +#include #include #include #include "tap.h" +static int random_replication_lag_seconds() { + static thread_local std::random_device random_source; + static thread_local std::uniform_int_distribution distribution(10, 39); + return distribution(random_source); +} + #define SELECT_VERSION_COMMENT "select @@version_comment limit 1" #define SELECT_VERSION_COMMENT_LEN 32 #define SELECT_DB_USER "select DATABASE(), USER() limit 1" @@ -85,7 +92,7 @@ void SQLite3_Server::populate_galera_table(MySQL_Session *sess) { cluster_id--; int hg_id = 2270+(cluster_id*10)+1; char buf[1024]; - sprintf(buf, (char *)"SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); + snprintf(buf, sizeof(buf), "SELECT * FROM HOST_STATUS_GALERA WHERE hostgroup_id = %d LIMIT 1", hg_id); sessdb->execute_statement(buf, &error , &cols , &affected_rows , &resultset); if (resultset->rows_count==0) { //sessdb->execute("DELETE FROM HOST_STATUS_GALERA"); @@ -204,10 +211,11 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p GloSQLite3Server->populate_galera_table(sess); } if (strstr(query_no_space,(char *)"Seconds_Behind_Master")) { - free(query); - char *a = (char *)"SELECT %d as Seconds_Behind_Master"; - query = (char *)malloc(strlen(a)+4); - sprintf(query,a,rand()%30+10); + l_free(0, query); + const std::string formatted_query = cstr_format( + "SELECT %d as Seconds_Behind_Master", random_replication_lag_seconds() + ).str; + query = l_strdup(formatted_query.c_str()); } } SQLite3_Session *sqlite_sess = (SQLite3_Session *)sess->thread->gen_args; diff --git a/test/tap/tests/mysql-reg_test_4867_query_rules-t.cpp b/test/tap/tests/mysql-reg_test_4867_query_rules-t.cpp index c1eab3d333..9e7ecce4e5 100644 --- a/test/tap/tests/mysql-reg_test_4867_query_rules-t.cpp +++ b/test/tap/tests/mysql-reg_test_4867_query_rules-t.cpp @@ -74,22 +74,21 @@ int next_val(ValueGenerator* vg) { } char* unique_str(ValueGenerator* vg, const char* field) { - char* str = (char*)malloc(32); - sprintf(str, "%s_%d", field, next_val(vg)); - return str; + const std::string value = std::string(field) + "_" + std::to_string(next_val(vg)); + return strdup(value.c_str()); } char* unique_ip(ValueGenerator* vg) { char* ip = (char*)malloc(24); unsigned int octet = vg->base + vg->offset++; - sprintf(ip, "%u.%u.%u.%u", + snprintf(ip, 24, "%u.%u.%u.%u", octet % 256, (octet + 1) % 256, (octet + 2) % 256, (octet + 3) % 256); return ip; } char* unique_json(ValueGenerator* vg) { char* json = (char*)malloc(50); - sprintf(json, "{\"%s\":%d}", "unique_key", next_val(vg)); + snprintf(json, 50, "{\"%s\":%d}", "unique_key", next_val(vg)); return json; } @@ -136,13 +135,17 @@ char* psprintf(const char* fmt, ...) { } char* escape_str(MYSQL* mysql, const char* str) { - if (!str) return strdup("NULL"); - char* escaped = (char*)malloc(2 * strlen(str) + 1); - mysql_real_escape_string(mysql, escaped, str, strlen(str)); - char* result = (char*)malloc(strlen(escaped) + 3); - sprintf(result, "'%s'", escaped); - free(escaped); - return result; + if (!str) return strdup("NULL"); + const std::string input(str); + const size_t input_len = input.size(); + std::string escaped(2 * input_len + 1, '\0'); + const unsigned long escaped_len = mysql_real_escape_string(mysql, escaped.data(), input.c_str(), input_len); + std::string result; + result.reserve(escaped_len + 2); + result.push_back('\''); + result.append(escaped.data(), escaped_len); + result.push_back('\''); + return strdup(result.c_str()); } // Build INSERT query for a rule @@ -297,7 +300,7 @@ bool check_result(MYSQL_RES* res, RuleData* expected, bool runtime_table) { // converting digest to hex string char hex_string[20]; - sprintf(hex_string, "0x%016X", expected->digest); + snprintf(hex_string, sizeof(hex_string), "0x%016X", expected->digest); if (strcmp(row[field_idx], hex_string ? hex_string : "") != 0) { diag("Expected digest to be '%s', got '%s'", hex_string, row[field_idx]); @@ -408,7 +411,7 @@ int main() { // Check rules in runtime table for (int i = 0; i < num_tests; i++) { char query[256]; - sprintf(query, "SELECT * FROM runtime_mysql_query_rules WHERE rule_id = %d", rule_ids[i]); + snprintf(query, sizeof(query), "SELECT * FROM runtime_mysql_query_rules WHERE rule_id = %d", rule_ids[i]); MYSQL_QUERY_ON_ERR_CLEANUP(proxysql_admin, query); MYSQL_RES* res = mysql_store_result(proxysql_admin); if (!res || mysql_num_rows(res) == 0) { @@ -429,7 +432,7 @@ int main() { // Check rules in runtime table for (int i = 0; i < num_tests; i++) { char query[256]; - sprintf(query, "SELECT * FROM disk.mysql_query_rules WHERE rule_id = %d", rule_ids[i]); + snprintf(query, sizeof(query), "SELECT * FROM disk.mysql_query_rules WHERE rule_id = %d", rule_ids[i]); if (mysql_query(proxysql_admin, query)) { fprintf(stderr, "File %s, line %d, Error: %s (%s)\n", __FILE__, __LINE__, mysql_error(proxysql_admin), query); diff --git a/test/tap/tests/pgsql-connection_parameters_test-t.cpp b/test/tap/tests/pgsql-connection_parameters_test-t.cpp index c65eff0c2a..fa502b325e 100644 --- a/test/tap/tests/pgsql-connection_parameters_test-t.cpp +++ b/test/tap/tests/pgsql-connection_parameters_test-t.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -64,21 +65,18 @@ PGConnPtr createNewConnection(ConnType conn_type, const std::string& parameters return PGConnPtr(conn, &PQfinish); } -bool executeQueries(PGconn* conn, const std::vector& queries) { - auto fnResultType = [](const char* query) -> int { - const char* fs = strchr(query, ' '); - size_t qtlen = strlen(query); - if (fs != NULL) { - qtlen = (fs - query) + 1; + bool executeQueries(PGconn* conn, const std::vector& queries) { + auto fnResultType = [](const char* query) -> int { + const size_t qtlen = strcspn(query, " \t\r\n"); + std::string query_type(query, qtlen); + for (char& c : query_type) { + c = std::toupper(c, std::locale::classic()); } - char buf[qtlen]; - memcpy(buf, query, qtlen - 1); - buf[qtlen - 1] = 0; - if (strncasecmp(buf, "SELECT", sizeof("SELECT") - 1) == 0) { + if (query_type == "SELECT") { return PGRES_TUPLES_OK; } - if (strncasecmp(buf, "COPY", sizeof("COPY") - 1) == 0) { + if (query_type == "COPY") { return PGRES_COPY_OUT; } @@ -291,13 +289,29 @@ void send_startup_message(int sock, const std::vector sizeof(msg)) { + return; + } + memcpy(msg + offset, params[i].first.c_str(), key_len); + offset += key_len; + if (offset >= sizeof(msg)) { + return; + } + msg[offset++] = '\0'; + if (offset + val_len + 1 > sizeof(msg)) { + return; + } + memcpy(msg + offset, params[i].second.c_str(), val_len); + offset += val_len; + msg[offset++] = '\0'; + } + if (offset >= sizeof(msg)) { + return; + } + msg[offset++] = '\0'; send(sock, msg, offset, 0); } @@ -619,8 +633,8 @@ const char* escape_string_backslash_spaces(const char* input) { for (c = input; *c != '\0'; c++) { if ((*c == ' ')) { - memcpy(p, "\\\\", 2); - p += 2; + *p++ = '\\'; + *p++ = '\\'; } else if (*c == '\\') { *(p++) = '\\'; diff --git a/test/tap/tests/pgsql-copy_from_test-t.cpp b/test/tap/tests/pgsql-copy_from_test-t.cpp index 8f3832be74..1869f54f9b 100644 --- a/test/tap/tests/pgsql-copy_from_test-t.cpp +++ b/test/tap/tests/pgsql-copy_from_test-t.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -134,7 +136,7 @@ void write_int16(uint8_t* dest, int16_t value) { dest[1] = value & 0xFF; } -bool encodeNumericBinary(uint8_t* out, const char* numStr) { +int encodeNumericBinary(uint8_t* out, const char* numStr) { int16_t numDigits = 0, weight = 0, sign = 0x0000, scale = 0; int16_t digits[64] = { 0 }; // Temporary storage for up to 64 4-digit groups size_t digitCount = 0; @@ -153,9 +155,17 @@ bool encodeNumericBinary(uint8_t* out, const char* numStr) { // Combine integer and fractional parts into a single string of digits char combined[128] = { 0 }; - strncpy(combined, numericPart, intPartLen); + if (intPartLen >= sizeof(combined) || fracPartLen > sizeof(combined) - 1 - intPartLen) { + return -1; + } + size_t copy_len = intPartLen; + memcpy(combined, numericPart, copy_len); + combined[copy_len] = 0; if (fracPartLen > 0) { - strncat(combined, dotPos + 1, fracPartLen); + size_t combined_len = copy_len; + size_t copy_len_frac = fracPartLen; + memcpy(combined + combined_len, dotPos + 1, copy_len_frac); + combined[combined_len + copy_len_frac] = 0; } // Remove leading zeros @@ -173,7 +183,8 @@ bool encodeNumericBinary(uint8_t* out, const char* numStr) { // Parse the padded string into 4-digit groups for (size_t i = 0; i < paddedLen; i += 4) { char group[5] = { 0 }; // Temporary buffer for a group of up to 4 digits - strncpy(group, combined + i, 4); + memcpy(group, combined + i, 4); + group[4] = 0; digits[digitCount++] = static_cast(htons(static_cast(atoi(group)))); // Convert group to 16-bit integer } @@ -268,14 +279,23 @@ int is_string_in_result(PGresult* result, const char* target_str) { char full_row_str[1024] = { 0 }; // Buffer to reconstruct full row string // Reconstruct the row string (with tab and newline separators) - for (int j = 0; j < cols; j++) { - char* val = PQgetvalue(result, i, j); - strcat(full_row_str, val); - if (j < cols - 1) { - strcat(full_row_str, "\t"); + size_t current_len = 0; + for (int j = 0; j < cols; j++) { + char* val = PQgetvalue(result, i, j); + size_t space_left = sizeof(full_row_str) - current_len; + if (space_left == 0) { + break; } + int nwritten = snprintf(full_row_str + current_len, space_left, "%s%s", val, (j < cols - 1) ? "\t" : ""); + if (nwritten < 0 || (size_t)nwritten >= space_left) { + break; + } + current_len += nwritten; + } + size_t space_left = sizeof(full_row_str) - current_len; + if (space_left > 1) { + snprintf(full_row_str + current_len, space_left, "\n"); } - strcat(full_row_str, "\n"); // Compare reconstructed row string with target if (strcmp(full_row_str, target_str) == 0) { @@ -327,6 +347,62 @@ const column_type_t columns_type[] = { DATE }; +bool encodeBinaryField(uint8_t* row, int& offset, column_type_t type, const std::string& data) { + switch (type) { + case INT: { + write_int32(row + offset, sizeof(int32_t)); + offset += sizeof(int32_t); + const int32_t value = atoi(data.c_str()); + write_int32(row + offset, value); + offset += sizeof(value); + return true; + } + case DATE: { + write_int32(row + offset, sizeof(int32_t)); + offset += sizeof(int32_t); + const uint32_t date = encodeDateBinary(data.c_str()); + memcpy(row + offset, &date, sizeof(date)); + offset += sizeof(date); + return true; + } + case TEXT: + write_int32(row + offset, data.size()); + offset += sizeof(int32_t); + memcpy(row + offset, data.c_str(), data.size()); + offset += data.size(); + return true; + case BOOLEAN: { + bool value; + if (data == "true" || data == "t") { + value = true; + } else if (data == "false" || data == "f") { + value = false; + } else { + fprintf(stderr, "Invalid boolean value for binary COPY: %s\n", data.c_str()); + return false; + } + write_int32(row + offset, 1); + offset += sizeof(int32_t); + row[offset++] = value ? 1 : 0; + return true; + } + case NUMERIC: { + uint8_t* length_pos = row + offset; + offset += sizeof(int32_t); + const int digit_count = encodeNumericBinary(row + offset, data.c_str()); + if (digit_count < 0) { + fprintf(stderr, "Numeric value is too long for the binary COPY test buffer: %s\n", data.c_str()); + return false; + } + const int32_t payload_length = digit_count > 0 ? 12 : 8; + write_int32(length_pos, payload_length); + offset += payload_length; + return true; + } + } + return false; +} + /** * @brief Tests the COPY IN functionality using STDIN in TEXT format. * @@ -426,44 +502,14 @@ void testSTDIN_TEXT_BINARY(PGconn* admin_conn, PGconn* conn, std::fstream& f_pro offset += sizeof(num_fields); for (unsigned int j = 0; j < row_data.size(); j++) { - const std::string& data = row_data[j]; - if (columns_type[j] == INT) { - write_int32(row + offset, sizeof(int32_t)); - offset += sizeof(int32_t); - - int32_t value = atoi(data.c_str()); - // write actual data - memcpy(row + offset, &value, sizeof(value)); - offset += sizeof(value); - } else if (columns_type[j] == DATE) { - write_int32(row + offset, sizeof(int32_t)); - offset += sizeof(int32_t); - - uint32_t date = encodeDateBinary(data.c_str()); - // write actual data - memcpy(row + offset, &date, sizeof(date)); - offset += sizeof(date); - } else if (columns_type[j] == TEXT || columns_type[j] == BOOLEAN) { - // write field length - write_int32(row + offset, data.size()); - offset += sizeof(int32_t); - - // write actual data - memcpy(row + offset, data.c_str(), data.size()); - offset += data.size(); - } else if (columns_type[j] == NUMERIC) { - uint8_t* prev_pos = (row + offset); - offset += sizeof(int32_t); - bool has_digits = encodeNumericBinary(row + offset, data.c_str()); - if (has_digits) { - write_int32(prev_pos, 12); - offset += 12; - } else { - write_int32(prev_pos, 8); - offset += 8; - } - } + if (!encodeBinaryField(row, offset, columns_type[j], row_data[j])) { + success = false; + break; + } } + if (!success) { + break; + } bool last = (i == (test_data.size() - 1)); @@ -478,6 +524,9 @@ void testSTDIN_TEXT_BINARY(PGconn* admin_conn, PGconn* conn, std::fstream& f_pro } ok(success, "Copy data transmission should be successful"); + if (!success) { + return; + } PGresult* res = PQgetResult(conn); diff --git a/test/tap/tests/pgsql-copy_to_test-t.cpp b/test/tap/tests/pgsql-copy_to_test-t.cpp index 5286256ec9..28a082f478 100644 --- a/test/tap/tests/pgsql-copy_to_test-t.cpp +++ b/test/tap/tests/pgsql-copy_to_test-t.cpp @@ -285,12 +285,12 @@ void testLargeDataVolume(PGconn* admin_conn, PGconn* conn) { return; // Insert a large number of rows - for (int i = 0; i < 1000; i++) { - char query[256]; - sprintf(query, "INSERT INTO copy_test (name, value, active, created_at) VALUES ('User%d', %d, %s, NOW())", - i, i * 10, (i % 2 == 0) ? "TRUE" : "FALSE"); - if (!executeQueries(conn, { - query + for (int i = 0; i < 1000; i++) { + char query[256]; + snprintf(query, sizeof(query), "INSERT INTO copy_test (name, value, active, created_at) VALUES ('User%d', %d, %s, NOW())", + i, i * 10, (i % 2 == 0) ? "TRUE" : "FALSE"); + if (!executeQueries(conn, { + query })) return; } diff --git a/test/tap/tests/pgsql-reg_test_4867_query_rules-t.cpp b/test/tap/tests/pgsql-reg_test_4867_query_rules-t.cpp index 4bc34f28b5..a233dfb0ba 100644 --- a/test/tap/tests/pgsql-reg_test_4867_query_rules-t.cpp +++ b/test/tap/tests/pgsql-reg_test_4867_query_rules-t.cpp @@ -122,21 +122,21 @@ int next_val(ValueGenerator* vg) { char* unique_str(ValueGenerator* vg, const char* field) { char* str = (char*)malloc(32); - sprintf(str, "%s_%d", field, next_val(vg)); + snprintf(str, 32, "%s_%d", field, next_val(vg)); return str; } char* unique_ip(ValueGenerator* vg) { char* ip = (char*)malloc(24); unsigned int octet = vg->base + vg->offset++; - sprintf(ip, "%u.%u.%u.%u", + snprintf(ip, 24, "%u.%u.%u.%u", octet % 256, (octet + 1) % 256, (octet + 2) % 256, (octet + 3) % 256); return ip; } char* unique_json(ValueGenerator* vg) { char* json = (char*)malloc(50); - sprintf(json, "{\"%s\":%d}", "unique_key", next_val(vg)); + snprintf(json, 50, "{\"%s\":%d}", "unique_key", next_val(vg)); return json; } @@ -343,7 +343,7 @@ bool check_result(PGresult* res, RuleData* expected, bool runtime_table) { // converting digest to hex string char hex_string[20]; - sprintf(hex_string, "0x%016X", expected->digest); + snprintf(hex_string, sizeof(hex_string), "0x%016X", expected->digest); f = PQfnumber(res, "digest"); if (!compare_str(PQgetvalue(res, 0, f), hex_string)) { match = false; @@ -515,7 +515,7 @@ int main() { // Check rules in runtime table for (int i = 0; i < num_tests; i++) { char query[256]; - sprintf(query, "SELECT * FROM runtime_pgsql_query_rules WHERE rule_id = %d", rule_ids[i]); + snprintf(query, sizeof(query), "SELECT * FROM runtime_pgsql_query_rules WHERE rule_id = %d", rule_ids[i]); PGresult* res = PQexec(conn.get(), query); if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0) { fprintf(stderr, "Rule %d not found\n", rule_ids[i]); @@ -536,7 +536,7 @@ int main() { // Check rules in runtime table for (int i = 0; i < num_tests; i++) { char query[256]; - sprintf(query, "SELECT * FROM disk.pgsql_query_rules WHERE rule_id = %d", rule_ids[i]); + snprintf(query, sizeof(query), "SELECT * FROM disk.pgsql_query_rules WHERE rule_id = %d", rule_ids[i]); PGresult* res = PQexec(conn.get(), query); if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0) { fprintf(stderr, "Rule %d not found\n", rule_ids[i]); diff --git a/test/tap/tests/pgsql-set_parameter_validation_test-t.cpp b/test/tap/tests/pgsql-set_parameter_validation_test-t.cpp index 71e5623caf..0d3935416f 100644 --- a/test/tap/tests/pgsql-set_parameter_validation_test-t.cpp +++ b/test/tap/tests/pgsql-set_parameter_validation_test-t.cpp @@ -19,15 +19,19 @@ using PGConnPtr = std::unique_ptr; enum ConnType { ADMIN, - BACKEND + BACKEND, + CLIENT }; PGConnPtr createNewConnection(ConnType conn_type, const std::string& options = "", bool with_ssl = false) { - - const char* host = (conn_type == BACKEND) ? cl.pgsql_host : cl.pgsql_admin_host; - int port = (conn_type == BACKEND) ? cl.pgsql_port : cl.pgsql_admin_port; - const char* username = (conn_type == BACKEND) ? cl.pgsql_root_username : cl.admin_username; - const char* password = (conn_type == BACKEND) ? cl.pgsql_root_password : cl.admin_password; + const char* host = (conn_type == ADMIN) ? cl.pgsql_admin_host : cl.pgsql_host; + int port = (conn_type == ADMIN) ? cl.pgsql_admin_port : cl.pgsql_port; + const char* username = (conn_type == ADMIN) ? cl.admin_username : + (conn_type == BACKEND ? cl.pgsql_root_username : cl.pgsql_username); + const char* password = (conn_type == ADMIN) ? cl.admin_password : + (conn_type == BACKEND ? cl.pgsql_root_password : cl.pgsql_password); + const char* connection_name = (conn_type == ADMIN) ? "Admin" : + (conn_type == BACKEND ? "Backend" : "Client"); std::stringstream ss; @@ -41,13 +45,23 @@ PGConnPtr createNewConnection(ConnType conn_type, const std::string& options = " PGconn* conn = PQconnectdb(ss.str().c_str()); if (PQstatus(conn) != CONNECTION_OK) { - fprintf(stderr, "Connection failed to '%s': %s", (conn_type == BACKEND ? "Backend" : "Admin"), PQerrorMessage(conn)); + fprintf(stderr, "Connection failed to '%s': %s", connection_name, PQerrorMessage(conn)); PQfinish(conn); return PGConnPtr(nullptr, &PQfinish); } return PGConnPtr(conn, &PQfinish); } +std::string queryCurrentUser(PGconn* conn) { + PGresult* res = PQexec(conn, "SELECT current_user"); + std::string username; + if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) { + username = PQgetvalue(res, 0, 0); + } + PQclear(res); + return username; +} + struct SetCommandTest { std::string command; bool expect_success; @@ -382,7 +396,7 @@ static int query_pgsql_set_parser_algorithm() { } int main(int argc, char** argv) { - int total_tests = 0; + int total_tests = 2; for (const auto& test_case : test_cases) { total_tests += test_case.commands.size(); @@ -397,11 +411,26 @@ int main(int argc, char** argv) { diag("pgsql-set_parser_algorithm = %d (per-case algo3 override %s)", parser_algorithm, parser_algorithm == 3 ? "ACTIVE" : "ignored"); + PGConnPtr client_conn = createNewConnection(ConnType::CLIENT, "", false); + if (!client_conn || PQstatus(client_conn.get()) != CONNECTION_OK) { + BAIL_OUT("Error: failed to create an unprivileged PostgreSQL connection"); + return exit_status(); + } + const std::string client_user = queryCurrentUser(client_conn.get()); + ok(client_user == cl.pgsql_username, + "unprivileged frontend retains its backend identity (expected '%s', got '%s')", + cl.pgsql_username, client_user.c_str()); + client_conn.reset(); + PGConnPtr conn = createNewConnection(ConnType::BACKEND, "", false); if (!conn || PQstatus(conn.get()) != CONNECTION_OK) { BAIL_OUT("Error: failed to connect to the database in file %s, line %d", __FILE__, __LINE__); return exit_status(); } + const std::string backend_user = queryCurrentUser(conn.get()); + ok(backend_user == cl.pgsql_root_username, + "privileged frontend does not reuse the unprivileged backend identity (expected '%s', got '%s')", + cl.pgsql_root_username, backend_user.c_str()); for (const auto& test_case : test_cases) { for (const auto& cmd_test : test_case.commands) { diff --git a/test/tap/tests/reg_test_1288-load-pgsql-variables-feedback-t.cpp b/test/tap/tests/reg_test_1288-load-pgsql-variables-feedback-t.cpp index d48a7d311e..5dcee7a37b 100644 --- a/test/tap/tests/reg_test_1288-load-pgsql-variables-feedback-t.cpp +++ b/test/tap/tests/reg_test_1288-load-pgsql-variables-feedback-t.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { if (snap) { MYSQL_ROW row = mysql_fetch_row(snap); if (row && row[0]) { - strncpy(original_pgsql_max_conn, row[0], sizeof(original_pgsql_max_conn) - 1); + snprintf(original_pgsql_max_conn, sizeof(original_pgsql_max_conn), "%s", row[0]); } mysql_free_result(snap); } diff --git a/test/tap/tests/reg_test_3585-stmt_metadata-t.cpp b/test/tap/tests/reg_test_3585-stmt_metadata-t.cpp index f40e959a39..9c947074a6 100644 --- a/test/tap/tests/reg_test_3585-stmt_metadata-t.cpp +++ b/test/tap/tests/reg_test_3585-stmt_metadata-t.cpp @@ -248,24 +248,24 @@ int insert_and_check(MYSQL_STMT *stmti, MYSQL_STMT *stmts, int id, char *name1, } char buf1[256], buf2[256]; if (ts1) { - sprintf(buf1,"%d:%d:%d", ts1->hour, ts1->minute, ts1->second); + snprintf(buf1,sizeof(buf1),"%u:%u:%u", ts1->hour, ts1->minute, ts1->second); } else { - sprintf(buf1,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); } if (is_null[2]) { - sprintf(buf2,"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } else { - sprintf(buf2,"%d:%d:%d", ts_res1.hour, ts_res1.minute, ts_res1.second); + snprintf(buf2,sizeof(buf2),"%u:%u:%u", ts_res1.hour, ts_res1.minute, ts_res1.second); } if (strcmp(buf1,buf2)==0) matches++; diag("time1 expected/retrieved: %s , %s", buf1, buf2); - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); if (i1) - sprintf(buf1, "%d", *i1); + snprintf(buf1,sizeof(buf1), "%d", *i1); if (!is_null[3]) - sprintf(buf2, "%d", i1_res); + snprintf(buf2,sizeof(buf2), "%d", i1_res); diag("i1 expected/retrieved: %s , %s", buf1, buf2); if (strcmp(buf1,buf2)==0) matches++; @@ -277,24 +277,24 @@ int insert_and_check(MYSQL_STMT *stmti, MYSQL_STMT *stmts, int id, char *name1, matches++; } if (ts2) { - sprintf(buf1,"%d:%d:%d", ts2->hour, ts2->minute, ts2->second); + snprintf(buf1,sizeof(buf1),"%u:%u:%u", ts2->hour, ts2->minute, ts2->second); } else { - sprintf(buf1,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); } if (is_null[5]) { - sprintf(buf2,"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } else { - sprintf(buf2,"%d:%d:%d", ts_res2.hour, ts_res2.minute, ts_res2.second); + snprintf(buf2,sizeof(buf2),"%u:%u:%u", ts_res2.hour, ts_res2.minute, ts_res2.second); } if (strcmp(buf1,buf2)==0) matches++; diag("time2 expected/retrieved: %s , %s", buf1, buf2); - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); if (i2) - sprintf(buf1, "%d", *i2); + snprintf(buf1,sizeof(buf1), "%d", *i2); if (!is_null[6]) - sprintf(buf2, "%d", i2_res); + snprintf(buf2,sizeof(buf2), "%d", i2_res); diag("i2 expected/retrieved: %s , %s", buf1, buf2); if (strcmp(buf1,buf2)==0) matches++; diff --git a/test/tap/tests/reg_test_3603-stmt_metadata-t.cpp b/test/tap/tests/reg_test_3603-stmt_metadata-t.cpp index 8afc9a8614..6c8231cc48 100644 --- a/test/tap/tests/reg_test_3603-stmt_metadata-t.cpp +++ b/test/tap/tests/reg_test_3603-stmt_metadata-t.cpp @@ -383,13 +383,13 @@ int update_and_check( } { - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); if (dur) - sprintf(buf1, "%ld", *dur); + snprintf(buf1,sizeof(buf1), "%ld", *dur); if (!is_null[3]) - sprintf(buf2, "%d", i_duration); + snprintf(buf2,sizeof(buf2), "%d", i_duration); diag("'duration' expected/retrieved: %s , %s", buf1, buf2); if (strcmp(buf1,buf2)==0) matches++; @@ -397,20 +397,20 @@ int update_and_check( { if (end_time) { - sprintf(buf1,"%d:%d:%d", end_time->hour, end_time->minute, end_time->second); + snprintf(buf1,sizeof(buf1),"%u:%u:%u", end_time->hour, end_time->minute, end_time->second); } else { - sprintf(buf1,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); } if (is_null[4]) { - sprintf(buf2,"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } else { - sprintf(buf2,"%d:%d:%d", ts_end_time.hour, ts_end_time.minute, ts_end_time.second); + snprintf(buf2,sizeof(buf2),"%u:%u:%u", ts_end_time.hour, ts_end_time.minute, ts_end_time.second); } if (strcmp(buf1,buf2)==0) matches++; diag("'end_time' expected/retrieved: %s , %s", buf1, buf2); - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } { @@ -434,13 +434,13 @@ int update_and_check( } { - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); if (mapping_id) - sprintf(buf1, "%d", *mapping_id); + snprintf(buf1,sizeof(buf1), "%d", *mapping_id); if (!is_null[7]) - sprintf(buf2, "%d", i_mapping_id); + snprintf(buf2,sizeof(buf2), "%d", i_mapping_id); diag("'mapping_id' expected/retrieved: %s , %s", buf1, buf2); if (strcmp(buf1,buf2)==0) matches++; @@ -468,20 +468,20 @@ int update_and_check( { if (st_time) { - sprintf(buf1,"%d:%d:%d", st_time->hour, st_time->minute, st_time->second); + snprintf(buf1,sizeof(buf1),"%u:%u:%u", st_time->hour, st_time->minute, st_time->second); } else { - sprintf(buf1,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); } if (is_null[10]) { - sprintf(buf2,"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } else { - sprintf(buf2,"%d:%d:%d", ts_st_time.hour, ts_st_time.minute, ts_st_time.second); + snprintf(buf2,sizeof(buf2),"%u:%u:%u", ts_st_time.hour, ts_st_time.minute, ts_st_time.second); } if (strcmp(buf1,buf2)==0) matches++; diag("'st_time' expected/retrieved: %s , %s", buf1, buf2); - sprintf(buf1,"NULL"); - sprintf(buf2,"NULL"); + snprintf(buf1,sizeof(buf1),"NULL"); + snprintf(buf2,sizeof(buf2),"NULL"); } { diff --git a/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp b/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp index 4dbba2cb85..7ce4cbb5d1 100644 --- a/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp +++ b/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp @@ -64,7 +64,7 @@ int main(int argc, char** argv) { char query[128]{}; diag("Generating simulated traffic..."); for (unsigned int i=0; i < QUERY_COUNT; i++) { - sprintf(query, "DO /*#%d#*/ %d", i, i); + snprintf(query, sizeof(query), "DO /*#%u#*/ %u", i, i); MYSQL_QUERY(proxysql, query); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } diff --git a/test/tap/tests/reg_test_stmt_resultset_err_no_rows-t.cpp b/test/tap/tests/reg_test_stmt_resultset_err_no_rows-t.cpp index f02fc7fd95..a357884470 100644 --- a/test/tap/tests/reg_test_stmt_resultset_err_no_rows-t.cpp +++ b/test/tap/tests/reg_test_stmt_resultset_err_no_rows-t.cpp @@ -106,8 +106,13 @@ int main(int argc, char** argv) { goto exit; } - strncpy(str_data, param.c_str(), STRING_SIZE); - str_length = strlen(str_data); + size_t copy_len = param.size(); + if (copy_len >= STRING_SIZE) { + copy_len = STRING_SIZE - 1; + } + memcpy(str_data, param.data(), copy_len); + str_data[copy_len] = 0; + str_length = copy_len; int exec_res = mysql_stmt_execute(stmt); if (exec_res) { diff --git a/test/tap/tests/set_testing-240-t.cpp b/test/tap/tests/set_testing-240-t.cpp index 467cd2c740..99d983cbfb 100644 --- a/test/tap/tests/set_testing-240-t.cpp +++ b/test/tap/tests/set_testing-240-t.cpp @@ -281,7 +281,13 @@ void * my_conn_thread(void *arg) { usleep(sleepDelay * 1000); char query[128]; - sprintf(query, "SELECT /* %p %s */ %d;", mysql, paddress.c_str(), sleepDelay); + const int query_len = snprintf(query, sizeof(query), "SELECT /* %p %s */ %d;", mysql, paddress.c_str(), sleepDelay); + if (query_len < 0 || (size_t)query_len >= sizeof(query)) { + diag("Skipping truncated query for address of length %zu", paddress.size()); + select_ERR++; + __sync_fetch_and_add(&g_select_ERR,1); + continue; + } if (mysql_query(mysql,query)) { select_ERR++; __sync_fetch_and_add(&g_select_ERR,1); diff --git a/test/tap/tests/set_testing-multi-t.cpp b/test/tap/tests/set_testing-multi-t.cpp index 4b03581bdc..12676d112c 100644 --- a/test/tap/tests/set_testing-multi-t.cpp +++ b/test/tap/tests/set_testing-multi-t.cpp @@ -197,7 +197,7 @@ void * my_conn_thread(void *arg) { usleep(sleepDelay * 1000); char query[128]; - sprintf(query, "SELECT /* %p */ %d;", mysql, sleepDelay); + snprintf(query, sizeof(query), "SELECT /* %p */ %d;", mysql, sleepDelay); if (mysql_query(mysql,query)) { select_ERR++; __sync_fetch_and_add(&g_select_ERR,1); diff --git a/test/tap/tests/set_testing-t.cpp b/test/tap/tests/set_testing-t.cpp index e65c88500e..e1b9adb29d 100644 --- a/test/tap/tests/set_testing-t.cpp +++ b/test/tap/tests/set_testing-t.cpp @@ -207,7 +207,13 @@ void * my_conn_thread(void *arg) { usleep(sleepDelay * 1000); char query[128]; - sprintf(query, "SELECT /* %p %s */ %d;", mysql, paddress.c_str(), sleepDelay); + const int query_len = snprintf(query, sizeof(query), "SELECT /* %p %s */ %d;", mysql, paddress.c_str(), sleepDelay); + if (query_len < 0 || (size_t)query_len >= sizeof(query)) { + diag("Skipping truncated query for address of length %zu", paddress.size()); + select_ERR++; + __sync_fetch_and_add(&g_select_ERR,1); + continue; + } if (mysql_query(mysql,query)) { select_ERR++; __sync_fetch_and_add(&g_select_ERR,1); diff --git a/test/tap/tests/test_cluster_sync-t.cpp b/test/tap/tests/test_cluster_sync-t.cpp index 4b2be03655..10b82af49d 100644 --- a/test/tap/tests/test_cluster_sync-t.cpp +++ b/test/tap/tests/test_cluster_sync-t.cpp @@ -121,7 +121,7 @@ const char* get_cluster_visible_host() { static char buf[256] = {}; if (buf[0]) return buf; if (gethostname(buf, sizeof(buf)) != 0) { - strncpy(buf, R_HOST, sizeof(buf) - 1); + snprintf(buf, sizeof(buf), "%s", R_HOST); } return buf; } diff --git a/test/tap/tests/test_cluster_sync_mysql_servers-t.cpp b/test/tap/tests/test_cluster_sync_mysql_servers-t.cpp index d653a762ca..158a7e9257 100644 --- a/test/tap/tests/test_cluster_sync_mysql_servers-t.cpp +++ b/test/tap/tests/test_cluster_sync_mysql_servers-t.cpp @@ -75,7 +75,7 @@ const char* get_cluster_visible_host() { static char buf[256] = {}; if (buf[0]) return buf; if (gethostname(buf, sizeof(buf)) != 0) { - strncpy(buf, "127.0.0.1", sizeof(buf) - 1); + snprintf(buf, sizeof(buf), "%s", "127.0.0.1"); } return buf; } diff --git a/test/tap/tests/test_ps_hg_routing-t.cpp b/test/tap/tests/test_ps_hg_routing-t.cpp index 02a514f111..2e5fb85fa8 100644 --- a/test/tap/tests/test_ps_hg_routing-t.cpp +++ b/test/tap/tests/test_ps_hg_routing-t.cpp @@ -47,7 +47,7 @@ int main(int argc, char** argv) { MYSQL_QUERY(mysql, "create database if not exists test"); MYSQL_QUERY(mysql, "drop table if exists test.ps_hg_routing"); - sprintf(buf, "create table if not exists test.ps_hg_routing (c1 varchar(%d) primary key, c2 varchar(%d))", STRING_SIZE, STRING_SIZE); + snprintf(buf, sizeof(buf), "create table if not exists test.ps_hg_routing (c1 varchar(%d) primary key, c2 varchar(%d))", STRING_SIZE, STRING_SIZE); MYSQL_QUERY(mysql, buf); MYSQL_QUERY(mysql, "insert into test.ps_hg_routing (c1,c2) values ('abcdef', 'abcdef')"); @@ -158,4 +158,3 @@ int main(int argc, char** argv) { mysql_close(mysql); mysql_close(mysqladmin); } - diff --git a/test/tap/tests/test_read_only_actions_offline_hard_servers-t.cpp b/test/tap/tests/test_read_only_actions_offline_hard_servers-t.cpp index 8e8fc5c0fa..ba71f150af 100644 --- a/test/tap/tests/test_read_only_actions_offline_hard_servers-t.cpp +++ b/test/tap/tests/test_read_only_actions_offline_hard_servers-t.cpp @@ -185,7 +185,7 @@ int set_read_only_value(const std::string& host, uint16_t port, const std::strin } char query[256]; - sprintf(query, "SET @@global.read_only=%d", read_only_val); + snprintf(query, sizeof(query), "SET @@global.read_only=%d", read_only_val); rc_query = mysql_query(mysqldb,query); diff --git a/test/tap/tests/unit/ffto_state_machine_unit-t.cpp b/test/tap/tests/unit/ffto_state_machine_unit-t.cpp index 5256d9c5c5..090752ff47 100644 --- a/test/tap/tests/unit/ffto_state_machine_unit-t.cpp +++ b/test/tap/tests/unit/ffto_state_machine_unit-t.cpp @@ -9,6 +9,7 @@ #include #include +#include extern __thread int mysql_thread___ffto_max_buffer_size; extern __thread int pgsql_thread___ffto_max_buffer_size; @@ -92,7 +93,7 @@ static void test_pgsql_ffto_simple_query_message() { pgsql_thread___ffto_max_buffer_size = 16 * 1024 * 1024; PgSQLFFTO ffto(nullptr); const char* query = "SELECT 1"; - size_t qlen = strlen(query) + 1; + const size_t qlen = std::string_view(query).size() + 1; uint32_t msg_len = htonl((uint32_t)(qlen + 4)); std::vector msg(1 + 4 + qlen); msg[0] = 'Q'; @@ -124,7 +125,7 @@ static void test_pgsql_ffto_parse_message() { */ const char* query = "SELECT 1"; const size_t name_len = 1; /* empty name + NUL */ - const size_t query_len = strlen(query) + 1; + const size_t query_len = std::string_view(query).size() + 1; const size_t payload_len = name_len + query_len + 2; const uint32_t wire_len = (uint32_t)(4 + payload_len); uint32_t msg_len_be = htonl(wire_len); diff --git a/test/tap/tests/unit/genai_mcp_thread_unit-t.cpp b/test/tap/tests/unit/genai_mcp_thread_unit-t.cpp index 22d62b82c6..286101c0f5 100644 --- a/test/tap/tests/unit/genai_mcp_thread_unit-t.cpp +++ b/test/tap/tests/unit/genai_mcp_thread_unit-t.cpp @@ -35,10 +35,9 @@ /* Helper: get a variable value as std::string */ /* ------------------------------------------------------------------ */ static std::string get_var(MCP_Threads_Handler& h, const char* name) { - char buf[4096] = {0}; - int rc = h.get_variable(name, buf); - if (rc != 0) return "__ERROR__"; - return std::string(buf); + std::string value; + if (!h.get_variable_string(name, value)) return "__ERROR__"; + return value; } /* ================================================================== */ @@ -361,11 +360,13 @@ static void test_get_variables_list(MCP_Threads_Handler& h) { static void test_null_safety(MCP_Threads_Handler& h) { char buf[256]; - ok(h.get_variable(nullptr, buf) == -1, + ok(h.get_variable(nullptr, buf, sizeof(buf)) == -1, "get_variable(nullptr, buf) = -1"); - ok(h.get_variable("enabled", nullptr) == -1, + ok(h.get_variable("enabled", nullptr, sizeof(buf)) == -1, "get_variable(enabled, nullptr) = -1"); - ok(h.get_variable(nullptr, nullptr) == -1, + ok(h.get_variable("enabled", buf, 0) == -1, + "get_variable(enabled, buf, 0) = -1"); + ok(h.get_variable(nullptr, nullptr, 0) == -1, "get_variable(nullptr, nullptr) = -1"); ok(h.set_variable(nullptr, "true") == -1, @@ -376,6 +377,23 @@ static void test_null_safety(MCP_Threads_Handler& h) { "set_variable(nullptr, nullptr) = -1"); } +/** + * @brief Bounded get_variable() rejects values that would be truncated. + */ +static void test_bounded_get_variable(MCP_Threads_Handler& h) { + const std::string long_value(4096, 'x'); + ok(h.set_variable("config_endpoint_auth", long_value.c_str()) == 0, + "set long config_endpoint_auth value"); + + char buf[16]; + memset(buf, 'x', sizeof(buf)); + ok(h.get_variable("config_endpoint_auth", buf, sizeof(buf)) == -1 && buf[0] == '\0', + "get_variable rejects and clears a truncated value"); + + ok(h.set_variable("config_endpoint_auth", "") == 0, + "reset config_endpoint_auth after bounded read test"); +} + /** * @brief get_variable_string() should overwrite stale output. */ @@ -392,9 +410,9 @@ static void test_get_variable_string_contract(MCP_Threads_Handler& h) { */ static void test_get_unknown_variable(MCP_Threads_Handler& h) { char buf[256]; - ok(h.get_variable("nonexistent", buf) == -1, + ok(h.get_variable("nonexistent", buf, sizeof(buf)) == -1, "get_variable(nonexistent) = -1"); - ok(h.get_variable("", buf) == -1, + ok(h.get_variable("", buf, sizeof(buf)) == -1, "get_variable(empty) = -1"); } @@ -450,7 +468,8 @@ static void test_wrlock_wrunlock(MCP_Threads_Handler& h) { * String variables: 7 vars * 6 tests each = 42 * has_variable: 13 * get_variables_list: 2 + 14 = 16 - * Null safety: 6 + * Null safety: 7 + * Bounded get_variable: 3 * get_variable_string: 2 * Get unknown: 2 * Set unknown: 2 @@ -458,9 +477,9 @@ static void test_wrlock_wrunlock(MCP_Threads_Handler& h) { * Load target auth null: 1 * wrlock/wrunlock: 1 * ------------------------------------------------- - * Total: 199 + * Total: 203 */ -static const int TOTAL_TESTS = 199; +static const int TOTAL_TESTS = 203; int main() { plan(TOTAL_TESTS); @@ -477,6 +496,7 @@ int main() { test_has_variable(handler); test_get_variables_list(handler); test_null_safety(handler); + test_bounded_get_variable(handler); test_get_variable_string_contract(handler); test_get_unknown_variable(handler); test_set_unknown_variable(handler); diff --git a/test/tap/tests/unit/glovars_unit-t.cpp b/test/tap/tests/unit/glovars_unit-t.cpp index 61da3289b1..c39ca2cdae 100644 --- a/test/tap/tests/unit/glovars_unit-t.cpp +++ b/test/tap/tests/unit/glovars_unit-t.cpp @@ -162,6 +162,28 @@ static void test_checksum_value_set() { ok(spaces_replaced, "set_checksum(spaces): positions 2-17 all replaced with '0'"); } +static void test_checksum_value_short_input() { + ProxySQL_Checksum_Value cv; + struct { + char input[5]; + char guard[15]; + } source; + memcpy(source.input, "0x12", sizeof(source.input)); + memset(source.guard, 'X', sizeof(source.guard)); + + cv.set_checksum(source.input); + + bool zero_padded = true; + for (int i = 4; i < 18; i++) { + if (cv.checksum[i] != '0') { + zero_padded = false; + break; + } + } + ok(zero_padded, + "set_checksum(short input): zero-pads without reading beyond the source string"); +} + static void test_checksum_value_shutdown_flag() { // Normal destruction (in_shutdown == false): no crash { @@ -415,7 +437,7 @@ static void test_replace_checksum_zeros() { } int main() { - plan(78); + plan(79); test_init_minimal(); @@ -425,6 +447,7 @@ int main() { // Checksum value (16 tests) test_checksum_value_defaults(); // 5 test_checksum_value_set(); // 9 + test_checksum_value_short_input(); // 1 test_checksum_value_shutdown_flag(); // 2 // Checksum value version/epoch (6 tests) diff --git a/test/tap/tests/unit/parsersql_unit-t.cpp b/test/tap/tests/unit/parsersql_unit-t.cpp index d7dc818115..bdf1c58e9a 100644 --- a/test/tap/tests/unit/parsersql_unit-t.cpp +++ b/test/tap/tests/unit/parsersql_unit-t.cpp @@ -6,14 +6,19 @@ #include #include +#include #include #include +static inline size_t str_view_len(const char *s) { + return s ? std::string_view{s}.size() : 0; +} + static void test_mysql_digest_select() { SQP_par_t qp; memset(&qp, 0, sizeof(qp)); const char* q = "SELECT * FROM t1 WHERE id = 1"; - parsersql_digest_init_mysql(&qp, q, strlen(q)); + parsersql_digest_init_mysql(&qp, q, str_view_len(q)); ok(qp.digest_text != NULL, "MySQL digest: SELECT produces digest_text"); ok(qp.digest != 0, "MySQL digest: SELECT produces non-zero hash"); if (qp.digest_text) { @@ -26,7 +31,7 @@ static void test_mysql_digest_insert() { SQP_par_t qp; memset(&qp, 0, sizeof(qp)); const char* q = "INSERT INTO t1 (a, b) VALUES (1, 'hello')"; - parsersql_digest_init_mysql(&qp, q, strlen(q)); + parsersql_digest_init_mysql(&qp, q, str_view_len(q)); ok(qp.digest_text != NULL, "MySQL digest: INSERT produces digest_text"); ok(qp.digest != 0, "MySQL digest: INSERT produces non-zero hash"); if (qp.digest_text) free(qp.digest_text); @@ -38,8 +43,8 @@ static void test_mysql_digest_same_for_different_literals() { memset(&qp2, 0, sizeof(qp2)); const char* q1 = "SELECT * FROM t1 WHERE id = 1"; const char* q2 = "SELECT * FROM t1 WHERE id = 999"; - parsersql_digest_init_mysql(&qp1, q1, strlen(q1)); - parsersql_digest_init_mysql(&qp2, q2, strlen(q2)); + parsersql_digest_init_mysql(&qp1, q1, str_view_len(q1)); + parsersql_digest_init_mysql(&qp2, q2, str_view_len(q2)); ok(qp1.digest == qp2.digest, "MySQL digest: same query with different literals produces same hash"); if (qp1.digest_text) free(qp1.digest_text); if (qp2.digest_text) free(qp2.digest_text); @@ -51,8 +56,8 @@ static void test_mysql_digest_different_queries() { memset(&qp2, 0, sizeof(qp2)); const char* q1 = "SELECT * FROM t1 WHERE id = 1"; const char* q2 = "SELECT * FROM t2 WHERE id = 1"; - parsersql_digest_init_mysql(&qp1, q1, strlen(q1)); - parsersql_digest_init_mysql(&qp2, q2, strlen(q2)); + parsersql_digest_init_mysql(&qp1, q1, str_view_len(q1)); + parsersql_digest_init_mysql(&qp2, q2, str_view_len(q2)); ok(qp1.digest != qp2.digest, "MySQL digest: different tables produce different hashes"); if (qp1.digest_text) free(qp1.digest_text); if (qp2.digest_text) free(qp2.digest_text); @@ -62,7 +67,7 @@ static void test_pgsql_digest_select() { SQP_par_t qp; memset(&qp, 0, sizeof(qp)); const char* q = "SELECT * FROM t1 WHERE id = 1"; - parsersql_digest_init_pgsql(&qp, q, strlen(q)); + parsersql_digest_init_pgsql(&qp, q, str_view_len(q)); ok(qp.digest_text != NULL, "PgSQL digest: SELECT produces digest_text"); ok(qp.digest != 0, "PgSQL digest: SELECT produces non-zero hash"); if (qp.digest_text) free(qp.digest_text); @@ -74,8 +79,8 @@ static void test_pgsql_digest_same_for_different_literals() { memset(&qp2, 0, sizeof(qp2)); const char* q1 = "SELECT * FROM t1 WHERE id = 1"; const char* q2 = "SELECT * FROM t1 WHERE id = 999"; - parsersql_digest_init_pgsql(&qp1, q1, strlen(q1)); - parsersql_digest_init_pgsql(&qp2, q2, strlen(q2)); + parsersql_digest_init_pgsql(&qp1, q1, str_view_len(q1)); + parsersql_digest_init_pgsql(&qp2, q2, str_view_len(q2)); ok(qp1.digest == qp2.digest, "PgSQL digest: same query with different literals produces same hash"); if (qp1.digest_text) free(qp1.digest_text); if (qp2.digest_text) free(qp2.digest_text); @@ -83,145 +88,145 @@ static void test_pgsql_digest_same_for_different_literals() { static void test_mysql_command_type_select() { const char* q = "SELECT 1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_SELECT, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_SELECT, "MySQL cmd: SELECT → SELECT"); } static void test_mysql_command_type_insert() { const char* q = "INSERT INTO t1 VALUES (1)"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_INSERT, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_INSERT, "MySQL cmd: INSERT → INSERT"); } static void test_mysql_command_type_update() { const char* q = "UPDATE t1 SET a = 1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_UPDATE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_UPDATE, "MySQL cmd: UPDATE → UPDATE"); } static void test_mysql_command_type_delete() { const char* q = "DELETE FROM t1 WHERE id = 1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_DELETE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_DELETE, "MySQL cmd: DELETE → DELETE"); } static void test_mysql_command_type_set() { const char* q = "SET @a = 1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_SET, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_SET, "MySQL cmd: SET → SET"); } static void test_mysql_command_type_begin() { const char* q = "BEGIN"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_BEGIN, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_BEGIN, "MySQL cmd: BEGIN → BEGIN"); } static void test_mysql_command_type_commit() { const char* q = "COMMIT"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_COMMIT, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_COMMIT, "MySQL cmd: COMMIT → COMMIT"); } static void test_mysql_command_type_rollback() { const char* q = "ROLLBACK"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_ROLLBACK, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_ROLLBACK, "MySQL cmd: ROLLBACK → ROLLBACK"); } static void test_mysql_command_type_create_table() { const char* q = "CREATE TABLE t1 (id INT)"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_CREATE_TABLE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_CREATE_TABLE, "MySQL cmd: CREATE TABLE → CREATE_TABLE"); } static void test_mysql_command_type_drop_table() { const char* q = "DROP TABLE t1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_DROP_TABLE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_DROP_TABLE, "MySQL cmd: DROP TABLE → DROP_TABLE"); } static void test_mysql_command_type_show() { const char* q = "SHOW TABLES"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_SHOW, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_SHOW, "MySQL cmd: SHOW → SHOW"); } static void test_mysql_command_type_use() { const char* q = "USE mydb"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_USE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_USE, "MySQL cmd: USE → USE"); } static void test_mysql_command_type_prepare() { const char* q = "PREPARE stmt FROM 'SELECT 1'"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_PREPARE, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_PREPARE, "MySQL cmd: PREPARE → PREPARE"); } static void test_mysql_command_type_explain() { const char* q = "EXPLAIN SELECT 1"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_EXPLAIN, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_EXPLAIN, "MySQL cmd: EXPLAIN → EXPLAIN"); } static void test_pgsql_command_type_select() { const char* q = "SELECT 1"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_SELECT, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_SELECT, "PgSQL cmd: SELECT → SELECT"); } static void test_pgsql_command_type_insert() { const char* q = "INSERT INTO t1 VALUES (1)"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_INSERT, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_INSERT, "PgSQL cmd: INSERT → INSERT"); } static void test_pgsql_command_type_update() { const char* q = "UPDATE t1 SET a = 1"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_UPDATE, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_UPDATE, "PgSQL cmd: UPDATE → UPDATE"); } static void test_pgsql_command_type_delete() { const char* q = "DELETE FROM t1 WHERE id = 1"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_DELETE, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_DELETE, "PgSQL cmd: DELETE → DELETE"); } static void test_pgsql_command_type_set() { const char* q = "SET search_path TO public"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_SET, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_SET, "PgSQL cmd: SET → SET"); } static void test_pgsql_command_type_begin() { const char* q = "BEGIN"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_BEGIN, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_BEGIN, "PgSQL cmd: BEGIN → BEGIN"); } static void test_pgsql_command_type_commit() { const char* q = "COMMIT"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_COMMIT, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_COMMIT, "PgSQL cmd: COMMIT → COMMIT"); } static void test_pgsql_command_type_show() { const char* q = "SHOW search_path"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_SHOW, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_SHOW, "PgSQL cmd: SHOW → SHOW"); } static void test_pgsql_command_type_truncate() { const char* q = "TRUNCATE TABLE t1"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_TRUNCATE, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_TRUNCATE, "PgSQL cmd: TRUNCATE → TRUNCATE"); } static void test_pgsql_command_type_reset() { const char* q = "RESET ALL"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_RESET, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_RESET, "PgSQL cmd: RESET → RESET"); } @@ -289,13 +294,13 @@ static void test_mysql_digest_empty_query() { static void test_mysql_command_type_unknown() { const char* q = "THISISNOTASQLCOMMAND"; - ok(parsersql_command_type_mysql(q, strlen(q)) == MYSQL_COM_QUERY_UNKNOWN, + ok(parsersql_command_type_mysql(q, str_view_len(q)) == MYSQL_COM_QUERY_UNKNOWN, "MySQL cmd: garbage → UNKNOWN"); } static void test_pgsql_command_type_unknown() { const char* q = "THISISNOTASQLCOMMAND"; - ok(parsersql_command_type_pgsql(q, strlen(q)) == PGSQL_QUERY_UNKNOWN, + ok(parsersql_command_type_pgsql(q, str_view_len(q)) == PGSQL_QUERY_UNKNOWN, "PgSQL cmd: garbage → UNKNOWN"); } diff --git a/tools/bench_connect.c b/tools/bench_connect.c index e972ecb8de..c65bc8df5f 100644 --- a/tools/bench_connect.c +++ b/tools/bench_connect.c @@ -124,13 +124,19 @@ int main(int argc, char **argv) { // NOSONAR: benchmark tool, cognitive complexi /* Launch threads */ pthread_t *tids = calloc(threads, sizeof(pthread_t)); struct thread_arg *args = calloc(threads, sizeof(struct thread_arg)); + if (tids == NULL || args == NULL) { + fprintf(stderr, "Unable to allocate benchmark thread state\n"); + free(tids); + free(args); + return 1; + } struct timespec wall0, wall1; clock_gettime(CLOCK_MONOTONIC, &wall0); for (int t = 0; t < threads; t++) { args[t].thread_id = t; - strncpy(args[t].conninfo, conninfo, sizeof(args[t].conninfo) - 1); + snprintf(args[t].conninfo, sizeof(args[t].conninfo), "%s", conninfo); args[t].iterations = iterations; args[t].warmup = warmup; pthread_create(&tids[t], NULL, thread_worker, &args[t]); diff --git a/tools/eventslog_reader_sample.cpp b/tools/eventslog_reader_sample.cpp index 44377c2405..bd1ae1103a 100644 --- a/tools/eventslog_reader_sample.cpp +++ b/tools/eventslog_reader_sample.cpp @@ -170,7 +170,7 @@ class MySQL_Event { read_encoded_length((uint64_t *)&rows_sent,f); read_encoded_length((uint64_t *)&query_digest,f); char digest_hex[20]; - sprintf(digest_hex,"0x%016llX", (long long unsigned int)query_digest); + snprintf(digest_hex, sizeof(digest_hex), "0x%016llX", (long long unsigned int)query_digest); read_encoded_length((uint64_t *)&query_len,f); query_ptr=read_string(f,query_len); char buffer[26]; @@ -180,12 +180,12 @@ class MySQL_Event { timer=start_time/1000/1000; tm_info = localtime(&timer); strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info); - sprintf(buffer2,"%06u", (unsigned)(start_time%1000000)); + snprintf(buffer2, sizeof(buffer2), "%06u", (unsigned)(start_time%1000000)); cout << " starttime=\"" << buffer << "." << buffer2 << "\""; timer=end_time/1000/1000; tm_info = localtime(&timer); strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info); - sprintf(buffer2,"%06u", (unsigned)(end_time%1000000)); + snprintf(buffer2, sizeof(buffer2), "%06u", (unsigned)(end_time%1000000)); cout << " endtime=\"" << buffer << "." << buffer2 << "\""; cout << " duration=" << (end_time-start_time) << "us"; if (et == PROXYSQL_COM_STMT_PREPARE || et == PROXYSQL_COM_STMT_EXECUTE) {