diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index f496db4e72b..d87d4269f89 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -569,14 +569,14 @@ static int file_exists(char * filename) @retval int error = 1, success = 0 */ -static int search_dir(const char * base_path, const char *tool_name, +static int search_dir(const char *base_path, const char *tool_name, const char *subdir, char *tool_path) { char new_path[FN_REFLEN]; char source_path[FN_REFLEN]; - strcpy(source_path, base_path); - strcat(source_path, subdir); + safe_strcpy(source_path, sizeof(source_path), base_path); + safe_strcat(source_path, sizeof(source_path), subdir); fn_format(new_path, tool_name, source_path, "", MY_UNPACK_FILENAME); if (file_exists(new_path)) { @@ -632,7 +632,7 @@ static int load_plugin_data(char *plugin_name, char *config_file) FILE *file_ptr; char path[FN_REFLEN]; char line[1024]; - char *reason= 0; + const char *reason= 0; char *res; int i= -1; @@ -643,14 +643,14 @@ static int load_plugin_data(char *plugin_name, char *config_file) } if (!file_exists(opt_plugin_ini)) { - reason= (char *)"File does not exist."; + reason= "File does not exist."; goto error; } file_ptr= fopen(opt_plugin_ini, "r"); if (file_ptr == NULL) { - reason= (char *)"Cannot open file."; + reason= "Cannot open file."; goto error; } @@ -660,17 +660,20 @@ static int load_plugin_data(char *plugin_name, char *config_file) /* Read plugin components */ while (i < 16) { + size_t line_len; + res= fgets(line, sizeof(line), file_ptr); + line_len= strlen(line); + /* strip /n */ - if (line[strlen(line)-1] == '\n') - { - line[strlen(line)-1]= '\0'; - } + if (line[line_len - 1] == '\n') + line[line_len - 1]= '\0'; + if (res == NULL) { if (i < 1) { - reason= (char *)"Bad format in plugin configuration file."; + reason= "Bad format in plugin configuration file."; fclose(file_ptr); goto error; } @@ -683,14 +686,19 @@ static int load_plugin_data(char *plugin_name, char *config_file) if (i == -1) /* if first pass, read this line as so_name */ { /* Add proper file extension for soname */ - strcat(line, FN_SOEXT); + if (safe_strcpy(line + line_len - 1, sizeof(line), FN_SOEXT)) + { + reason= "Plugin name too long."; + fclose(file_ptr); + goto error; + } /* save so_name */ plugin_data.so_name= my_strdup(line, MYF(MY_WME|MY_ZEROFILL)); i++; } else { - if (strlen(line) > 0) + if (line_len > 0) { plugin_data.components[i]= my_strdup(line, MYF(MY_WME)); i++; @@ -779,14 +787,13 @@ static int check_options(int argc, char **argv, char *operation) /* read the plugin config file and check for match against argument */ else { - if (strlen(argv[i]) + 4 + 1 > FN_REFLEN) + if (safe_strcpy(plugin_name, sizeof(plugin_name), argv[i]) || + safe_strcpy(config_file, sizeof(config_file), argv[i]) || + safe_strcat(config_file, sizeof(config_file), ".ini")) { fprintf(stderr, "ERROR: argument is too long.\n"); return 1; } - strcpy(plugin_name, argv[i]); - strcpy(config_file, argv[i]); - strcat(config_file, ".ini"); } } @@ -855,35 +862,30 @@ static int check_options(int argc, char **argv, char *operation) static int process_options(int argc, char *argv[], char *operation) { int error= 0; - int i= 0; /* Parse and execute command-line options */ if ((error= handle_options(&argc, &argv, my_long_options, get_one_option))) - goto exit; + return error; /* If the print defaults option used, exit. */ if (opt_print_defaults) - { - error= -1; - goto exit; - } + return -1; /* Add a trailing directory separator if not present */ if (opt_basedir) { - i= (int)strlength(opt_basedir); - if (opt_basedir[i-1] != FN_LIBCHAR || opt_basedir[i-1] != FN_LIBCHAR2) + size_t basedir_len= strlength(opt_basedir); + if (opt_basedir[basedir_len - 1] != FN_LIBCHAR || + opt_basedir[basedir_len - 1] != FN_LIBCHAR2) { char buff[FN_REFLEN]; - memset(buff, 0, sizeof(buff)); + if (basedir_len + 2 > FN_REFLEN) + return -1; - strncpy(buff, opt_basedir, sizeof(buff) - 1); -#ifdef __WIN__ - strncat(buff, "/", sizeof(buff) - strlen(buff) - 1); -#else - strncat(buff, FN_DIRSEP, sizeof(buff) - strlen(buff) - 1); -#endif - buff[sizeof(buff) - 1]= 0; + memcpy(buff, opt_basedir, basedir_len); + buff[basedir_len]= '/'; + buff[basedir_len + 1]= '\0'; + my_free(opt_basedir); opt_basedir= my_strdup(buff, MYF(MY_FAE)); } @@ -895,10 +897,7 @@ static int process_options(int argc, char *argv[], char *operation) generated when the defaults were read from the file, exit. */ if (!opt_no_defaults && ((error= get_default_values()))) - { - error= -1; - goto exit; - } + return -1; /* Check to ensure required options are present and validate the operation. @@ -906,11 +905,9 @@ static int process_options(int argc, char *argv[], char *operation) read a configuration file named .ini from the --plugin-dir or --plugin-ini location if the --plugin-ini option presented. */ - strcpy(operation, ""); - if ((error = check_options(argc, argv, operation))) - { - goto exit; - } + operation[0]= '\0'; + if ((error= check_options(argc, argv, operation))) + return error; if (opt_verbose) { @@ -922,8 +919,7 @@ static int process_options(int argc, char *argv[], char *operation) printf("# lc_messages_dir = %s\n", opt_lc_messages_dir); } -exit: - return error; + return 0; } diff --git a/client/mysqldump.c b/client/mysqldump.c index 294f29b7acd..b382dd41d08 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2478,7 +2478,7 @@ static uint dump_events_for_db(char *db) if (mysql_query_with_error_report(mysql, &event_list_res, "show events")) DBUG_RETURN(0); - strcpy(delimiter, ";"); + safe_strcpy(delimiter, sizeof(delimiter), ";"); if (mysql_num_rows(event_list_res) > 0) { if (opt_xml) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 61bb3822d36..e0bd37dd934 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6171,7 +6171,9 @@ int do_done(struct st_command *command) if (*cur_block->delim) { /* Restore "old" delimiter after false if block */ - strcpy (delimiter, cur_block->delim); + if (safe_strcpy(delimiter, sizeof(delimiter), cur_block->delim)) + die("Delimiter too long, truncated"); + delimiter_length= strlen(delimiter); } /* Pop block from stack, goto next line */ @@ -6426,10 +6428,12 @@ void do_block(enum block_cmd cmd, struct st_command* command) if (cur_block->ok) { cur_block->delim[0]= '\0'; - } else + } + else { /* Remember "old" delimiter if entering a false if block */ - strcpy (cur_block->delim, delimiter); + if (safe_strcpy(cur_block->delim, sizeof(cur_block->delim), delimiter)) + die("Delimiter too long, truncated"); } DBUG_PRINT("info", ("OK: %d", cur_block->ok)); @@ -11301,9 +11305,8 @@ static int setenv(const char *name, const char *value, int overwrite) char *envvar= (char *)malloc(buflen); if(!envvar) return ENOMEM; - strcpy(envvar, name); - strcat(envvar, "="); - strcat(envvar, value); + + snprintf(envvar, buflen, "%s=%s", name, value); putenv(envvar); return 0; } diff --git a/dbug/dbug.c b/dbug/dbug.c index 17567585bfd..9c1371730be 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -508,7 +508,7 @@ static int DbugParse(CODE_STATE *cs, const char *control) stack->delay= stack->next->delay; stack->maxdepth= stack->next->maxdepth; stack->sub_level= stack->next->sub_level; - strcpy(stack->name, stack->next->name); + safe_strcpy(stack->name, sizeof(stack->name), stack->next->name); stack->out_file= stack->next->out_file; stack->out_file->used++; if (stack->next == &init_settings) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 3169b647ea2..a65114a1679 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -844,7 +844,7 @@ parse_page( { unsigned long long id; uint16_t undo_page_type; - char str[20]={'\0'}; + const char *str; ulint n_recs; uint32_t page_no, left_page_no, right_page_no; ulint data_bytes; @@ -852,11 +852,7 @@ parse_page( ulint size_range_id; /* Check whether page is doublewrite buffer. */ - if(skip_page) { - strcpy(str, "Double_write_buffer"); - } else { - strcpy(str, "-"); - } + str = skip_page ? "Double_write_buffer" : "-"; switch (mach_read_from_2(page + FIL_PAGE_TYPE)) { diff --git a/extra/mariabackup/xbcloud.cc b/extra/mariabackup/xbcloud.cc index fed937be834..cee76e5f3d7 100644 --- a/extra/mariabackup/xbcloud.cc +++ b/extra/mariabackup/xbcloud.cc @@ -1676,8 +1676,11 @@ container_list_add_object(container_list *list, const char *name, list->object_count += object_count_step; } assert(list->idx <= list->object_count); - strcpy(list->objects[list->idx].name, name); - strcpy(list->objects[list->idx].hash, hash); + safe_strcpy(list->objects[list->idx].name, + sizeof(list->objects[list->idx].name), name); + safe_strcpy(list->objects[list->idx].hash, + sizeof(list->objects[list->idx].hash), hash); + list->objects[list->idx].bytes = bytes; ++list->idx; } diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index f7910fc9c23..ee954919a55 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4235,11 +4235,13 @@ static bool xtrabackup_backup_low() dst_log_file = NULL; - if(!xtrabackup_incremental) { - strcpy(metadata_type, "full-backuped"); + if (!xtrabackup_incremental) { + safe_strcpy(metadata_type, sizeof(metadata_type), + "full-backuped"); metadata_from_lsn = 0; } else { - strcpy(metadata_type, "incremental"); + safe_strcpy(metadata_type, sizeof(metadata_type), + "incremental"); metadata_from_lsn = incremental_lsn; } metadata_last_lsn = log_copy_scanned_lsn; @@ -5987,7 +5989,8 @@ static bool xtrabackup_prepare_func(char** argv) if (ok) { char filename[FN_REFLEN]; - strcpy(metadata_type, "log-applied"); + safe_strcpy(metadata_type, sizeof(metadata_type), + "log-applied"); if(xtrabackup_incremental && metadata_to_lsn < incremental_to_lsn) diff --git a/include/m_string.h b/include/m_string.h index e967f140dc4..8edaf19bc0a 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -225,6 +225,44 @@ static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str, lex_str->length= len; } +/* + Copies src into dst and ensures dst is a NULL terminated C string. + + Returns 1 if the src string was truncated due to too small size of dst. + Returns 0 if src completely fit within dst. Pads the remaining dst with '\0' + + Note: dst_size must be > 0 +*/ +static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) +{ + memset(dst, '\0', dst_size); + strncpy(dst, src, dst_size - 1); + /* + If the first condition is true, we are guaranteed to have src length + >= (dst_size - 1), hence safe to access src[dst_size - 1]. + */ + if (dst[dst_size - 2] != '\0' && src[dst_size - 1] != '\0') + return 1; /* Truncation of src. */ + return 0; +} + +/* + Appends src to dst and ensures dst is a NULL terminated C string. + + Returns 1 if the src string was truncated due to too small size of dst. + Returns 0 if src completely fit within the remaining dst space. Pads the + remaining dst with '\0'. + + Note: dst_size must be > 0 +*/ +static inline int safe_strcat(char *dst, size_t dst_size, const char *src) +{ + size_t init_len= strlen(dst); + if (unlikely(init_len >= dst_size - 1)) + return 1; + return safe_strcpy(dst + init_len, dst_size - init_len, src); +} + #ifdef __cplusplus static inline char *safe_str(char *str) { return str ? str : const_cast(""); } diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 9639051e93c..0baaff80ef6 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -243,7 +243,7 @@ static char *get_plugindir() { static char plugin_dir[2*MAX_PATH]; get_basedir(plugin_dir, sizeof(plugin_dir), mysqld_path); - strcat(plugin_dir, "/" STR(INSTALL_PLUGINDIR)); + safe_strcat(plugin_dir, sizeof(plugin_dir), "/" STR(INSTALL_PLUGINDIR)); if (access(plugin_dir, 0) == 0) return plugin_dir; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e4a814b82dd..ea3849ed9f9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5393,12 +5393,11 @@ static int init_server_components() else // full wsrep initialization { // add basedir/bin to PATH to resolve wsrep script names - char* const tmp_path= (char*)my_alloca(strlen(mysql_home) + - strlen("/bin") + 1); + size_t tmp_path_size= strlen(mysql_home) + 5; /* including "/bin" */ + char* const tmp_path= (char*)my_alloca(tmp_path_size); if (tmp_path) { - strcpy(tmp_path, mysql_home); - strcat(tmp_path, "/bin"); + snprintf(tmp_path, tmp_path_size, "%s/bin", mysql_home); wsrep_prepend_PATH(tmp_path); } else @@ -6254,8 +6253,9 @@ int mysqld_main(int argc, char **argv) char real_server_version[2 * SERVER_VERSION_LENGTH + 10]; set_server_version(real_server_version, sizeof(real_server_version)); - strcat(real_server_version, "' as '"); - strcat(real_server_version, server_version); + safe_strcat(real_server_version, sizeof(real_server_version), "' as '"); + safe_strcat(real_server_version, sizeof(real_server_version), + server_version); sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname, real_server_version, @@ -9192,7 +9192,8 @@ static int mysql_init_variables(void) } else my_path(prg_dev, my_progname, "mysql/bin"); - strcat(prg_dev,"/../"); // Remove 'bin' to get base dir + // Remove 'bin' to get base dir + safe_strcat(prg_dev, sizeof(prg_dev), "/../"); cleanup_dirname(mysql_home,prg_dev); } #else diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index a5c2e065742..1eeb4ac05ca 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -975,13 +975,13 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) xtrc(1, "Arraylist: len=%d\n", len); p = (char *)PlugSubAlloc(g, NULL, len); - strcpy(p, "("); + safe_strcpy(p, len, "("); for (i = 0; i < Nval;) { Value->SetValue_pvblk(Vblp, i); Value->Prints(g, tp, z); - strcat(p, tp); - strcat(p, (++i == Nval) ? ")" : ","); + safe_strcat(p, len, tp); + safe_strcat(p, len, (++i == Nval) ? ")" : ","); } // enfor i xtrc(1, "Arraylist: newlen=%d\n", strlen(p)); diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp index 1a1c5cf5d8d..208cd04cb3a 100644 --- a/storage/connect/bson.cpp +++ b/storage/connect/bson.cpp @@ -10,6 +10,7 @@ /* Include relevant sections of the MariaDB header file. */ /***********************************************************************/ #include +#include /***********************************************************************/ /* Include application header files: */ @@ -598,7 +599,7 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) try { if (!bvp) { - strcpy(g->Message, "Null json tree"); + safe_strcpy(g->Message, sizeof(g->Message), "Null json tree"); throw 1; } else if (!fn) { // Serialize to a string @@ -606,9 +607,8 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) b = pretty == 1; } else { if (!(fs = fopen(fn, "wb"))) { - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR), - "w", (int)errno, fn); - strcat(strcat(g->Message, ": "), strerror(errno)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR) ": %s", + "w", (int)errno, fn, strerror(errno)); throw 2; } else if (pretty >= 2) { // Serialize to a pretty file diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index 2d9132e20ed..8df04232277 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -4908,7 +4908,7 @@ char *bbin_make_array(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endfor i if ((bsp = BbinAlloc(bnx.G, initid->max_length, arp))) { - strcat(bsp->Msg, " array"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " array"); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; @@ -5106,8 +5106,9 @@ char *bbin_array_grp(UDF_INIT *initid, UDF_ARGS *, char *result, PUSH_WARNING("Result truncated to json_grp_size values"); if (arp) - if ((bsp = BbinAlloc(g, initid->max_length, arp))) - strcat(bsp->Msg, " array"); + if ((bsp = BbinAlloc(g, initid->max_length, arp))) { + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " array"); + } if (!bsp) { *res_length = 0; @@ -5153,8 +5154,9 @@ char *bbin_object_grp(UDF_INIT *initid, UDF_ARGS *, char *result, PUSH_WARNING("Result truncated to json_grp_size values"); if (bop) - if ((bsp = BbinAlloc(g, initid->max_length, bop))) - strcat(bsp->Msg, " object"); + if ((bsp = BbinAlloc(g, initid->max_length, bop))) { + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); + } if (!bsp) { *res_length = 0; @@ -5198,7 +5200,7 @@ char *bbin_make_object(UDF_INIT *initid, UDF_ARGS *args, char *result, bnx.SetKeyValue(objp, bnx.MakeValue(args, i), bnx.MakeKey(args, i)); if ((bsp = BbinAlloc(bnx.G, initid->max_length, objp))) { - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; @@ -5253,7 +5255,7 @@ char *bbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, bnx.SetKeyValue(objp, jvp, bnx.MakeKey(args, i)); if ((bsp = BbinAlloc(bnx.G, initid->max_length, objp))) { - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; @@ -5312,7 +5314,7 @@ char *bbin_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result, bnx.SetKeyValue(objp, bnx.MakeValue(args, i + 1), MakePSZ(g, args, i)); if ((bsp = BbinAlloc(bnx.G, initid->max_length, objp))) { - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; @@ -6075,7 +6077,7 @@ char *bbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result, // pretty = pty; if ((bsp = BbinAlloc(bnx.G, len, jsp))) { - strcat(bsp->Msg, " file"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " file"); bsp->Filename = fn; bsp->Pretty = pretty; } else { diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index a4c2232b1bf..c5694c06b65 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -442,7 +442,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info) hp->Headlen, hp->Filedate[0], hp->Filedate[1], hp->Filedate[2]); - strcat(g->Message, buf); + safe_strcat(g->Message, sizeof(g->Message), buf); } // endif info #endif // 0 diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index 1df247bd951..d767ba6e4bc 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -36,6 +36,8 @@ #include #endif // !_WIN32 +#include + /***********************************************************************/ /* Include application header files: */ /* global.h is header containing all global declarations. */ @@ -883,7 +885,6 @@ bool BGXFAM::OpenTableFile(PGLOBAL g) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)filename, sizeof(filename), NULL); - strcat(g->Message, filename); } else rc = 0; @@ -1004,7 +1005,7 @@ int BGXFAM::Cardinality(PGLOBAL g) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)filename, sizeof(filename), NULL); - strcat(g->Message, filename); + safe_strcat(g->Message, sizeof(g->Message), filename); return -1; } else return 0; // File does not exist @@ -1384,7 +1385,8 @@ bool BGXFAM::OpenTempFile(PGLOBAL g) /*********************************************************************/ tempname = (char*)PlugSubAlloc(g, NULL, _MAX_PATH); PlugSetPath(tempname, To_File, Tdbp->GetPath()); - strcat(PlugRemoveType(tempname, tempname), ".t"); + PlugRemoveType(tempname, tempname); + safe_strcat(tempname, _MAX_PATH, ".t"); remove(tempname); // Be sure it does not exist yet #if defined(_WIN32) @@ -1393,11 +1395,12 @@ bool BGXFAM::OpenTempFile(PGLOBAL g) if (Tfile == INVALID_HANDLE_VALUE) { DWORD rc = GetLastError(); - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR), rc, MODE_INSERT, tempname); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR), rc, MODE_INSERT, + tempname); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)tempname, _MAX_PATH, NULL); - strcat(g->Message, tempname); + safe_strcat(g->Message, sizeof(g->Message), tempname); return true; } // endif Tfile #else // UNIX @@ -1405,8 +1408,8 @@ bool BGXFAM::OpenTempFile(PGLOBAL g) if (Tfile == INVALID_HANDLE_VALUE) { int rc = errno; - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR), rc, MODE_INSERT, tempname); - strcat(g->Message, strerror(errno)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR)" %s", rc, + MODE_INSERT, tempname, strerror(errno)); return true; } //endif Tfile #endif // UNIX diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp index 7e9597d6b75..d8ffa63beac 100644 --- a/storage/connect/filamgz.cpp +++ b/storage/connect/filamgz.cpp @@ -33,6 +33,8 @@ #include #endif // !_WIN32 +#include + /***********************************************************************/ /* Include application header files: */ /* global.h is header containing all global declarations. */ @@ -128,12 +130,13 @@ int GZFAM::GetFileLength(PGLOBAL g) /***********************************************************************/ bool GZFAM::OpenTableFile(PGLOBAL g) { - char opmode[4], filename[_MAX_PATH]; - MODE mode = Tdbp->GetMode(); + const char *opmode; + char filename[_MAX_PATH]; + MODE mode = Tdbp->GetMode(); switch (mode) { case MODE_READ: - strcpy(opmode, "r"); + opmode = "rb"; break; case MODE_UPDATE: /*****************************************************************/ @@ -147,7 +150,7 @@ bool GZFAM::OpenTableFile(PGLOBAL g) DelRows = Cardinality(g); // This will erase the entire file - strcpy(opmode, "w"); + opmode = "wb"; // Block = 0; // For ZBKFAM // Last = Nrec; // For ZBKFAM Tdbp->ResetSize(); @@ -158,7 +161,7 @@ bool GZFAM::OpenTableFile(PGLOBAL g) break; case MODE_INSERT: - strcpy(opmode, "a+"); + opmode = "a+b"; break; default: snprintf(g->Message, sizeof(g->Message), MSG(BAD_OPEN_MODE), mode); @@ -170,13 +173,11 @@ bool GZFAM::OpenTableFile(PGLOBAL g) /* Use specific zlib functions. */ /* Treat files as binary. */ /*********************************************************************/ - strcat(opmode, "b"); Zfile = gzopen(PlugSetPath(filename, To_File, Tdbp->GetPath()), opmode); if (Zfile == NULL) { - snprintf(g->Message, sizeof(g->Message), MSG(GZOPEN_ERROR), - opmode, (int)errno, filename); - strcat(strcat(g->Message, ": "), strerror(errno)); + snprintf(g->Message, sizeof(g->Message), MSG(GZOPEN_ERROR) ": %s", + opmode, (int)errno, filename, strerror(errno)); return (mode == MODE_READ && errno == ENOENT) ? PushWarning(g, Tdbp) : true; } // endif Zfile diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index 9ecc2293c48..9db890c5f36 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -38,6 +38,8 @@ #include #endif // !_WIN32 +#include + /***********************************************************************/ /* Include application header files: */ /* global.h is header containing all global declarations. */ @@ -593,7 +595,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g) } // endswitch Mode // For blocked I/O or for moving lines, open the table in binary - strcat(opmode, (Bin) ? "b" : "t"); + safe_strcat(opmode, sizeof(opmode), (Bin) ? "b" : "t"); // Now open the file stream PlugSetPath(filename, To_File, Tdbp->GetPath()); @@ -1081,7 +1083,8 @@ bool DOSFAM::OpenTempFile(PGLOBAL g) /* Open the temporary file, Spos is at the beginning of file. */ /*********************************************************************/ PlugSetPath(tempname, To_File, Tdbp->GetPath()); - strcat(PlugRemoveType(tempname, tempname), ".t"); + PlugRemoveType(tempname, tempname); + safe_strcat(tempname, sizeof(tempname), ".t"); if (!(T_Stream = PlugOpenFile(g, tempname, "wb"))) { if (trace(1)) @@ -1170,7 +1173,8 @@ int DOSFAM::RenameTempFile(PGLOBAL g) if (!Abort) { PlugSetPath(filename, To_File, Tdbp->GetPath()); - strcat(PlugRemoveType(filetemp, filename), ".ttt"); + PlugRemoveType(filetemp, filename); + safe_strcat(filetemp, sizeof(filetemp), ".ttt"); remove(filetemp); // May still be there from previous error if (rename(filename, filetemp)) { // Save file for security diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index f3e31895324..91a6772d961 100644 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -42,6 +42,8 @@ #include #endif // !_WIN32 +#include + /***********************************************************************/ /* Include application header files: */ /* global.h is header containing all global declarations. */ @@ -194,7 +196,7 @@ int VCTFAM::GetBlockInfo(PGLOBAL g) if (Header == 2) { PlugRemoveType(filename, filename); - strncat(filename, ".blk", _MAX_PATH - strlen(filename)); + safe_strcat(filename, sizeof(filename), ".blk"); } if ((h = global_open(g, MSGID_CANNOT_OPEN, filename, O_RDONLY)) == -1 @@ -251,7 +253,7 @@ bool VCTFAM::SetBlockInfo(PGLOBAL g) } else { // Header == 2 PlugRemoveType(filename, filename); - strncat(filename, ".blk", _MAX_PATH - strlen(filename)); + safe_strcat(filename, sizeof(filename), ".blk"); s= global_fopen(g, MSGID_CANNOT_OPEN, filename, "wb"); } // endif Header @@ -586,7 +588,7 @@ bool VCTFAM::InitInsert(PGLOBAL g) htrc("Exception %d: %s\n", n, g->Message); rc = true; } catch (const char *msg) { - strncpy(g->Message, msg, sizeof(g->Message)); + safe_strcpy(g->Message, sizeof(msg), msg); rc = true; } // end catch @@ -890,8 +892,7 @@ bool VCTFAM::OpenTempFile(PGLOBAL g) /*********************************************************************/ PlugSetPath(tempname, To_File, Tdbp->GetPath()); PlugRemoveType(tempname, tempname); - strncat(tempname, ".t", _MAX_PATH - strlen(tempname)); - + safe_strcat(tempname, sizeof(tempname), ".t"); if (MaxBlk) { if (MakeEmptyFile(g, tempname)) return true; @@ -1562,7 +1563,7 @@ bool VCMFAM::InitInsert(PGLOBAL g) htrc("Exception %d: %s\n", n, g->Message); rc = true; } catch (const char *msg) { - strncpy(g->Message, msg, sizeof(g->Message)); + safe_strcpy(g->Message, sizeof(g->Message), msg); rc = true; } // end catch @@ -2082,10 +2083,10 @@ bool VECFAM::AllocateBuffer(PGLOBAL g) // Allocate all that is needed to move lines and make Temp if (UseTemp) { Tempat = (char*)PlugSubAlloc(g, NULL, _MAX_PATH); - strcpy(Tempat, Colfn); + safe_strcpy(Tempat, _MAX_PATH, Colfn); PlugSetPath(Tempat, Tempat, Tdbp->GetPath()); PlugRemoveType(Tempat, Tempat); - strncat(Tempat, ".t", _MAX_PATH - strlen(Tempat)); + safe_strcat(Tempat, _MAX_PATH, ".t"); T_Fbs = (PFBLOCK *)PlugSubAlloc(g, NULL, Ncol * sizeof(PFBLOCK)); } // endif UseTemp @@ -2460,7 +2461,7 @@ int VECFAM::RenameTempFile(PGLOBAL g) snprintf(filename, _MAX_PATH, Colfn, i+1); PlugSetPath(filename, filename, Tdbp->GetPath()); PlugRemoveType(filetemp, filename); - strncat(filetemp, ".ttt", _MAX_PATH - strlen(filetemp)); + safe_strcat(filetemp, sizeof(filetemp), ".ttt"); remove(filetemp); // May still be there from previous error if (rename(filename, filetemp)) { // Save file for security @@ -3221,7 +3222,7 @@ int BGVFAM::GetBlockInfo(PGLOBAL g) if (Header == 2) { PlugRemoveType(filename, filename); - strncat(filename, ".blk", _MAX_PATH - strlen(filename)); + safe_strcat(filename, sizeof(filename), ".blk"); } #if defined(_WIN32) @@ -3300,7 +3301,7 @@ bool BGVFAM::SetBlockInfo(PGLOBAL g) } else // Header == 2 { PlugRemoveType(filename, filename); - strncat(filename, ".blk", _MAX_PATH - strlen(filename)); + safe_strcat(filename, sizeof(filename), ".blk"); } if (h == INVALID_HANDLE_VALUE) { @@ -3398,7 +3399,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)filename, sizeof(filename), NULL); - strncat(g->Message, filename, sizeof(g->Message) - strlen(g->Message)); + safe_strcat(g->Message, sizeof(g->Message), filename); if (h != INVALID_HANDLE_VALUE) CloseHandle(h); @@ -3534,7 +3535,7 @@ bool BGVFAM::OpenTableFile(PGLOBAL g) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)filename, sizeof(filename), NULL); - strncat(g->Message, filename, sizeof(g->Message) - strlen(g->Message)); + safe_strcat(g->Message, sizeof(g->Message), filename); } // endif Hfile if (trace(1)) @@ -3622,8 +3623,8 @@ bool BGVFAM::OpenTableFile(PGLOBAL g) if (Hfile == INVALID_HANDLE_VALUE) { rc = errno; - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR), rc, mode, filename); - strncat(g->Message, strerror(errno), sizeof(g->Message) - strlen(g->Message)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR)"%s", rc, mode, + filename, strerror(errno)); } // endif Hfile if (trace(1)) @@ -3967,7 +3968,7 @@ bool BGVFAM::OpenTempFile(PGLOBAL g) tempname = (char*)PlugSubAlloc(g, NULL, _MAX_PATH); PlugSetPath(tempname, To_File, Tdbp->GetPath()); PlugRemoveType(tempname, tempname); - strncat(tempname, ".t", _MAX_PATH - strlen(tempname)); + safe_strcat(tempname, _MAX_PATH, ".t"); if (!MaxBlk) remove(tempname); // Be sure it does not exist yet @@ -3986,7 +3987,7 @@ bool BGVFAM::OpenTempFile(PGLOBAL g) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)tempname, _MAX_PATH, NULL); - strncat(g->Message, tempname, sizeof(g->Message) - strlen(g->Message)); + safe_strcat(g->Message, sizeof(g->Message), tempname); return true; } // endif Tfile #else // UNIX @@ -3996,8 +3997,8 @@ bool BGVFAM::OpenTempFile(PGLOBAL g) if (Tfile == INVALID_HANDLE_VALUE) { int rc = errno; - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR), rc, MODE_INSERT, tempname); - strncat(g->Message, strerror(errno), sizeof(g->Message) - strlen(g->Message)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_ERROR) "%s", rc, MODE_INSERT, + tempname, strerror(errno)); return true; } //endif Tfile #endif // UNIX diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 814503ae6f7..40926cd2ae7 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -29,6 +29,7 @@ #include #endif // !_WIN32 #include +#include /***********************************************************************/ /* Include application header files: */ @@ -181,7 +182,8 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) while (true) { if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName); + snprintf(filename, sizeof(filename), "%s%s%s", + drive, direc, FileData.cFileName); if (ZipFile(g, zutp, filename, FileData.cFileName, buf)) { FindClose(hSearch); @@ -217,7 +219,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) struct dirent *entry; _splitpath(filename, NULL, direc, pattern, ftype); - strcat(pattern, ftype); + safe_strcat(pattern, sizeof(pattern), ftype); // Start searching files in the target directory. if (!(dir = opendir(direc))) { @@ -226,7 +228,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) } // endif dir while ((entry = readdir(dir))) { - strcat(strcpy(fn, direc), entry->d_name); + snprintf(fn, sizeof(fn), "%s%s", direc, entry->d_name); if (lstat(fn, &fileinfo) < 0) { snprintf(g->Message, sizeof(g->Message), "%s: %s", fn, strerror(errno)); @@ -240,7 +242,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) if (fnmatch(pattern, entry->d_name, 0)) continue; // Not a match - strcat(strcpy(filename, direc), entry->d_name); + snprintf(filename, sizeof(filename), "%s%s", direc, entry->d_name); if (ZipFile(g, zutp, filename, entry->d_name, buf)) { closedir(dir); diff --git a/storage/connect/javaconn.cpp b/storage/connect/javaconn.cpp index 0dc467aa7ee..3d1dfbc3f26 100644 --- a/storage/connect/javaconn.cpp +++ b/storage/connect/javaconn.cpp @@ -33,6 +33,8 @@ #define NODW #endif // !_WIN32 +#include + /***********************************************************************/ /* Required objects includes. */ /***********************************************************************/ @@ -231,15 +233,16 @@ bool JAVAConn::GetJVM(PGLOBAL g) #if defined(_WIN32) for (ntry = 0; !LibJvm && ntry < 3; ntry++) { if (!ntry && JvmPath) { - strcat(strcpy(soname, JvmPath), "\\jvm.dll"); + snprintf(soname, sizeof(soname), "%s\\jvm.dll", JvmPath); + ntry = 3; // No other try } else if (ntry < 2 && getenv("JAVA_HOME")) { - strcpy(soname, getenv("JAVA_HOME")); + safe_strcpy(soname, sizeof(soname), getenv("JAVA_HOME")); if (ntry == 1) - strcat(soname, "\\jre"); + safe_strcat(soname, sizeof(soname), "\\jre"); - strcat(soname, "\\bin\\client\\jvm.dll"); + safe_strcat(soname, sizeof(soname), "\\bin\\client\\jvm.dll"); } else { // Try to find it through the registry char version[16]; @@ -247,11 +250,12 @@ bool JAVAConn::GetJVM(PGLOBAL g) LONG rc; DWORD BufferSize = 16; - strcpy(soname, "jvm.dll"); // In case it fails + safe_strcpy(soname, sizeof(soname), "jvm.dll"); // In case it fails if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "CurrentVersion", RRF_RT_ANY, NULL, (PVOID)&version, &BufferSize)) == ERROR_SUCCESS) { - strcat(strcat(javaKey, "\\"), version); + safe_strcat(javaKey, sizeof(javaKey), "\\"); + safe_strcat(javaKey, sizeof(javaKey), version); BufferSize = sizeof(soname); if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "RuntimeLib", @@ -272,11 +276,11 @@ bool JAVAConn::GetJVM(PGLOBAL g) char buf[256]; DWORD rc = GetLastError(); - snprintf(g->Message, sizeof(g->Message), MSG(DLL_LOAD_ERROR), rc, soname); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, (LPTSTR)buf, sizeof(buf), NULL); - strcat(strcat(g->Message, ": "), buf); + snprintf(g->Message, sizeof(g->Message), MSG(DLL_LOAD_ERROR)": %s", rc, + soname, buf); } else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm, "JNI_CreateJavaVM"))) { snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM"); @@ -301,13 +305,14 @@ bool JAVAConn::GetJVM(PGLOBAL g) for (ntry = 0; !LibJvm && ntry < 2; ntry++) { if (!ntry && JvmPath) { - strcat(strcpy(soname, JvmPath), "/libjvm.so"); + snprintf(soname, sizeof(soname), "%s/libjvm.so", JvmPath); ntry = 2; } else if (!ntry && getenv("JAVA_HOME")) { // TODO: Replace i386 by a better guess - strcat(strcpy(soname, getenv("JAVA_HOME")), "/jre/lib/i386/client/libjvm.so"); + snprintf(soname, sizeof(soname), "%s/jre/lib/i386/client/libjvm.so", + getenv("JAVA_HOME")); } else { // Will need LD_LIBRARY_PATH to be set - strcpy(soname, "libjvm.so"); + safe_strcpy(soname, sizeof(soname), "libjvm.so"); ntry = 2; } // endelse diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 0786c3139e1..9cce77d025a 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -10,6 +10,7 @@ /* Include relevant sections of the MariaDB header file. */ /***********************************************************************/ #include +#include /***********************************************************************/ /* Include application header files: */ @@ -270,7 +271,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char* fn, int pretty) { jdp->dfp = GetDefaultPrec(); if (!jsp) { - strcpy(g->Message, "Null json tree"); + safe_strcpy(g->Message, sizeof(g->Message), "Null json tree"); throw 1; } else if (!fn) { // Serialize to a string @@ -278,9 +279,8 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char* fn, int pretty) { b = pretty == 1; } else { if (!(fs = fopen(fn, "wb"))) { - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR), - "w", (int)errno, fn); - strcat(strcat(g->Message, ": "), strerror(errno)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR) ": %s", + "w", (int)errno, fn, strerror(errno)); throw 2; } else if (pretty >= 2) { // Serialize to a pretty file diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 1b5ff9ae0c4..d48489298ac 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -4753,7 +4753,7 @@ char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result, if ((arp = (PJAR)JsonNew(g, TYPE_JAR)) && (bsp = JbinAlloc(g, args, initid->max_length, arp))) { - strcat(bsp->Msg, " array"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " array"); for (uint i = 0; i < args->arg_count; i++) arp->AddArrayValue(g, MakeValue(g, args, i)); @@ -4830,7 +4830,7 @@ char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, arp->InitArray(gb); if ((bsp = JbinAlloc(g, args, initid->max_length, top))) { - strcat(bsp->Msg, " array"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " array"); bsp->Jsp = arp; } // endif bsp @@ -5051,7 +5051,7 @@ char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result, if ((bsp = JbinAlloc(g, args, initid->max_length, objp))) - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); } else bsp = NULL; @@ -5107,7 +5107,7 @@ char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, objp->SetKeyValue(g, jvp, MakeKey(g, args, i)); if ((bsp = JbinAlloc(g, args, initid->max_length, objp))) - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); } else bsp = NULL; @@ -5166,7 +5166,7 @@ char *jbin_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result, objp->SetKeyValue(g, MakeValue(g, args, i + 1), MakePSZ(g, args, i)); if ((bsp = JbinAlloc(g, args, initid->max_length, objp))) - strcat(bsp->Msg, " object"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " object"); } else bsp = NULL; @@ -5388,7 +5388,7 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif CheckMemory if ((bsp = JbinAlloc(g, args, initid->max_length, jarp))) - strcat(bsp->Msg, " array"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " array"); // Keep result of constant function g->Xchk = (initid->const_item) ? bsp : NULL; @@ -5463,7 +5463,7 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result, jsp = (jvp->GetJsp()) ? jvp->GetJsp() : JvalNew(g, TYPE_JVAL, jvp->GetValue(g)); if ((bsp = JbinAlloc(g, args, initid->max_length, jsp))) - strcat(bsp->Msg, " item"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " item"); else *error = 1; @@ -5823,7 +5823,7 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result, pretty = pty; if ((bsp = JbinAlloc(g, args, len, jsp))) { - strcat(bsp->Msg, " file"); + safe_strcat(bsp->Msg, sizeof(bsp->Msg), " file"); bsp->Filename = fn; bsp->Pretty = pretty; } else { @@ -6159,9 +6159,8 @@ char* JUP::UnprettyJsonFile(PGLOBAL g, char *fn, char *outfn, int lrecl) { /* Parse the json file and allocate its tree structure. */ /*********************************************************************************/ if (!(fs = fopen(outfn, "wb"))) { - snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR), - "w", (int)errno, outfn); - strcat(strcat(g->Message, ": "), strerror(errno)); + snprintf(g->Message, sizeof(g->Message), MSG(OPEN_MODE_ERROR)": %s", + "w", (int)errno, outfn, strerror(errno)); CloseMemMap(mm.memory, len); return NULL; } // endif fs diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index e5ea1ac52ae..7a4c2f897a0 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -405,18 +405,20 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, port = mysqld_port; if (!strnicmp(srcdef, "select ", 7) || strstr(srcdef, "%s")) { - query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10); + size_t query_sz = strlen(srcdef) + 10; + query = (char *)PlugSubAlloc(g, NULL, query_sz); if ((p= strstr(srcdef, "%s"))) { /* Replace %s with 1=1 */ - sprintf(query, "%.*s1=1%s", (int) (p - srcdef), srcdef, p + 2); // dummy where clause + snprintf(query, query_sz, "%.*s1=1%s", + (int) (p - srcdef), srcdef, p + 2); // dummy where clause } - else - strcpy(query, srcdef); + else + safe_strcpy(query, query_sz, srcdef); if (!strnicmp(srcdef, "select ", 7)) - strcat(query, " LIMIT 0"); + safe_strcat(query, query_sz, " LIMIT 0"); } else query = (char *)srcdef;