fix: harden comment serialization and DOMSnapshot recursion depth
fix: harden comment serialization and DOMSnapshot recursion depth
This commit is contained in:
2 files changed
+32
-11
No files matched your search
@@ -84,21 +84,32 @@ impl Interner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Pre-order DFS from the document, recording each node and its parent's index.
|
/// Pre-order DFS from the document, recording each node and its parent's index.
|
||||||
|
/// Iterative with an explicit stack: the MAX_NODES cap bounds the node count,
|
||||||
|
/// but recursion depth is a separate axis. A deeply nested linear chain (script
|
||||||
|
/// can build thousands of nested elements) would recurse that many frames deep
|
||||||
|
/// and could overflow the stack before the count guard triggers. An explicit
|
||||||
|
/// stack keeps the depth on the heap (issue #341).
|
||||||
fn walk(
|
fn walk(
|
||||||
dom: &DomTree,
|
dom: &DomTree,
|
||||||
id: NodeId,
|
root: NodeId,
|
||||||
parent: i64,
|
root_parent: i64,
|
||||||
order: &mut Vec<NodeId>,
|
order: &mut Vec<NodeId>,
|
||||||
parent_idx: &mut Vec<i64>,
|
parent_idx: &mut Vec<i64>,
|
||||||
) {
|
) {
|
||||||
if order.len() >= MAX_NODES {
|
// (node, parent_index). Children are pushed in reverse so they pop in
|
||||||
return;
|
// document order, preserving the original pre-order traversal.
|
||||||
}
|
let mut stack: Vec<(NodeId, i64)> = vec![(root, root_parent)];
|
||||||
let my = order.len() as i64;
|
while let Some((id, parent)) = stack.pop() {
|
||||||
order.push(id);
|
if order.len() >= MAX_NODES {
|
||||||
parent_idx.push(parent);
|
break;
|
||||||
for child in dom.children(id) {
|
}
|
||||||
walk(dom, child, my, order, parent_idx);
|
let my = order.len() as i64;
|
||||||
|
order.push(id);
|
||||||
|
parent_idx.push(parent);
|
||||||
|
let children: Vec<NodeId> = dom.children(id);
|
||||||
|
for child in children.into_iter().rev() {
|
||||||
|
stack.push((child, my));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,17 @@ impl DomTree {
|
|||||||
}
|
}
|
||||||
NodeData::Comment { contents } => {
|
NodeData::Comment { contents } => {
|
||||||
buf.push_str("<!--");
|
buf.push_str("<!--");
|
||||||
buf.push_str(contents);
|
// The HTML parser can never produce a comment whose data contains
|
||||||
|
// "-->" (that ends the comment), but script can via
|
||||||
|
// document.createComment("a-->b"). Emitting it verbatim would close
|
||||||
|
// the comment early and let the trailing text escape into markup.
|
||||||
|
// Neutralize the terminator so the serialized output round-trips as
|
||||||
|
// a single comment.
|
||||||
|
if contents.contains("-->") {
|
||||||
|
buf.push_str(&contents.replace("-->", "-->"));
|
||||||
|
} else {
|
||||||
|
buf.push_str(contents);
|
||||||
|
}
|
||||||
buf.push_str("-->");
|
buf.push_str("-->");
|
||||||
}
|
}
|
||||||
NodeData::ProcessingInstruction { target, data } => {
|
NodeData::ProcessingInstruction { target, data } => {
|
||||||
|
|||||||
Reference in new issue
Block a user