Commit e255837e authored by Marko Mäkelä's avatar Marko Mäkelä Committed by Vicențiu-Marian Ciorbaru

MDEV-34266 safe_strcpy() includes an unnecessary conditional branch

The strncpy() wrapper that was introduced in
commit 567b6812
is checking whether the output was truncated even in cases
where the caller does not care about it.

Let us introduce a separate function safe_strcpy_truncated() that
indidates whether the output was truncated.
parent 4b4dbb23
......@@ -686,7 +686,7 @@ 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 */
if (safe_strcpy(line + line_len - 1, sizeof(line), FN_SOEXT))
if (safe_strcpy_truncated(line + line_len - 1, sizeof line, FN_SOEXT))
{
reason= "Plugin name too long.";
fclose(file_ptr);
......@@ -749,7 +749,7 @@ static int check_options(int argc, char **argv, char *operation)
const char *plugin_dir_prefix = "--plugin_dir=";
size_t plugin_dir_len= strlen(plugin_dir_prefix);
strcpy(plugin_name, "");
*plugin_name= '\0';
for (i = 0; i < argc && num_found < 5; i++)
{
......@@ -787,8 +787,8 @@ static int check_options(int argc, char **argv, char *operation)
/* read the plugin config file and check for match against argument */
else
{
if (safe_strcpy(plugin_name, sizeof(plugin_name), argv[i]) ||
safe_strcpy(config_file, sizeof(config_file), argv[i]) ||
if (safe_strcpy_truncated(plugin_name, sizeof plugin_name, argv[i]) ||
safe_strcpy_truncated(config_file, sizeof config_file, argv[i]) ||
safe_strcat(config_file, sizeof(config_file), ".ini"))
{
fprintf(stderr, "ERROR: argument is too long.\n");
......
......@@ -6265,7 +6265,7 @@ int do_done(struct st_command *command)
if (*cur_block->delim)
{
/* Restore "old" delimiter after false if block */
if (safe_strcpy(delimiter, sizeof(delimiter), cur_block->delim))
if (safe_strcpy_truncated(delimiter, sizeof delimiter, cur_block->delim))
die("Delimiter too long, truncated");
delimiter_length= strlen(delimiter);
......@@ -6526,7 +6526,8 @@ void do_block(enum block_cmd cmd, struct st_command* command)
else
{
/* Remember "old" delimiter if entering a false if block */
if (safe_strcpy(cur_block->delim, sizeof(cur_block->delim), delimiter))
if (safe_strcpy_truncated(cur_block->delim, sizeof cur_block->delim,
delimiter))
die("Delimiter too long, truncated");
}
......
......@@ -239,15 +239,14 @@ 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'
/**
Copies a string.
Note: dst_size must be > 0
@param dst destination buffer, will be NUL padded.
@param dst_size size of dst buffer, must be > 0
@param src NUL terminated source string
*/
static inline int safe_strcpy(char *dst, size_t dst_size, const char *src)
static inline void safe_strcpy(char *dst, size_t dst_size, const char *src)
{
DBUG_ASSERT(dst_size > 0);
......@@ -256,45 +255,49 @@ static inline int safe_strcpy(char *dst, size_t dst_size, const char *src)
*
* 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will
* copy dst_size bytes, and the final byte won't be 0.
*
* In GCC 8+, the `-Wstringop-truncation` warning will object to strncpy()
* being used in this way, so we need to disable this warning for this
* single statement.
*/
#if defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
#endif
strncpy(dst, src, dst_size);
#if defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
dst[dst_size - 1]= 0;
}
/**
Copies a string, checking for truncation.
@param dst destination buffer, will be NUL padded.
@param dst_size size of dst buffer, must be > 0
@param src NUL terminated source string
if (dst[dst_size-1])
@retval 1 if the src string was truncated due to too small size of dst.
@retval 0 if src completely fit within dst,
*/
static inline int safe_strcpy_truncated(char *dst, size_t dst_size,
const char *src)
{
DBUG_ASSERT(dst_size > 0);
strncpy(dst, src, dst_size);
if (dst[dst_size - 1])
{
/* Only possible in case (2), meaning src was truncated. */
dst[dst_size-1]= 0;
dst[dst_size - 1]= 0;
return 1;
}
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'.
/**
Appends src to dst and ensures dst is a NUL terminated C string.
Note: dst_size must be > 0
@retval 1 if the src string was truncated due to too small size of dst.
@retval 0 if src completely fit within the remaining dst space,
including NUL termination.
*/
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))
if (unlikely(init_len > dst_size))
return 1;
return safe_strcpy(dst + init_len, dst_size - init_len, src);
return safe_strcpy_truncated(dst + init_len, dst_size - init_len, src);
}
#ifdef __cplusplus
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment