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] #[test]
fn check_size() { fn check_size() {
assert!(64 <= std::mem::size_of::<Value>()); assert!(
assert_eq!(104, std::mem::size_of::<Error>()); 64 >= std::mem::size_of::<Value>(),
assert_eq!(104, std::mem::size_of::<Result<Value, Error>>()); "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::number::Number>());
assert_eq!(24, std::mem::size_of::<crate::sql::strand::Strand>()); assert_eq!(24, std::mem::size_of::<crate::sql::strand::Strand>());
assert_eq!(16, std::mem::size_of::<crate::sql::duration::Duration>()); assert_eq!(16, std::mem::size_of::<crate::sql::duration::Duration>());
assert_eq!(12, std::mem::size_of::<crate::sql::datetime::Datetime>()); 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::array::Array>());
assert_eq!(24, std::mem::size_of::<crate::sql::object::Object>()); 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::param::Param>());
assert_eq!(24, std::mem::size_of::<crate::sql::idiom::Idiom>()); assert_eq!(24, std::mem::size_of::<crate::sql::idiom::Idiom>());
assert_eq!(24, std::mem::size_of::<crate::sql::table::Table>()); 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) let offset = (substr.as_ptr() as usize)
.checked_sub(input.as_ptr() as usize) .checked_sub(input.as_ptr() as usize)
.expect("tried to find location of substring in unrelated string"); .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; let mut bytes_prior = 0;
for (line_idx, (line, seperator_offset)) in LineIterator::new(input).enumerate() { for (line_idx, (line, seperator_len)) in LineIterator::new(input).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize; let bytes_so_far = bytes_prior + line.len() + seperator_len.unwrap_or(0) as usize;
if bytes_so_far >= offset { if bytes_so_far >= offset {
// found line. // found line.
let line_offset = offset - bytes_prior; 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. // +1 because line and column are 1 index.
return Self { return Self {
line: line_idx + 1, line: line_idx + 1,
@ -43,14 +50,21 @@ impl Location {
#[cfg(feature = "experimental-parser")] #[cfg(feature = "experimental-parser")]
pub fn of_offset(source: &str, offset: usize) -> Self { 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; let mut bytes_prior = 0;
for (line_idx, (line, seperator_offset)) in LineIterator::new(source).enumerate() { for (line_idx, (line, seperator_len)) in LineIterator::new(source).enumerate() {
let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize; let bytes_so_far = bytes_prior + line.len() + seperator_len.unwrap_or(0) as usize;
if bytes_so_far >= offset { if bytes_so_far >= offset {
// found line. // found line.
let line_offset = offset - bytes_prior; 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. // +1 because line and column are 1 index.
return Self { return Self {
line: line_idx + 1, line: line_idx + 1,
@ -94,7 +108,11 @@ impl Location {
if bytes_so_far >= offset { if bytes_so_far >= offset {
// found line. // found line.
let line_offset = offset - bytes_prior; 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. // +1 because line and column are 1 index.
if bytes_so_far >= end { if bytes_so_far >= end {
// end is on the same line, finish immediatly. // 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; let bytes_so_far = bytes_prior + line.len() + seperator_offset.unwrap_or(0) as usize;
if bytes_so_far >= end { if bytes_so_far >= end {
let line_offset = end - bytes_prior; 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 { return start..Self {
line: line_idx + 1, line: line_idx + 1,
column: column + 1, column: column + 1,
}; };
} }
bytes_prior = bytes_so_far;
} }
} }
} }

View file

@ -20,3 +20,17 @@ pub use v2::{
pub trait Parse<T> { pub trait Parse<T> {
fn parse(val: &str) -> 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();
}
}