From d1c95193c1228537fcf5f7f47f76ae631edd541b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Oct 2020 12:07:16 -0700 Subject: [PATCH] query: Fix invalid use of slice::from_raw_parts --- cli/src/tests/query_test.rs | 30 ++++++++++++++++++++++++++++++ lib/binding_rust/lib.rs | 22 ++++++++++++++++++++-- lib/src/query.c | 4 ++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index efdaf780..323a13fc 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -1691,6 +1691,36 @@ fn test_query_matches_with_multiple_captures_on_a_node() { }); } +#[test] +fn test_query_matches_with_no_captures() { + allocations::record(|| { + let language = get_language("javascript"); + let query = Query::new( + language, + r#" + (identifier) + (string) @s + "#, + ) + .unwrap(); + + assert_query_matches( + language, + &query, + " + a = 'hi'; + b = 'bye'; + ", + &[ + (0, vec![]), + (1, vec![("s", "'hi'")]), + (0, vec![]), + (1, vec![("s", "'bye'")]), + ], + ); + }); +} + #[test] fn test_query_captures_basic() { allocations::record(|| { diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index 47b8d19d..372d937f 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -138,7 +138,7 @@ pub struct QueryCaptures<'a, T: AsRef<[u8]>> { } /// A particular `Node` that has been captured with a particular name within a `Query`. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] #[repr(C)] pub struct QueryCapture<'a> { pub node: Node<'a>, @@ -1272,7 +1272,11 @@ impl Query { let mut length = 0u32; let raw_predicates = ffi::ts_query_predicates_for_pattern(ptr, i as u32, &mut length as *mut u32); + if length > 0 { slice::from_raw_parts(raw_predicates, length as usize) + } else { + &[] + } }; let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr, i as u32) }; @@ -1649,11 +1653,15 @@ impl<'a> QueryMatch<'a> { cursor, id: m.id, pattern_index: m.pattern_index as usize, - captures: unsafe { + captures: if m.capture_count > 0 { + unsafe { slice::from_raw_parts( m.captures as *const QueryCapture<'a>, m.capture_count as usize, ) + } + } else { + &[] }, } } @@ -1729,6 +1737,16 @@ impl<'a, T: AsRef<[u8]>> Iterator for QueryCaptures<'a, T> { } } +impl<'a> fmt::Debug for QueryMatch<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}", + self.id, self.pattern_index, self.captures + ) + } +} + impl PartialEq for Query { fn eq(&self, other: &Self) -> bool { self.ptr == other.ptr diff --git a/lib/src/query.c b/lib/src/query.c index b6e48951..ce0e4cdf 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -1710,6 +1710,8 @@ static TSQueryError ts_query__parse_pattern( stream_reset(stream, node_name); return TSQueryErrorNodeType; } + + stream_skip_whitespace(stream); } // Parse the child patterns @@ -2518,6 +2520,7 @@ static inline bool ts_query_cursor__advance( } else if (ts_tree_cursor_goto_parent(&self->cursor)) { self->depth--; } else { + LOG("halt at root"); self->halted = true; } @@ -2582,6 +2585,7 @@ static inline bool ts_query_cursor__advance( self->end_byte <= ts_node_start_byte(node) || point_lte(self->end_point, ts_node_start_point(node)) ) { + LOG("halt at end of range"); self->halted = true; continue; }