forked from enlightenment/efl
eet: fix tokenizer's escape logic.
Tokenizer's approach of looking back is horrible and breaks the following simple case (bug I had that lead to this patch): "string\\" As the parser would get the end quote and check the previous character if it was a backslash and it was, but it was not escaping the quote, but being escaped by the previous backslash. The best approach is to first check for escape and then go to quote. Escape is simple and only the following byte, so we enter escape, process the byte and then are back to regular mode (be it quote or unquote). Added testcase so we avoid breaking it again. @bugfix cherry-pick
This commit is contained in:
parent
6242271e74
commit
f2a1f14abd
|
@ -2775,6 +2775,7 @@ _eet_data_dump_token_get(const char *src,
|
|||
char *tok = NULL;
|
||||
int in_token = 0;
|
||||
int in_quote = 0;
|
||||
int in_escape = 0;
|
||||
int tlen = 0, tsize = 0;
|
||||
|
||||
#define TOK_ADD(x) \
|
||||
|
@ -2792,25 +2793,32 @@ _eet_data_dump_token_get(const char *src,
|
|||
{
|
||||
if (in_token)
|
||||
{
|
||||
if (in_quote)
|
||||
if (in_escape)
|
||||
{
|
||||
if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
|
||||
in_quote = 0;
|
||||
else if ((p[0] == '\\') && (*len > 1) &&
|
||||
(p[1] == '\"'))
|
||||
{
|
||||
/* skip */
|
||||
}
|
||||
else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
|
||||
{
|
||||
/* skip */
|
||||
}
|
||||
else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n'))
|
||||
{
|
||||
/* skip */
|
||||
}
|
||||
else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\'))
|
||||
switch (p[0]) {
|
||||
case 'n':
|
||||
TOK_ADD('\n');
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
TOK_ADD(p[0]);
|
||||
break;
|
||||
default:
|
||||
ERR("Unknow escape character %#x (%c). Append as is",
|
||||
p[0], p[0]);
|
||||
TOK_ADD(p[0]);
|
||||
}
|
||||
in_escape = 0;
|
||||
}
|
||||
else if (p[0] == '\\')
|
||||
{
|
||||
in_escape = 1;
|
||||
}
|
||||
else if (in_quote)
|
||||
{
|
||||
if (p[0] == '\"')
|
||||
in_quote = 0;
|
||||
else
|
||||
TOK_ADD(p[0]);
|
||||
}
|
||||
|
|
|
@ -920,6 +920,47 @@ START_TEST(eet_test_data_type_dump_undump)
|
|||
eet_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
append_strbuf_string(void *data, const char *string)
|
||||
{
|
||||
Eina_Strbuf *strbuf = data;
|
||||
eina_strbuf_append(strbuf, string);
|
||||
}
|
||||
|
||||
START_TEST(eet_test_data_type_escape_dump_undump)
|
||||
{
|
||||
void *blob;
|
||||
int blob_len;
|
||||
int ret = 0;
|
||||
const char *outputstr;
|
||||
Eina_Strbuf *strbuf;
|
||||
const char inputstr[] = ""
|
||||
"group \"\\\\My\\\"Group\\\\\" struct {\n"
|
||||
" value \"\\\\My\\\\BackSlash\\\\\" string: \"\\\\\";\n"
|
||||
" value \"\\\\My\\\\DoubleQuote\\\\\" string: \"\\\"\";\n"
|
||||
" value \"\\\\My\\\\NewLine\\\\\" string: \"\\n\";\n"
|
||||
"}\n";
|
||||
|
||||
eet_init();
|
||||
|
||||
blob = eet_data_text_undump(inputstr, strlen(inputstr), &blob_len);
|
||||
fail_if(!blob);
|
||||
|
||||
strbuf = eina_strbuf_new();
|
||||
ret = eet_data_text_dump(blob, blob_len, append_strbuf_string, strbuf);
|
||||
ck_assert_int_eq(ret, 1);
|
||||
|
||||
outputstr = eina_strbuf_string_get(strbuf);
|
||||
fail_if(!outputstr);
|
||||
ck_assert_str_eq(inputstr, outputstr);
|
||||
|
||||
eina_strbuf_free(strbuf);
|
||||
free(blob);
|
||||
|
||||
eet_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
START_TEST(eet_file_simple_write)
|
||||
{
|
||||
const char *buffer = "Here is a string of data to save !";
|
||||
|
@ -2724,6 +2765,7 @@ eet_suite(void)
|
|||
tcase_add_test(tc, eet_test_basic_data_type_encoding_decoding);
|
||||
tcase_add_test(tc, eet_test_data_type_encoding_decoding);
|
||||
tcase_add_test(tc, eet_test_data_type_dump_undump);
|
||||
tcase_add_test(tc, eet_test_data_type_escape_dump_undump);
|
||||
tcase_add_test(tc, eet_fp);
|
||||
tcase_add_test(tc, eet_test_union);
|
||||
tcase_add_test(tc, eet_test_variant);
|
||||
|
|
Loading…
Reference in New Issue