mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Add support for minimum field width for strings to my_vsnprintf()
This patch adds support for right aligned strings and numbers. Left alignment is left as an exercise for anyone needing it. MDEV-25612 "Assertion `to <= end' failed in process_args" fixed. (Was caused by the original version of this patch)
This commit is contained in:
9
mysql-test/main/strings.result
Normal file
9
mysql-test/main/strings.result
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# MDEV-25612 Assertion `to <= end' failed in process_args
|
||||
#
|
||||
SET SESSION default_master_connection=REPEAT('a',190),lc_messages=ru_ru;
|
||||
CHANGE MASTER TO master_host='dummy';
|
||||
START SLAVE sql_thread;
|
||||
CHANGE MASTER TO master_user='user',master_password='pwd';
|
||||
ERROR HY000: \042D\0442\0443 \043E\043F\0435\0440\0430\0446\0438\044E \043D\0435\0432\043E\0437\043C\043E\0436\043D\043E \0432\044B\043F\043E\043B\043D\0438\0442\044C \043F\0440\0438 \0440\0430\0431\043E\0442\0430\044E\0449\0435\043C \043F\043E\0442\043E\043A\0435 \043F\043E\0434\0447\0438\043D\0435\043D\043D\043E\0433\043E \0441\0435\0440\0432\0435\0440\0430 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
STOP SLAVE;
|
16
mysql-test/main/strings.test
Normal file
16
mysql-test/main/strings.test
Normal file
@ -0,0 +1,16 @@
|
||||
--source include/not_windows.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
#
|
||||
# Test that exposes problems in string functions like my_vsnprintf
|
||||
#
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-25612 Assertion `to <= end' failed in process_args
|
||||
--echo #
|
||||
SET SESSION default_master_connection=REPEAT('a',190),lc_messages=ru_ru;
|
||||
CHANGE MASTER TO master_host='dummy';
|
||||
START SLAVE sql_thread;
|
||||
--error ER_SLAVE_MUST_STOP
|
||||
CHANGE MASTER TO master_user='user',master_password='pwd';
|
||||
STOP SLAVE;
|
@ -224,12 +224,27 @@ err:
|
||||
*/
|
||||
|
||||
static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end,
|
||||
size_t width, char *par, uint print_type,
|
||||
my_bool nice_cut)
|
||||
longlong length_arg, size_t width, char *par,
|
||||
uint print_type, my_bool nice_cut)
|
||||
{
|
||||
int well_formed_error;
|
||||
uint dots= 0;
|
||||
size_t plen, left_len= (size_t) (end - to) + 1, slen=0;
|
||||
my_bool left_fill= 1;
|
||||
size_t length;
|
||||
|
||||
/*
|
||||
The sign of the length argument specific the string should be right
|
||||
or left adjusted
|
||||
*/
|
||||
if (length_arg < 0)
|
||||
{
|
||||
length= (size_t) -length_arg;
|
||||
left_fill= 0;
|
||||
}
|
||||
else
|
||||
length= (size_t) length_arg;
|
||||
|
||||
if (!par)
|
||||
par = (char*) "(null)";
|
||||
|
||||
@ -239,7 +254,10 @@ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end,
|
||||
if (plen > width)
|
||||
plen= width;
|
||||
if (left_len <= plen)
|
||||
{
|
||||
plen = left_len - 1;
|
||||
length= plen;
|
||||
}
|
||||
if ((slen > plen))
|
||||
{
|
||||
if (plen < 3)
|
||||
@ -259,24 +277,34 @@ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end,
|
||||
plen= slen= strnlen(par, width);
|
||||
dots= 0;
|
||||
if (left_len <= plen)
|
||||
{
|
||||
plen = left_len - 1;
|
||||
length= plen;
|
||||
}
|
||||
}
|
||||
|
||||
plen= my_well_formed_length(cs, par, par + plen, width, &well_formed_error);
|
||||
if (print_type & ESCAPED_ARG)
|
||||
{
|
||||
const char *org_to= to;
|
||||
to= backtick_string(cs, to, end, par, plen + dots, '`', MY_TEST(dots));
|
||||
plen= (size_t) (to - org_to);
|
||||
dots= 0;
|
||||
}
|
||||
else
|
||||
to= strnmov(to,par,plen);
|
||||
|
||||
if (dots)
|
||||
{
|
||||
for (; dots; dots--)
|
||||
*(to++)= '.';
|
||||
*(to)= 0;
|
||||
if (left_fill)
|
||||
{
|
||||
if (plen + dots < length)
|
||||
to= strfill(to, length - plen - dots, ' ');
|
||||
}
|
||||
to= strnmov(to,par,plen);
|
||||
if (dots)
|
||||
to= strfill(to, dots, '.');
|
||||
}
|
||||
|
||||
if (!left_fill && plen + dots < length)
|
||||
to= strfill(to, length - plen - dots, ' ');
|
||||
return to;
|
||||
}
|
||||
|
||||
@ -494,11 +522,16 @@ start:
|
||||
case 's':
|
||||
case 'T':
|
||||
{
|
||||
longlong min_field_width;
|
||||
char *par= args_arr[print_arr[i].arg_idx].str_arg;
|
||||
width= (print_arr[i].flags & WIDTH_ARG)
|
||||
? (size_t)args_arr[print_arr[i].width].longlong_arg
|
||||
: print_arr[i].width;
|
||||
to= process_str_arg(cs, to, end, width, par, print_arr[i].flags,
|
||||
min_field_width= (print_arr[i].flags & LENGTH_ARG)
|
||||
? args_arr[print_arr[i].length].longlong_arg
|
||||
: (longlong) print_arr[i].length;
|
||||
to= process_str_arg(cs, to, end, min_field_width, width, par,
|
||||
print_arr[i].flags,
|
||||
(print_arr[i].arg_type == 'T'));
|
||||
break;
|
||||
}
|
||||
@ -565,7 +598,7 @@ start:
|
||||
*to++= ' ';
|
||||
*to++= '"';
|
||||
my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg);
|
||||
to= process_str_arg(cs, to, real_end, width, errmsg_buff,
|
||||
to= process_str_arg(cs, to, real_end, 0, width, errmsg_buff,
|
||||
print_arr[i].flags, 1);
|
||||
if (real_end > to) *to++= '"';
|
||||
}
|
||||
@ -693,7 +726,8 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
|
||||
if (*fmt == 's' || *fmt == 'T') /* String parameter */
|
||||
{
|
||||
reg2 char *par= va_arg(ap, char *);
|
||||
to= process_str_arg(cs, to, end, width, par, print_type, (*fmt == 'T'));
|
||||
to= process_str_arg(cs, to, end, (longlong) length, width, par,
|
||||
print_type, (*fmt == 'T'));
|
||||
continue;
|
||||
}
|
||||
else if (*fmt == 'b') /* Buffer parameter */
|
||||
@ -751,7 +785,7 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
|
||||
*to++= ' ';
|
||||
*to++= '"';
|
||||
my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg);
|
||||
to= process_str_arg(cs, to, real_end, width, errmsg_buff,
|
||||
to= process_str_arg(cs, to, real_end, 0, width, errmsg_buff,
|
||||
print_type, 1);
|
||||
if (real_end > to) *to++= '"';
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ static void test_many(const char **res, const char *fmt, ...)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(47);
|
||||
plan(48);
|
||||
|
||||
test1("Constant string",
|
||||
"Constant string");
|
||||
@ -96,8 +96,11 @@ int main(void)
|
||||
test1("Flag '0' works <0006>",
|
||||
"Flag '0' works <%04d>", 6);
|
||||
|
||||
test1("Width is ignored for strings <x> <y>",
|
||||
"Width is ignored for strings <%04s> <%5s>", "x", "y");
|
||||
test1("Width for strings < x> < y>",
|
||||
"Width for strings <%04s> <%5s>", "x", "y");
|
||||
|
||||
test1("Negative width is ignored for strings < x> < y>",
|
||||
"Negative width is ignored for strings <%-4s> <%-5s>", "x", "y");
|
||||
|
||||
test1("Precision works for strings <abcde>",
|
||||
"Precision works for strings <%.5s>", "abcdef!");
|
||||
|
Reference in New Issue
Block a user