tinyexpr: Check for wcstod errors

This would otherwise unwrap() an Err and crash.
This commit is contained in:
Fabian Boehm 2023-08-25 16:15:52 +02:00
parent b3ff982ad7
commit 06b89083d5
2 changed files with 32 additions and 3 deletions

View file

@ -35,7 +35,7 @@ use std::{
use crate::{ use crate::{
wchar::prelude::*, wchar::prelude::*,
wutil::{wcstod::wcstod_underscores, wgettext}, wutil::{wcstod::wcstod_underscores, wgettext, Error as wcstodError},
}; };
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -95,6 +95,7 @@ pub enum ErrorKind {
UnexpectedToken, UnexpectedToken,
LogicalOperator, LogicalOperator,
DivByZero, DivByZero,
NumberTooLarge,
Unknown, Unknown,
} }
@ -113,6 +114,7 @@ impl ErrorKind {
wgettext!("Logical operations are not supported, use `test` instead") wgettext!("Logical operations are not supported, use `test` instead")
} }
ErrorKind::DivByZero => wgettext!("Division by zero"), ErrorKind::DivByZero => wgettext!("Division by zero"),
ErrorKind::NumberTooLarge => wgettext!("Number is too large"),
ErrorKind::Unknown => wgettext!("Expression is bogus"), ErrorKind::Unknown => wgettext!("Expression is bogus"),
} }
} }
@ -396,8 +398,21 @@ impl<'s> State<'s> {
// Try reading a number. // Try reading a number.
if matches!(next.first(), Some('0'..='9') | Some('.')) { if matches!(next.first(), Some('0'..='9') | Some('.')) {
let mut consumed = 0; let mut consumed = 0;
let num = wcstod_underscores(*next, &mut consumed).unwrap(); match wcstod_underscores(*next, &mut consumed) {
Some((consumed, Some(Token::Number(num)))) Ok(num) => Some((consumed, Some(Token::Number(num)))),
Err(wcstodError::InvalidChar) => {
self.set_error(ErrorKind::Unknown, Some((self.pos + consumed, 1)));
return Some((consumed, Some(Token::Error)));
},
Err(wcstodError::Overflow) => {
self.set_error(ErrorKind::NumberTooLarge, Some((self.pos, consumed)));
return Some((consumed, Some(Token::Error)));
},
Err(wcstodError::Empty) => {
// We have a matches! above, this can't be?
unreachable!()
}
}
} else { } else {
// Look for a function call. // Look for a function call.
// But not when it's an "x" followed by whitespace // But not when it's an "x" followed by whitespace

View file

@ -358,3 +358,17 @@ echo 7 + 6 | math 2 + 2
# It isn't checked at all. # It isn't checked at all.
echo 7 + 8 | math not an expression echo 7 + 8 | math not an expression
# CHECK: 15 # CHECK: 15
math (string repeat -n 1000 1) 2>| string shorten -m50 --char=""
# CHECK: math: Error: Number is too large
# CHECK: '1111111111111111111111111111111111111111111111111
# CHECK: ^
math 0x0_2.0P-0x3
# CHECKERR: math: Error: Unknown function
# CHECKERR: '0x0_2.0P-0x3'
# CHECKERR: ^^
math 0x0_2.0P-f
# CHECKERR: math: Error: Unexpected token
# CHECKERR: '0x0_2.0P-f'
# CHECKERR: ^