Skip to content

Commit 59d679a

Browse files
committed
MDEV-30691 Assertion `strlen(Ptr) == str_length' failed in void Binary_string::chop()
numerous bugs in JSON_DETAILED and multibyte charsets: * String:chop() must be charset-aware and not simply length-- * String::append(char) must be charset-aware and not simply length++ * json_nice() first removes value_len bytes, then a certain number of characters
1 parent ed81e5f commit 59d679a

File tree

5 files changed

+41
-39
lines changed

5 files changed

+41
-39
lines changed

mysql-test/main/ctype_ucs.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ SET NAMES koi8r;
118118
SET character_set_connection=ucs2;
119119
--source include/ctype_like.inc
120120

121+
--disable_service_connection
121122
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2);
122123
INSERT INTO t1 VALUES ('����'),('����'),('����'),('����'),('����'),('����');
123124
INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������');
@@ -127,6 +128,7 @@ SELECT * FROM t1 WHERE a LIKE '%
127128
SELECT * FROM t1 WHERE a LIKE '%���%';
128129
SELECT * FROM t1 WHERE a LIKE '����%';
129130
SELECT * FROM t1 WHERE a LIKE '����%' COLLATE ucs2_bin;
131+
--enable_service_connection
130132
DROP TABLE t1;
131133

132134
#

mysql-test/main/func_json.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,3 +2669,21 @@ JSON_VALUE(@json,'$.A[last-1][last-1].key1')
26692669
NULL
26702670
SET @@collation_connection= @save_collation_connection;
26712671
# End of 10.9 Test
2672+
#
2673+
# MDEV-30691 Assertion `strlen(Ptr) == str_length' failed in void Binary_string::chop()
2674+
#
2675+
set @@collation_connection=utf32_czech_ci;
2676+
select json_detailed('[[123],456]');
2677+
json_detailed('[[123],456]')
2678+
[
2679+
[123],
2680+
456
2681+
]
2682+
set @@collation_connection=@save_collation_connection;
2683+
select json_detailed('[[123],456]');
2684+
json_detailed('[[123],456]')
2685+
[
2686+
[123],
2687+
456
2688+
]
2689+
# End of 10.11 Test

mysql-test/main/func_json.test

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,5 +1937,14 @@ SELECT JSON_VALUE(@json,'$.A[last-1][last-1].key1');
19371937

19381938
SET @@collation_connection= @save_collation_connection;
19391939

1940-
19411940
--echo # End of 10.9 Test
1941+
1942+
--echo #
1943+
--echo # MDEV-30691 Assertion `strlen(Ptr) == str_length' failed in void Binary_string::chop()
1944+
--echo #
1945+
set @@collation_connection=utf32_czech_ci;
1946+
select json_detailed('[[123],456]');
1947+
set @@collation_connection=@save_collation_connection;
1948+
select json_detailed('[[123],456]');
1949+
1950+
--echo # End of 10.11 Test

sql/item_jsonfunc.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,14 +422,9 @@ static int json_nice(json_engine_t *je, String *nice_js,
422422
if (mode == Item_func_json_format::DETAILED &&
423423
value_size == 1 && je->state != JST_OBJ_END)
424424
{
425-
for (auto i = 0; i < value_len; i++)
426-
{
427-
nice_js->chop();
428-
}
425+
nice_js->length(nice_js->length() - value_len);
429426
for (auto i = 0; i < (depth + 1) * tab_size + 1; i++)
430-
{
431427
nice_js->chop();
432-
}
433428
nice_js->append(curr_str);
434429
}
435430

sql/sql_string.h

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -374,37 +374,6 @@ class Binary_string: public Sql_alloc
374374
!memcmp(ptr(), other->ptr(), length());
375375
}
376376

377-
/*
378-
PMG 2004.11.12
379-
This is a method that works the same as perl's "chop". It simply
380-
drops the last character of a string. This is useful in the case
381-
of the federated storage handler where I'm building a unknown
382-
number, list of values and fields to be used in a sql insert
383-
statement to be run on the remote server, and have a comma after each.
384-
When the list is complete, I "chop" off the trailing comma
385-
386-
ex.
387-
String stringobj;
388-
stringobj.append("VALUES ('foo', 'fi', 'fo',");
389-
stringobj.chop();
390-
stringobj.append(")");
391-
392-
In this case, the value of string was:
393-
394-
VALUES ('foo', 'fi', 'fo',
395-
VALUES ('foo', 'fi', 'fo'
396-
VALUES ('foo', 'fi', 'fo')
397-
*/
398-
inline void chop()
399-
{
400-
if (str_length)
401-
{
402-
str_length--;
403-
Ptr[str_length]= '\0';
404-
DBUG_ASSERT(strlen(Ptr) == str_length);
405-
}
406-
}
407-
408377
// Returns offset to substring or -1
409378
int strstr(const Binary_string &search, uint32 offset=0) const;
410379
int strstr(const char *search, uint32 search_length, uint32 offset=0) const;
@@ -1039,7 +1008,7 @@ class String: public Charset, public Binary_string
10391008
}
10401009
inline bool append(char chr)
10411010
{
1042-
return Binary_string::append_char(chr);
1011+
return append(&chr, 1);
10431012
}
10441013
bool append_hex(const char *src, uint32 srclen)
10451014
{
@@ -1162,6 +1131,15 @@ class String: public Charset, public Binary_string
11621131
return false;
11631132
}
11641133

1134+
inline void chop()
1135+
{
1136+
if (str_length)
1137+
{
1138+
str_length--;
1139+
str_length= well_formed_length();
1140+
}
1141+
}
1142+
11651143
void strip_sp();
11661144
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
11671145
friend class Field;

0 commit comments

Comments
 (0)