Title HTML spec single page doesn't load fully
AuthorRodrigo Arias Mallo
CreatedSat, 27 Jun 2026 11:03:54 +0200
State open

When loading the full HTML WHATWG spec in Dillo, only a subset of the page seems to be rendered.

https://html.spec.whatwg.org/ (warning: huge page)

We seem to have the whole thing in the cache entry:

% dilloc dump | wc -c
15563880
% curl -s https://html.spec.whatwg.org/ | wc -c
15563880
% dilloc dump | md5sum
00af5d9e18d6e98a0879b4ea45c9baed  -
% curl -s https://html.spec.whatwg.org/ | md5sum
00af5d9e18d6e98a0879b4ea45c9baed  -

Which ends with the license:

% dilloc dump | xq | tail
  International License</a>. To the extent portions of it are incorporated into source code, such
  portions in the source code are licensed under the
      <a rel="license" href="https://opensource.org/licenses/BSD-3-Clause">BSD 3-Clause License</a> instead.
    </p>
    <p>This is the Living Standard. Those interested in the patent-review version
  should view the
      <a href="/review-drafts/2026-01/">Living Standard Review Draft</a>.
    </p>
  </body>
</html>

But it doesn't reach the widget tree, the last section is 2.5.4 then it adds garbage:

    ...
    <dw::Textblock::Line>
      <dw::Textblock x=50 y=136006 w=695 h=101>
        <dw::Textblock::Line>
          <word w=42 h=18>2.5.4</word>
          <word w=47 h=18>CORS</word>
          <word w=69 h=18>settings</word>
          <word w=84 h=18>attributes</word>
        </dw::Textblock::Line>
      </dw::Textblock>
      <break/>
    </dw::Textblock::Line>
    <dw::Textblock::Line>
      <dw::Textblock x=50 y=136107 w=695 h=68>
        <dw::Textblock::Line>
          <unknown type=32/>
          <break/>
        </dw::Textblock::Line>
        <dw::Textblock::Line>
          <dw::Textblock x=54 y=136112 w=687 h=34>
            <dw::Textblock::Line>
              <dw::Textblock x=54 y=136126 w=687 h=20>
                <dw::Textblock::Line>
                  <word w=4 h=14>,</word> <--- hmm?
                  <word w=4 h=14>,</word>
                  <word w=4 h=14>,</word>
                </dw::Textblock::Line>
              </dw::Textblock>
              <break/>
            </dw::Textblock::Line>
          </dw::Textblock>
          <break/>
        </dw::Textblock::Line>
      </dw::Textblock>
      <break/>
    </dw::Textblock::Line>
  </dw::Textblock>
</resize>

Let's see if the sanitizer catches something. Nope.

Adding a print line to the open section shows that we are stopping at the 2.5.4, so the parser is stopping:

Html_tag_open_h(tag=<h4 id="content-type-sniffing"><span class="secno">2.5.2</span>)
Html_tag_open_h(tag=<h4 id="extracting-character-encodings-from-meta-elements"><spa)
Html_tag_open_h(tag=<h4 id="cors-settings-attributes"><span class="secno">2.5.4</sp)

Also, html->stop_parser is false, so it must be stopped by another condition. It seems it doesn't go past the 736782 byte:

Html_tag_open_h(tag=<h4 id="extracting-character-encodings-from-meta-elements"><spa)
Html_tag_open_h(tag=<h4 id="cors-settings-attributes"><span class="secno">2.5.4</sp)
DilloHtml::write BufSize=1535770 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=2093431 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=2224847 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=4387518 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=4909458 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=8756788 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=9124319 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=14841875 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=15563880 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=15563880 Start_Ofs=736782 EOF=0
DilloHtml::write BufSize=15563880 Start_Ofs=736782 EOF=1

We can dump what is at that location, and a bit before:

% dilloc dump | dd skip=736782 count=64 bs=1 status=none
, and <video> elements, provides support for CORS, defining how
% dilloc dump | dd skip=736762 count=64 bs=1 status=none
g>, <link>, <script>, and <video> elements, provides support for
            ^^^^^^^^
            here seems to be the problem

This seems to be coming from the title attribute of a link:

<a
    href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin"
    title="
        The crossorigin attribute, valid on the <audio>,
        <img>, <link>, <script>, and <video> elements, provides
        support for CORS, defining how the element handles
        cross-origin requests, thereby enabling the configuration
        of the CORS requests for the element's fetched data.
        Depending on the element, the attribute can be a CORS
        settings attribute.
    "
>Attributes/crossorigin</a>

Following https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 it seems to be acceptable for quoted attribute values to contain < or >.

However, this breaks the tag parser as it stops in <audio> instead of continuing until the </a> is found:

Html_tag_open_a(tag=<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin" title="The crossorigin attribute, valid on the <audio>)

Here seems to be the problem:

if ((ch = buf[buf_index]) == '>') {
   break;
} else if (ch == '"' || ch == '\'') {
   /* Skip over quoted string */
   buf_index++;
   buf_index += strcspn(buf + buf_index,
                        (ch == '"') ? "\">" : "'>");
   if (buf[buf_index] == '>') {
      /* Unterminated string value? Let's look ahead and test:
       * (<: unterminated, closing-quote: terminated) */
      int offset = buf_index + 1;
      offset += strcspn(buf + offset,
                        (ch == '"') ? "\"<" : "'<");
      if (buf[offset] == ch || !buf[offset]) {
         buf_index = offset;
      } else {
         BUG_MSG("Attribute lacks closing quote.");
         break;
      }
   }
} else if (ch == '<') {
...

The HTML spec from WHATWG seems to indicate that we should not treat < or > characters inside a quoted string differently:

https://html.spec.whatwg.org/multipage/parsing.html#attribute-value-(double-quoted)-state

In XML, we cannot have < inside an attribute value:

https://www.w3.org/TR/REC-xml/#NT-AttValue

For HTML 4.01 it is not very clear.

Removing the special handling for < allows Dillo to parse the whole HTML spec with no truncation.