mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-34266 safe_strcpy() includes an unnecessary conditional branch
The strncpy() wrapper that was introduced in
commit 567b681299
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.
This commit is contained in:
parent
4b4dbb23ea
commit
e255837eaf
3 changed files with 40 additions and 36 deletions
|
@ -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.
|
||||
/**
|
||||
Copies a 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
|
||||
@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;
|
||||
}
|
||||
|
||||
if (dst[dst_size-1])
|
||||
/**
|
||||
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
|
||||
|
||||
@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.
|
||||
/**
|
||||
Appends src to dst and ensures dst is a NUL 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
|
||||
@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
|
||||
|
|
Loading…
Reference in a new issue