Skip to content
Browse files

MB-5794 View parser didn't preserve escaping in strings

This includes a patch submitted upstream that tells YAJL
to not unescape strings before passing them to the user's
string callback function.

Upstream pull request:

lloyd/yajl#81

Change-Id: I9855e104dec2ce5bddaed526284afcca06d62c12
Reviewed-on: http://review.couchbase.org/17979
Reviewed-by: Volker Mische <volker.mische@gmail.com>
Tested-by: Filipe David Borba Manana <fdmanana@gmail.com>
  • Loading branch information...
1 parent 00bc008 commit 588f33dc74366d0e601fed50e705cae788b0c098 @fdmanana fdmanana committed with fdmanana Jul 6, 2012
View
1 src/couch_view_parser/couch_view_parser.cc
@@ -117,6 +117,7 @@ void initContext(ctx_t *context)
{
context->handle = yajl_alloc(&callbacks, NULL, (void *) context);
yajl_config(context->handle, yajl_dont_validate_strings, 1);
+ yajl_config(context->handle, yajl_dont_unescape_strings, 1);
context->level = 0;
context->row_count = NULL;
View
29 src/couch_view_parser/test/01-map-view.t
@@ -26,7 +26,7 @@
main(_) ->
test_util:init_code_path(),
- etap:plan(157),
+ etap:plan(161),
case (catch test()) of
ok ->
etap:end_tests();
@@ -59,6 +59,7 @@ test() ->
test_debug_info_4_rows(),
test_debug_info_4_rows_and_errors(),
test_all_docs_rows(),
+ test_quotes_in_string(),
ok.
@@ -956,3 +957,29 @@ test_all_docs_rows() ->
State3_2 = couch_view_parser:next_state(Ctx2),
etap:is(State3_2, {ok, done}, "State2 is {ok, done}"),
ok.
+
+
+test_quotes_in_string() ->
+ etap:diag("Testing double quotes inside strings are escaped"),
+ {ok, Ctx} = couch_view_parser:start_context(),
+ Json = [
+ <<"{">>,
+ <<"\"total_r">>, <<"ows\": 100,">>,
+ <<"\"rows\": [">>,
+ <<"{\"id\":\"doc_001\",\"key\":\"doc_001\",\"value\":1, \"doc\": {\"string\": \"foo \\\"bar\\\"\"}}">>,
+ <<"]}">>
+ ],
+ etap:is(couch_view_parser:parse_chunk(Ctx, Json),
+ ok,
+ "Success parsing row"),
+ State1 = couch_view_parser:next_state(Ctx),
+ etap:is(State1, {ok, row_count, "100"}, "State1 has row count"),
+ State2 = couch_view_parser:next_state(Ctx),
+ io:format("State2 is: ~p~n", [State2]),
+ ExpectedState2 = {ok, rows, [
+ {{<<"\"doc_001\"">>, <<"\"doc_001\"">>}, <<"1">>, <<"{\"string\":\"foo \\\"bar\\\"\"}">>}
+ ]},
+ etap:is(State2, ExpectedState2, "State2 has expected row"),
+ State3 = couch_view_parser:next_state(Ctx),
+ etap:is(State3, {ok, done}, "State3 is {ok, done}"),
+ ok.
View
1 src/couch_view_parser/yajl/yajl.c
@@ -91,6 +91,7 @@ yajl_config(yajl_handle h, yajl_option opt, ...)
case yajl_allow_trailing_garbage:
case yajl_allow_multiple_values:
case yajl_allow_partial_values:
+ case yajl_dont_unescape_strings:
if (va_arg(ap, int)) h->flags |= opt;
else h->flags &= ~opt;
break;
View
9 src/couch_view_parser/yajl/yajl_parse.h
@@ -156,7 +156,14 @@ extern "C" {
* yajl will enter an error state (premature EOF). Setting this
* flag suppresses that check and the corresponding error.
*/
- yajl_allow_partial_values = 0x10
+ yajl_allow_partial_values = 0x10,
+ /**
+ By default YAJL unescapes strings before passing them to the
+ string callback function. This options disables that behaviour.
+ Some applications might want the string escaped, and without this
+ option their string callback would have to escape the input string.
+ */
+ yajl_dont_unescape_strings = 0x20
} yajl_option;
/** allow the modification of parser options subsequent to handle
View
11 src/couch_view_parser/yajl/yajl_parser.c
@@ -246,11 +246,16 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
break;
case yajl_tok_string_with_escapes:
if (hand->callbacks && hand->callbacks->yajl_string) {
- yajl_buf_clear(hand->decodeBuf);
- yajl_string_decode(hand->decodeBuf, buf, bufLen);
- _CC_CHK(hand->callbacks->yajl_string(
+ if (hand->flags & yajl_dont_unescape_strings) {
+ _CC_CHK(hand->callbacks->yajl_string(hand->ctx,
+ buf, bufLen));
+ } else {
+ yajl_buf_clear(hand->decodeBuf);
+ yajl_string_decode(hand->decodeBuf, buf, bufLen);
+ _CC_CHK(hand->callbacks->yajl_string(
hand->ctx, yajl_buf_data(hand->decodeBuf),
yajl_buf_len(hand->decodeBuf)));
+ }
}
break;
case yajl_tok_bool:

0 comments on commit 588f33d

Please sign in to comment.
Something went wrong with that request. Please try again.