Bugfix: fix a panic in span rendering (#3527)
This commit is contained in:
parent
6469b653cd
commit
bbd5268e71
3 changed files with 55 additions and 14 deletions
|
@ -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>());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue