Skip to content

Commit

Permalink
rustdoc: parse self-closing tags and attributes in invalid_html_tags
Browse files Browse the repository at this point in the history
Fixes #103460
  • Loading branch information
notriddle committed Oct 25, 2022
1 parent 758f196 commit f9cace0
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 1 deletion.
55 changes: 54 additions & 1 deletion src/librustdoc/passes/html_tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,60 @@ fn extract_html_tag(
}
drop_tag(tags, tag_name, r, f);
} else {
tags.push((tag_name, r));
let mut is_self_closing = false;
let mut quote_pos = None;
if c != '>' {
let mut quote = None;
let mut after_eq = false;
for (i, c) in text[pos..].char_indices() {
if !c.is_whitespace() {
if let Some(q) = quote {
if c == q {
quote = None;
quote_pos = None;
after_eq = false;
}
} else if c == '>' {
break;
} else if c == '/' && !after_eq {
is_self_closing = true;
} else {
if is_self_closing {
is_self_closing = false;
}
if (c == '"' || c == '\'') && after_eq {
quote = Some(c);
quote_pos = Some(pos + i);
} else if c == '=' {
after_eq = true;
}
}
} else if quote.is_none() {
after_eq = false;
}
}
}
if let Some(quote_pos) = quote_pos {
let qr = Range { start: quote_pos, end: quote_pos };
f(
&format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
&qr,
false,
);
}
if is_self_closing {
// https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..])
|| tags.iter().take(pos + 1).any(|(at, _)| {
let at = at.to_lowercase();
at == "svg" || at == "math"
});
if !valid {
f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
}
} else {
tags.push((tag_name, r));
}
}
}
break;
Expand Down
70 changes: 70 additions & 0 deletions src/test/rustdoc-ui/invalid-html-self-closing-tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#![deny(rustdoc::invalid_html_tags)]

/// <p/>
//~^ ERROR invalid self-closing HTML tag `p`
pub struct A;

/// <p style/>
//~^ ERROR invalid self-closing HTML tag `p`
pub struct B;

/// <p style=""/>
//~^ ERROR invalid self-closing HTML tag `p`
pub struct C;

/// <p style="x"/>
//~^ ERROR invalid self-closing HTML tag `p`
pub struct D;

/// <p style="x/></p>
//~^ ERROR unclosed quoted HTML attribute
pub struct E;

/// <p style='x/></p>
//~^ ERROR unclosed quoted HTML attribute
pub struct F;

/// <p style="x/"></p>
pub struct G;

/// <p style="x/"/>
//~^ ERROR invalid self-closing HTML tag `p`
pub struct H;

/// <p / >
//~^ ERROR invalid self-closing HTML tag `p`
pub struct I;

/// <br/>
pub struct J;

/// <a href=/></a>
pub struct K;

/// <a href=//></a>
pub struct L;

/// <a href="/"/>
//~^ ERROR invalid self-closing HTML tag `a`
pub struct M;

/// <a href=x />
//~^ ERROR invalid self-closing HTML tag `a`
pub struct N;

/// <a href= />
//~^ ERROR invalid self-closing HTML tag `a`
pub struct O;

/// <a href=x/></a>
pub struct P;

/// <svg><rect width=1 height=1 /></svg>
pub struct Q;

/// <svg><rect width=1 height=/></svg>
//~^ ERROR unclosed HTML tag `rect`
pub struct R;

/// <svg / q>
pub struct S;
80 changes: 80 additions & 0 deletions src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:3:5
|
LL | /// <p/>
| ^^
|
note: the lint level is defined here
--> $DIR/invalid-html-self-closing-tag.rs:1:9
|
LL | #![deny(rustdoc::invalid_html_tags)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:7:5
|
LL | /// <p style/>
| ^^

error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:11:5
|
LL | /// <p style=""/>
| ^^

error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:15:5
|
LL | /// <p style="x"/>
| ^^

error: unclosed quoted HTML attribute on tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:19:14
|
LL | /// <p style="x/></p>
| ^

error: unclosed quoted HTML attribute on tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:23:14
|
LL | /// <p style='x/></p>
| ^

error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:30:5
|
LL | /// <p style="x/"/>
| ^^

error: invalid self-closing HTML tag `p`
--> $DIR/invalid-html-self-closing-tag.rs:34:5
|
LL | /// <p / >
| ^^

error: invalid self-closing HTML tag `a`
--> $DIR/invalid-html-self-closing-tag.rs:47:5
|
LL | /// <a href="/"/>
| ^^

error: invalid self-closing HTML tag `a`
--> $DIR/invalid-html-self-closing-tag.rs:51:5
|
LL | /// <a href=x />
| ^^

error: invalid self-closing HTML tag `a`
--> $DIR/invalid-html-self-closing-tag.rs:55:5
|
LL | /// <a href= />
| ^^

error: unclosed HTML tag `rect`
--> $DIR/invalid-html-self-closing-tag.rs:65:10
|
LL | /// <svg><rect width=1 height=/></svg>
| ^^^^^

error: aborting due to 12 previous errors

0 comments on commit f9cace0

Please sign in to comment.