Skip to content
Permalink
Browse files
MDEV-7533: COLUMN_JSON() doesn't escape control characters in string …
…values

escape all charecters less or equal 0x1F (control symbols)
(shorter sequence are not used to make code simple, long encoding is always legal according to the rfc4627)
  • Loading branch information
sanja-byelkin committed Jan 23, 2018
1 parent ea78c57 commit a4663af
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 2 deletions.
@@ -69,6 +69,9 @@ typedef struct st_mysql_lex_string LEX_STRING;
#define DYNCOL_UTF (&my_charset_utf8_general_ci)
#endif

/* escape json strings */
#define DYNCOL_JSON_ESC ((char)1)

enum enum_dyncol_func_result
{
ER_DYNCOL_OK= 0,
@@ -1873,5 +1873,15 @@ SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL));
COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL))
{"a":1,"b":1}
#
# MDEV-7533: COLUMN_JSON() doesn't escape control characters
# in string values
#
SELECT COLUMN_JSON(COLUMN_CREATE('test','"\\\t\n\Z')) AS json;
json
{"test":"\"\\\u0009\u000A\u001A"}
SELECT COLUMN_JSON(COLUMN_CREATE('test','First line\nSecond line')) AS json;
json
{"test":"First line\u000ASecond line"}
#
# end of 10.0 tests
#
@@ -920,6 +920,14 @@ SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL));

SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL));


--echo #
--echo # MDEV-7533: COLUMN_JSON() doesn't escape control characters
--echo # in string values
--echo #
SELECT COLUMN_JSON(COLUMN_CREATE('test','"\\\t\n\Z')) AS json;
SELECT COLUMN_JSON(COLUMN_CREATE('test','First line\nSecond line')) AS json;

--echo #
--echo # end of 10.0 tests
--echo #
@@ -3819,6 +3819,58 @@ mariadb_dyncol_check(DYNAMIC_COLUMN *str)
DBUG_RETURN(rc);
}

static
my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str,
const char *append, size_t len)
{
uint additional= ((str->alloc_increment && str->alloc_increment > 6) ?
str->alloc_increment :
10);
uint lim= additional;
uint i;
if (dynstr_realloc(str, len + additional + 2))
return TRUE;
str->str[str->length++]= '"';
for (i= 0; i < len; i++)
{
register char c= append[i];
if (unlikely(c <= 0x1F))
{
if (lim < 5)
{
if (dynstr_realloc(str, additional))
return TRUE;
lim+= additional;
}
lim-= 5;
str->str[str->length++]= '\\';
str->str[str->length++]= 'u';
str->str[str->length++]= '0';
str->str[str->length++]= '0';
str->str[str->length++]= (c < 0x10 ? '0' : '1');
c%= 0x10;
str->str[str->length++]= (c < 0xA ? '0' + c : 'A' + (c - 0xA));
}
else
{
if (c == '"' || c == '\\')
{
if (!lim)
{
if (dynstr_realloc(str, additional))
return TRUE;
lim= additional;
}
lim--;
str->str[str->length++]= '\\';
}
str->str[str->length++]= c;
}
}
str->str[str->length++]= '"';
return FALSE;
}


enum enum_dyncol_func_result
mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
@@ -3884,7 +3936,10 @@ mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
return ER_DYNCOL_RESOURCE;
}
if (quote)
rc= dynstr_append_quoted(str, from, len, quote);
if (quote == DYNCOL_JSON_ESC)
rc= dynstr_append_json_quoted(str, from, len);
else
rc= dynstr_append_quoted(str, from, len, quote);
else
rc= dynstr_append_mem(str, from, len);
if (alloc)
@@ -4184,7 +4239,8 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json,
}
else
{
if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, '"')) < 0)
if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, DYNCOL_JSON_ESC))
< 0)
goto err;
}
}

0 comments on commit a4663af

Please sign in to comment.