Re: [patch] HTML parser bugfix

123 <[email protected]>
Newsgroups gmane.comp.web.dillo.devel
Message-ID <[email protected]>
Forgot to attach.

_______________________________________________
Dillo-dev mailing list
[email protected]
http://lists.auriga.wearlab.de/cgi-bin/mailman/listinfo/dillo-dev
dilloparser.patch (text/plain, 10.2 KB)
diff -r 6d07beeb3d51 src/html.cc
--- a/src/html.cc	Mon May 28 21:40:15 2012 +0200
+++ b/src/html.cc	Thu Jun 07 16:37:57 2012 +0400
@@ -103,7 +103,7 @@
                                   int tagsize,
                                   const char *attrname,
                                   int tag_parsing_flags);
-static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof);
+static int Html_write_raw(DilloHtml *html, char *buf, size_t bufsize, int Eof);
 static bool Html_load_image(BrowserWindow *bw, DilloUrl *url,
                             const DilloUrl *requester, DilloImage *image);
 static void Html_callback(int Op, CacheClient_t *Client);
@@ -3490,18 +3490,14 @@
 {
    int ci, ni;           /* current and new tag indexes */
    char *start = tag + 1; /* discard the '<' */
-   int IsCloseTag = (*start == '/');
+   int IsCloseTag = *start == '/';
 
    dReturn_if (html->stop_parser == true);
 
    ni = a_Html_tag_index(start + IsCloseTag);
+   /* Ignore unknown tags */
    if (ni == -1) {
-      /* TODO: doctype parsing is a bit fuzzy, but enough for the time being */
-      if (!(html->InFlags & IN_HTML)) {
-         if (tagsize > 9 && !dStrnAsciiCasecmp(tag, "<!doctype", 9))
-            Html_parse_doctype(html, tag, tagsize);
-      }
-      /* Ignore unknown tags */
+      BUG_MSG("unknown tag\n");
       return;
    }
 
@@ -3759,24 +3755,36 @@
    }
 }
 
+/* Bogus comment state */
+static ssize_t Html_parse_bogus_comment(DilloHtml *html, char *buf, size_t bufsize, int Eof) {
+   char *p = (char *)memchr(buf, '>', bufsize);
+
+   if(p == NULL)
+      return -1;
+   else {
+      BUG_MSG("bogus comment\n");
+      return p - buf + 1;
+   }
+}
+
 /*
  * Here's where we parse the html and put it into the Textblock structure.
  * Return value: number of bytes parsed
  */
