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;
}
-
-