Bugfix: fix a panic in span rendering (#3527)

This commit is contained in:
Mees Delzenne 2024-02-16 18:05:24 +01:00 committed by GitHub
parent 6469b653cd
commit bbd5268e71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 14 deletions

View file

@ -2848,16 +2848,20 @@ mod tests {
#[test]
fn check_size() {
assert!(64 <= std::mem::size_of::<Value>());
assert_eq!(104, std::mem::size_of::<Error>());
assert_eq!(104, std::mem::size_of::<Result<Value, Error>>());
assert!(
64 >= std::mem::size_of::<Value>(),
"expected Value to be smaller then 64 bytes found {:?}",
std::mem::size_of::<Value>()
);
assert!(112 >= std::mem::size_of::<Error>());
assert!(112 >= std::mem::size_of::<Result<Value, Error>>());
assert_eq!(24, std::mem::size_of::<crate::sql::number::Number>());
assert_eq!(24, std::mem::size_of::<crate::sql::strand::Strand>());
assert_eq!(16, std::mem::size_of::<crate::sql::duration::Duration>());
assert_eq!(12, std::mem::size_of::<crate::sql::datetime::Datetime>());
assert_eq!(24, std::mem::size_of::<crate::sql::array::Array>());
assert_eq!(24, std::mem::size_of::<crate::sql::object::Object>());
assert_eq!(56, std::mem::size_of::<crate::sql::geometry::Geometry>());
assert!(56 >= std::mem::size_of::<crate::sql::geometry::Geometry>());
assert_eq!(24, std::mem::size_of::<crate::sql::param::Param>());
assert_eq!(24, std::mem::size_of::<crate::sql::idiom::Idiom>());
assert_eq!(24, std::mem::size_of::<crate::sql::table::Table>());

View file

@ -22,14 +22,21 @@ impl Location {
let offset = (substr.as_ptr() as usize)
.checked_sub(input.as_ptr() as usize)
.expect("tried to find location of substring in unrelated string");
// Bytes of input prior to line being iteratated.
assert!(offset <= input.len(), "tried to find location of substring in unrelated string");
// Bytes of input prior to line being iterated.
let mut bytes_prior = 0;
for (line_idx, (line, seperator_offset)) in LineIterator::new(input).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize;
for (line_idx, (line, seperator_len)) in LineIterator::new(input).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_len.unwrap_or(0) as usize;
if bytes_so_far >= offset {
// found line.
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
let column = if line_offset > line.len() {
// error is inside line terminator.
line.chars().count() + 1
} else {
line[..line_offset].chars().count()
};
// +1 because line and column are 1 index.
return Self {
line: line_idx + 1,
@ -43,14 +50,21 @@ impl Location {
#[cfg(feature = "experimental-parser")]
pub fn of_offset(source: &str, offset: usize) -> Self {
// Bytes of input prior to line being iteratated.
assert!(offset <= source.len(), "tried to find location of substring in unrelated string");
// Bytes of input prior to line being iterated.
let mut bytes_prior = 0;
for (line_idx, (line, seperator_offset)) in LineIterator::new(source).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize;
for (line_idx, (line, seperator_len)) in LineIterator::new(source).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_len.unwrap_or(0) as usize;
if bytes_so_far >= offset {
// found line.
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
let column = if line_offset > line.len() {
// error is inside line terminator.
line.chars().count() + 1
} else {
line[..line_offset].chars().count()
};
// +1 because line and column are 1 index.
return Self {
line: line_idx + 1,
@ -94,7 +108,11 @@ impl Location {
if bytes_so_far >= offset {
// found line.
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
let column = if line_offset > line.len() {
line.chars().count() + 1
} else {
line[..line_offset.min(line.len())].chars().count()
};
// +1 because line and column are 1 index.
if bytes_so_far >= end {
// end is on the same line, finish immediatly.
@ -124,12 +142,17 @@ impl Location {
let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize;
if bytes_so_far >= end {
let line_offset = end - bytes_prior;
let column = line[..line_offset].chars().count();
let column = if line_offset > line.len() {
line.chars().count() + 1
} else {
line[..line_offset.min(line.len())].chars().count()
};
return start..Self {
line: line_idx + 1,
column: column + 1,
};
}
bytes_prior = bytes_so_far;
}
}
}

View file

@ -20,3 +20,17 @@ pub use v2::{
pub trait Parse<T> {
fn parse(val: &str) -> T;
}
#[cfg(test)]
mod test {
use super::parse;
#[test]
fn test_error_in_lineterminator() {
let q = r#"
select * from person
CREATE person CONTENT { foo:'bar'};
"#;
parse(q).unwrap_err();
}
}