Skip to content

Commit f3d50f2

Browse files
committed
fix(lib): add saturating subtraction to prevent integer underflow
1 parent 7ba0f29 commit f3d50f2

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

cli/src/tests/query_test.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use lazy_static::lazy_static;
55
use rand::{prelude::StdRng, SeedableRng};
66
use streaming_iterator::StreamingIterator;
77
use tree_sitter::{
8-
CaptureQuantifier, Language, Node, Parser, Point, Query, QueryCursor, QueryCursorOptions,
9-
QueryError, QueryErrorKind, QueryPredicate, QueryPredicateArg, QueryProperty,
8+
CaptureQuantifier, InputEdit, Language, Node, Parser, Point, Query, QueryCursor,
9+
QueryCursorOptions, QueryError, QueryErrorKind, QueryPredicate, QueryPredicateArg,
10+
QueryProperty, Range,
1011
};
1112
use tree_sitter_generate::generate_parser_for_grammar;
1213
use unindent::Unindent;
@@ -5334,3 +5335,72 @@ fn test_query_execution_with_timeout() {
53345335
.count();
53355336
assert_eq!(matches, 1000);
53365337
}
5338+
5339+
#[test]
5340+
fn idk() {
5341+
let language = get_language("rust");
5342+
let mut parser = Parser::new();
5343+
parser.set_language(&language).unwrap();
5344+
5345+
let code = r#"fn main() {
5346+
println!("{:?}", foo());
5347+
}"#;
5348+
parser
5349+
.set_included_ranges(&[Range {
5350+
start_byte: 24,
5351+
end_byte: 39,
5352+
start_point: Point::new(0, 0), // 5, 12
5353+
end_point: Point::new(0, 0), // 5, 27
5354+
}])
5355+
.unwrap();
5356+
5357+
let query = Query::new(&language, "(call_expression) @cap").unwrap();
5358+
let mut cursor = QueryCursor::new();
5359+
5360+
let mut tree = parser.parse(code, None).unwrap();
5361+
5362+
let matches = {
5363+
let root_node = tree.root_node();
5364+
let matches = cursor.matches(&query, root_node, code.as_bytes());
5365+
collect_matches(matches, &query, code)
5366+
.into_iter()
5367+
.map(|(i, m)| {
5368+
(
5369+
i,
5370+
m.into_iter()
5371+
.map(|(k, v)| (k.to_string(), v.to_string()))
5372+
.collect::<Vec<_>>(),
5373+
)
5374+
})
5375+
.collect::<Vec<_>>()
5376+
};
5377+
5378+
tree.edit(&InputEdit {
5379+
start_byte: 40,
5380+
old_end_byte: 40,
5381+
new_end_byte: 41,
5382+
start_position: Point::new(1, 28),
5383+
old_end_position: Point::new(1, 28),
5384+
new_end_position: Point::new(2, 0),
5385+
});
5386+
5387+
let tree2 = parser.parse(code, Some(&tree)).unwrap();
5388+
5389+
let matches2 = {
5390+
let root_node = tree2.root_node();
5391+
let matches = cursor.matches(&query, root_node, code.as_bytes());
5392+
collect_matches(matches, &query, code)
5393+
.into_iter()
5394+
.map(|(i, m)| {
5395+
(
5396+
i,
5397+
m.into_iter()
5398+
.map(|(k, v)| (k.to_string(), v.to_string()))
5399+
.collect::<Vec<_>>(),
5400+
)
5401+
})
5402+
.collect::<Vec<_>>()
5403+
};
5404+
5405+
assert_eq!(matches, matches2);
5406+
}

lib/src/length.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static inline Length length_add(Length len1, Length len2) {
3131

3232
static inline Length length_sub(Length len1, Length len2) {
3333
Length result;
34-
result.bytes = len1.bytes - len2.bytes;
34+
result.bytes = (len1.bytes >= len2.bytes) ? len1.bytes - len2.bytes : 0;
3535
result.extent = point_sub(len1.extent, len2.extent);
3636
return result;
3737
}

lib/src/point.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ static inline TSPoint point_sub(TSPoint a, TSPoint b) {
2222
if (a.row > b.row)
2323
return point__new(a.row - b.row, a.column);
2424
else
25-
return point__new(0, a.column - b.column);
25+
return point__new(0, (a.column >= b.column) ? a.column - b.column : 0);
2626
}
2727

2828
static inline bool point_lte(TSPoint a, TSPoint b) {

0 commit comments

Comments
 (0)