-static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof)
+static int Html_write_raw(DilloHtml *html, char *buf, size_t bufsize, int Eof)
 {
-   char ch = 0, *p, *text;
-   int token_start, buf_index;
+   char ch, *p, *text;
+   size_t token_start, buf_index;
+   ssize_t s;
 
    /* Now, 'buf' and 'bufsize' define a buffer aligned to start at a token
     * boundary. Iterate through tokens until end of buffer is reached. */
-   buf_index = 0;
-   token_start = buf_index;
-   while ((buf_index < bufsize) && !html->stop_parser) {
+   token_start = buf_index = 0;
+
+   while (buf_index < bufsize && !html->stop_parser) {
       /* invariant: buf_index == bufsize || token_start == buf_index */
 
-      if (S_TOP(html)->parse_mode ==
-          DILLO_HTML_PARSE_MODE_VERBATIM) {
+      if (S_TOP(html)->parse_mode == DILLO_HTML_PARSE_MODE_VERBATIM) {
          /* Non HTML code here, let's skip until closing tag */
          do {
             const char *tag = Tags[S_TOP(html)->tag_idx].name;
@@ -3799,59 +3807,104 @@
             break;
       }
 
-      if (isspace(buf[buf_index])) {
-         /* whitespace: group all available whitespace */
-         while (++buf_index < bufsize && isspace(buf[buf_index])) ;
-         Html_process_space(html, buf + token_start, buf_index - token_start);
-         token_start = buf_index;
-
-      } else if (buf[buf_index] == '<' && (ch = buf[buf_index + 1]) &&
-                 (isalpha(ch) || strchr("/!?", ch)) ) {
-         /* Tag */
-         if (buf_index + 3 < bufsize && !strncmp(buf + buf_index, "<!--", 4)) {
-            /* Comment: search for close of comment, skipping over
-             * everything except a matching "-->" tag. */
-            while ( (p = (char*) memchr(buf + buf_index, '>',
-                                        bufsize - buf_index)) ){
-               buf_index = p - buf + 1;
-               if (p[-1] == '-' && p[-2] == '-') break;
+      /* Data state */
+      html->CurrTagOfs = html->Start_Ofs + token_start;
+      assert(buf_index < bufsize);
+      ch = buf[buf_index++];
+      if (ch == '<') {
+         if(buf_index == bufsize)
+            break;
+         ch = buf[buf_index++];
+         /* Tag open state */
+         if(ch == '!') {
+            /* Markup declaration open state */
+            if(buf_index + 1 < bufsize && memcmp(buf + buf_index, "--", 2) == 0) {
+               /* Comment start state */
+               buf_index += 2;
+               if(buf_index == bufsize)
+                  break;
+
+               if(buf[buf_index] == '>') {
+                  BUG_MSG("<!--> comment\n");
+                  buf_index++;
+                  token_start = buf_index;
+               } else if(buf_index + 1 < bufsize && strcmp(buf + buf_index, "->") == 0) {
+                  BUG_MSG("<!---> comment\n");
+                  buf_index += 2;
+                  token_start = buf_index;
+               }
+
+               /* Comment state */
+               p = (char *)memchr(buf + buf_index, '-', bufsize - buf_index);
+               if (p == NULL)
+                  buf_index = bufsize;
+               else
+                  buf_index = p - buf + 1;
+
+               while ((p = (char *)memchr(buf + buf_index, '>', bufsize - buf_index)) != NULL){
+                  /* Comment end dash state */
+                  buf_index = p - buf + 1;
+                  if (p[-1] == '-' && p[-2] == '-')
+                     break;
+               }
+
+               if (p == NULL)
+                  buf_index = bufsize;
+               else
+                  token_start = buf_index;
+            } else if(buf_index + 6 < bufsize && strncasecmp(buf + buf_index, "DOCTYPE", 7) == 0) {
+               /* DOCTYPE state */
+               buf_index += 7;
+               p = (char *)memchr(buf + buf_index, '>', bufsize - buf_index);
+
+               if (p == NULL)
+                  buf_index = bufsize;
+               else {
+                  buf_index = p - buf + 1;
+                  if (!(html->InFlags & IN_HTML))
+                     Html_parse_doctype(html, buf + token_start, buf_index - token_start);
+                  token_start = buf_index;
+               }
+            } else {
+               s = Html_parse_bogus_comment(html, buf + buf_index, bufsize - buf_index, Eof);
+               if (s == -1)
+                  buf_index = bufsize;
+               else {
+                  buf_index += s;
+                  token_start = buf_index;
+               }
             }
-            if (p) {
-               /* Got the whole comment. Let's throw it away! :) */
+         } else if(ch == '?') {
+            s = Html_parse_bogus_comment(html, buf + buf_index, bufsize - buf_index, Eof);
+            if (s == -1)
+               buf_index = bufsize;
+            else {
+               buf_index += s;
                token_start = buf_index;
-            } else
-               buf_index = bufsize;
+            }
          } else {
+            /* End tag if ch == '/', tag name if ch is latin letter */
+            /* End tag open state or tag name state */
+
+            /* TODO: move to separate Html_parse_tag */
+
+            buf_index -= 2;
             /* Tag: search end of tag (skipping over quoted strings) */
-            html->CurrTagOfs = html->Start_Ofs + token_start;
-
-            while ( buf_index < bufsize ) {
+
+            while (buf_index < bufsize) {
                buf_index++;
                buf_index += strcspn(buf + buf_index, ">\"'<");
-               if ((ch = buf[buf_index]) == '>') {
+               ch = buf[buf_index];
+               if (ch == '>')
                   break;
-               } else if (ch == '"' || ch == '\'') {
+               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\n");
-                        break;
-                     }
-                  }
+                  buf_index += strcspn(buf + buf_index, ch == '"' ? "\"" : "'");
                } else if (ch == '<') {
-                  /* unterminated tag detected */
-                  p = dStrndup(buf+token_start+1,
-                               strcspn(buf+token_start+1, " <"));
+                  /* Unterminated tag detected */
+                  p = dStrndup(buf + token_start + 1,
+                               strcspn(buf + token_start + 1, " <"));
                   BUG_MSG("<%s> element lacks its closing '>'\n", p);
                   dFree(p);
                   --buf_index;
@@ -3860,12 +3913,18 @@
             }
             if (buf_index < bufsize) {
                buf_index++;
-               Html_process_tag(html, buf + token_start,
-                                buf_index - token_start);
+               Html_process_tag(html, buf + token_start, buf_index - token_start);
                token_start = buf_index;
             }
          }
+      } else if (isspace(ch)) {
+         buf_index--;
+         /* whitespace: group all available whitespace */
+         while (++buf_index < bufsize && isspace(buf[buf_index]));
+         Html_process_space(html, buf + token_start, buf_index - token_start);
+         token_start = buf_index;
       } else {
+         buf_index--;
          /* A Word: search for whitespace or tag open */
          while (++buf_index < bufsize) {
             buf_index += strcspn(buf + buf_index, " <\n\r\t\f\v");
@@ -3878,17 +3937,14 @@
             /* successfully found end of token */
             ch = buf[buf_index];
             buf[buf_index] = 0;
-            Html_process_word(html, buf + token_start,
-                              buf_index - token_start);
+            Html_process_word(html, buf + token_start, buf_index - token_start);
             buf[buf_index] = ch;
             token_start = buf_index;
          }
       }
-   }/*while*/
+   }
 
    HT2TB(html)->flush ();
 
    return token_start;
 }
-
-
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.