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:
Gustavo Sverzut Barbieri 2014-03-13 22:00:27 -03:00
parent 6242271e74
commit f2a1f14abd
2 changed files with 67 additions and 17 deletions

View File

@ -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] != '\\'))
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 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] == '\\'))
TOK_ADD('\n');
else
TOK_ADD(p[0]);
}

View File

@ -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);