diff --git a/src/jsx_encoder.erl b/src/jsx_encoder.erl index 3b3fae8..27f2900 100644 --- a/src/jsx_encoder.erl +++ b/src/jsx_encoder.erl @@ -160,6 +160,9 @@ json_escape(<<$\t, Rest/binary>>, Acc) -> %% other control characters json_escape(<>, Acc) when C >= 0, C < $\s -> json_escape(Rest, <>); +%% escape u+2028 and u+2029 to avoid problems with jsonp +json_escape(<>, Acc) when C == 16#2028; C == 16#2029 -> + json_escape(Rest, <>); %% any other legal codepoint json_escape(<>, Acc) -> json_escape(Rest, <>); @@ -169,11 +172,10 @@ json_escape(_, _) -> erlang:error(badarg). -%% convert a codepoint to it's \uXXXX equiv. for laziness, this only handles -%% codepoints this module might escape, ie, control characters -json_escape_sequence(C) when C < 16#20 -> - <<_:8, A:4, B:4>> = <>, % first two hex digits are always zero - <<$\\, $u, $0, $0, (to_hex(A)), (to_hex(B))>>. +%% convert a codepoint to it's \uXXXX equiv. +json_escape_sequence(X) -> + <> = <>, + <<$\\, $u, (to_hex(A)), (to_hex(B)), (to_hex(C)), (to_hex(D))>>. to_hex(15) -> $f; diff --git a/src/jsx_terms.erl b/src/jsx_terms.erl index ecd947a..c1ce743 100644 --- a/src/jsx_terms.erl +++ b/src/jsx_terms.erl @@ -236,6 +236,9 @@ json_escape(<<$\t, Rest/binary>>, Acc) -> %% other control characters json_escape(<>, Acc) when C >= 0, C < $\s -> json_escape(Rest, <>); +%% escape u+2028 and u+2029 to avoid problems with jsonp +json_escape(<>, Acc) when C == 16#2028; C == 16#2029 -> + json_escape(Rest, <>); %% any other legal codepoint json_escape(<>, Acc) -> json_escape(Rest, <>); @@ -245,11 +248,10 @@ json_escape(_, _) -> erlang:error(badarg). -%% convert a codepoint to it's \uXXXX equiv. for laziness, this only handles -%% codepoints this module might escape, ie, control characters -json_escape_sequence(C) when C < 16#20 -> - <<_:8, A:4, B:4>> = <>, % first two hex digits are always zero - <<$\\, $u, $0, $0, (to_hex(A)), (to_hex(B))>>. +%% convert a codepoint to it's \uXXXX equiv. +json_escape_sequence(X) -> + <> = <>, + <<$\\, $u, (to_hex(A)), (to_hex(B)), (to_hex(C)), (to_hex(D))>>. to_hex(15) -> $f; @@ -402,6 +404,12 @@ escape_test_() -> <<1, 2, 3, 11, 26, 30, 31>> ) =:= <<"\\u0001\\u0002\\u0003\\u000b\\u001a\\u001e\\u001f">> ) + }, + {"jsonp protection", + ?_assert(json_escape( + <<226, 128, 168, 226, 128, 169>> + ) =:= <<"\\u2028\\u2029">> + ) } ].