Skip to content

Commit 193671c

Browse files
fix: infinite recursion with SQL params (#555)
Fixes #554 and maybe #516
1 parent 380fcfc commit 193671c

File tree

1 file changed

+42
-1
lines changed
  • crates/pgt_treesitter/src/context

1 file changed

+42
-1
lines changed

crates/pgt_treesitter/src/context/mod.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,9 @@ impl<'a> TreesitterContext<'a> {
470470
}
471471

472472
// We have arrived at the leaf node
473-
if current_node.child_count() == 0 {
473+
if current_node.child_count() == 0
474+
|| current_node.first_child_for_byte(self.position).is_none()
475+
{
474476
self.node_under_cursor = Some(NodeUnderCursor::from(current_node));
475477
return;
476478
}
@@ -1214,4 +1216,43 @@ mod tests {
12141216
_ => unreachable!(),
12151217
}
12161218
}
1219+
1220+
#[test]
1221+
fn does_not_overflow_callstack_on_smaller_treesitter_child() {
1222+
let query = format!(
1223+
r#"select * from persons where id = @i{}d;"#,
1224+
QueryWithCursorPosition::cursor_marker()
1225+
);
1226+
1227+
/*
1228+
The query (currently) yields the following treesitter tree for the WHERE clause:
1229+
1230+
where [29..43] 'where id = @id'
1231+
keyword_where [29..34] 'where'
1232+
binary_expression [35..43] 'id = @id'
1233+
field [35..37] 'id'
1234+
identifier [35..37] 'id'
1235+
= [38..39] '='
1236+
field [40..43] '@id'
1237+
identifier [40..43] '@id'
1238+
@ [40..41] '@'
1239+
1240+
You can see that the '@' is a child of the "identifier" but has a range smaller than its parent's.
1241+
This would crash our context parsing because, at position 42, we weren't at the leaf node but also couldn't
1242+
go to a child on that position.
1243+
*/
1244+
1245+
let (position, text) = QueryWithCursorPosition::from(query).get_text_and_position();
1246+
1247+
let tree = get_tree(text.as_str());
1248+
1249+
let params = TreeSitterContextParams {
1250+
position: (position as u32).into(),
1251+
text: &text,
1252+
tree: &tree,
1253+
};
1254+
1255+
// should simply not panic
1256+
let _ = TreesitterContext::new(params);
1257+
}
12171258
}

0 commit comments

Comments
 (0)