floki icon indicating copy to clipboard operation
floki copied to clipboard

CDATA inside a title tag is not handled in Mochiweb parser

Open mdg opened this issue 1 year ago • 0 comments

Description

First, it's not clear to me that this is a bug or just a difference in expected behavior since I'm trying to use Floki to parse XML rather than HTML.

The issue is that CDATA inside of a

tag is not handled. <h2>To Reproduce</h2> <p>Steps to reproduce the behavior:</p> <ul> <li>Using Floki v0.34.1</li> <li>Using Elixir 1.14.0 (compiled with Erlang/OTP 24)</li> <li>Using Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]</li> <li>With this code: <pre><code class="language-elixir"># An example to reproduce the problem iex(44)> Floki.parse_document!("<title><![CDATA[handle CDATA]]></title>") [{"title", [], ["<![CDATA[handle CDATA]]>"]}] iex(45)> Floki.parse_document!("<tacos><![CDATA[handle CDATA]]></tacos>") [{"tacos", [], ["handle CDATA"]}] </code></pre> </li> </ul> <h2>Expected behavior</h2> <p>I would expect it to behave like other tags.</p> <pre><code class="language-elixir"># An example to reproduce the problem iex(44)> Floki.parse_document!("<title><![CDATA[handle CDATA]]></title>") [{"title", [], ["handle CDATA"]}] </code></pre> <p>I recognize that this is maybe an artifact of trying to use the library for the wrong purpose (parsing XML) so no problem if you want to close this as "won't fix" or whatever.</p> <h2>Patch</h2> <p>If you do want to fix it, here's a patch that appears to do it.</p> <pre><code>diff --git a/src/floki_mochi_html.erl b/src/floki_mochi_html.erl index d4e3337..4096161 100644 --- a/src/floki_mochi_html.erl +++ b/src/floki_mochi_html.erl @@ -301,13 +301,10 @@ tokens(B, S=#decoder{offset=O}, Acc) -> {Tag2, S2} = tokenize_script(B, S1), tokens(B, S2, [Tag2, Tag | Acc]); style -> {Tag2, S2} = tokenize_style(B, S1), tokens(B, S2, [Tag2, Tag | Acc]); - title -> - {Tag2, S2} = tokenize_title(B, S1), - tokens(B, S2, [Tag2, Tag | Acc]); textarea -> {Tag2, S2} = tokenize_textarea(B, S1), tokens(B, S2, [Tag2, Tag | Acc]); none -> tokens(B, S1, [Tag | Acc]) @@ -318,12 +315,10 @@ parse_flag({start_tag, B, _, false}) -> case string:to_lower(binary_to_list(B)) of "script" -> script; "style" -> style; - "title" -> - title; "textarea" -> textarea; _ -> none end; @@ -822,32 +817,10 @@ tokenize_style(Bin, S=#decoder{offset=O}, Start) -> tokenize_style(Bin, ?INC_CHAR(S, C), Start); <<_:Start/binary, Raw/binary>> -> {{data, Raw, false}, S} end. -tokenize_title(Bin, S=#decoder{offset=O}) -> - tokenize_title(Bin, S, O). - -tokenize_title(Bin, S=#decoder{offset=O}, Start) -> - case Bin of - %% Just a look-ahead, we want the end_tag separately - <<_:O/binary, $<, $/, TT, II, TT2, LL, EE, ZZ, _/binary>> - when (TT=:= $t orelse TT =:= $T) andalso - (II=:= $i orelse II =:= $I) andalso - (TT2=:= $t orelse TT2 =:= $T) andalso - (LL=:= $l orelse LL =:= $L) andalso - (EE=:= $e orelse EE =:= $E) andalso - ?PROBABLE_CLOSE(ZZ) -> - Len = O - Start, - <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, - {{data, Raw, false}, S}; - <<_:O/binary, C, _/binary>> -> - tokenize_title(Bin, ?INC_CHAR(S, C), Start); - <<_:Start/binary, Raw/binary>> -> - {{data, Raw, false}, S} - end. - tokenize_textarea(Bin, S=#decoder{offset=O}) -> tokenize_textarea(Bin, S, O). tokenize_textarea(Bin, S=#decoder{offset=O}, Start) -> case Bin of </code></pre>

mdg avatar Mar 02 '23 05:03 mdg