mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
68 lines
2.1 KiB
Plaintext
68 lines
2.1 KiB
Plaintext
/**
|
|
* @name Ambiguous HTML id attribute
|
|
* @description If an HTML document contains two elements with the
|
|
* same id attribute, it may be interpreted differently
|
|
* by different browsers.
|
|
* @kind problem
|
|
* @problem.severity warning
|
|
* @id js/duplicate-html-id
|
|
* @tags maintainability
|
|
* correctness
|
|
* @precision low
|
|
*/
|
|
|
|
import javascript
|
|
|
|
/**
|
|
* Holds if `attr` is an id attribute with value `id` of a DOM element
|
|
* under document `root` at the given `line` and `column`.
|
|
*
|
|
* Furthermore, the id is required to be valid, and not look like a template.
|
|
*/
|
|
predicate idAt(
|
|
DOM::AttributeDefinition attr, string id, DOM::ElementDefinition root, int line, int column
|
|
) {
|
|
exists(DOM::ElementDefinition elt | attr = elt.getAttributeByName("id") |
|
|
id = attr.getStringValue() and
|
|
root = elt.getRoot() and
|
|
elt.getLocation().hasLocationInfo(_, line, column, _, _) and
|
|
// exclude invalid ids (reported by another query)
|
|
not DOM::isInvalidHtmlIdAttributeValue(attr, _)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if attributes `earlier` and `later` are id attributes with the same value in
|
|
* the same document, and `earlier` appears textually before `later`.
|
|
*/
|
|
predicate sameId(
|
|
DOM::ElementDefinition root, DOM::AttributeDefinition earlier, DOM::AttributeDefinition later
|
|
) {
|
|
exists(string id, int l1, int c1, int l2, int c2 |
|
|
idAt(earlier, id, root, l1, c1) and idAt(later, id, root, l2, c2)
|
|
|
|
|
l1 < l2
|
|
or
|
|
l1 = l2 and c1 < c2
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if any attribute value in `root` looks like it is templated.
|
|
*/
|
|
predicate mayContainTemplates(DOM::ElementDefinition root) {
|
|
exists(DOM::AttributeDefinition attr |
|
|
attr.mayHaveTemplateValue() and
|
|
root = attr.getElement().getRoot()
|
|
)
|
|
}
|
|
|
|
from DOM::ElementDefinition root, DOM::AttributeDefinition earlier, DOM::AttributeDefinition later
|
|
where
|
|
sameId(root, earlier, later) and
|
|
// only flag the first ambiguity if there are many
|
|
not sameId(root, _, earlier) and
|
|
// exclude templates
|
|
not mayContainTemplates(root)
|
|
select earlier, "This element has the same id as $@.", later, "another element"
|