Skip to content

Commit

Permalink
Fix bugs found by fuzzing (#23)
Browse files Browse the repository at this point in the history
Co-authored-by: David Sid Olofsson <[email protected]>
  • Loading branch information
sidju and David Sid Olofsson authored Oct 25, 2023
1 parent 24eeb86 commit db23210
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 18 deletions.
15 changes: 9 additions & 6 deletions fuzz/fuzz.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use std::collections::VecDeque;
use std::collections::HashMap;

extern crate add_ed;
use add_ed::io::fake_io::FakeIO;

fuzz_target!(|data: VecDeque<String>| {
// You can do anything in 4 input lines, so that should be enough
// (and it should help with the out-of-memory problems while fuzzing)
fuzz_target!(|data: [String; 4]| {
let mut ui = add_ed::ui::ScriptedUI {
input: data,
input: data.into(),
print_ui: None,
};
let mut io = FakeIO{fake_fs: HashMap::new(), fake_shell: HashMap::new()};
let mut buffer = add_ed::buffer::Buffer::new();
let mut ed = add_ed::Ed::new(&mut buffer, &mut io, "".to_string());
let _ = ed.run_macro(&mut ui);
let macro_store = HashMap::new();
let mut ed = add_ed::Ed::new(&mut io, &macro_store);
loop {
if let Ok(true) = ed.get_and_run_command(&mut ui) { break; }
}
});
24 changes: 15 additions & 9 deletions src/cmd/parsing/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,11 @@ pub fn parse_index(
// then an offset. Not caught earlier so we can give a more
// detailed error. Same error logic as post loop State::Default
if let Some(_) = current_ind {return Err(
// Note that this reports getting digits after another index.
// We catch it here to get all the digits before erroring.
EdError::IndicesUnrelated{
prior_index: input[start..i].to_owned(),
// Find the end of the current index
unrelated_index: input[i..]
.find(|c: char| !c.is_ascii_digit())
.map(|end| &input[i..end] )
.unwrap_or(&input[i..])
.to_owned(),
prior_index: input[..start].to_owned(),
unrelated_index: input[start..i].to_owned(),
}
)}
// If there is numeric input before, handle that
Expand Down Expand Up @@ -121,8 +118,17 @@ pub fn parse_index(
State::Tag => {
if let Some(_) = current_ind { return Err(
EdError::IndicesUnrelated{
// Safe, as the -1 is to exclude the ' (which is 1 byte long)
prior_index: input[..i-1].to_owned(),
unrelated_index: input[i-1..i+1].to_owned(),
// As the start -1 includes the ' the start is safe, but we can't
// assume the given tag is 1 byte long.
unrelated_index: {
let mut index = String::new();
for ch in input[i-1..].chars().take(2) {
index.push(ch);
}
index
},
}
)}
current_ind = Some(Ind::Tag(ch));
Expand Down Expand Up @@ -304,7 +310,7 @@ pub fn interpret_index(
// These are relative to the prior, so have no indexing per-se
Ind::Add(inner, offset) => {
let inner = interpret_index(state, *inner, old_selection)?;
Ok(inner+offset)
Ok(inner.saturating_add(offset))
},
Ind::Sub(inner, offset) => {
let inner = interpret_index(state, *inner, old_selection)?;
Expand Down
2 changes: 1 addition & 1 deletion src/error/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl std::fmt::Display for EdError {
text,
),
IndicesUnrelated{prior_index, unrelated_index} => write!(f,
"Received index `{}` immediately after index `{}`.",
"Received non-chainable index `{}` immediately after index `{}`.",
unrelated_index,
prior_index,
),
Expand Down
29 changes: 29 additions & 0 deletions tests/old_fuss_fails.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod shared;
use shared::fixtures::{
ErrorTest,
};
use add_ed::EdError;

#[test]
fn unrelated_indice_with_unicode_tag() {
ErrorTest{
init_buffer: vec![],
command_input: vec!["'''🏷 G"],
expected_error: EdError::IndicesUnrelated{
prior_index: "''".to_owned(),
unrelated_index: "'🏷".to_owned(),
},
}.run()
}

#[test]
fn index_overflow() {
ErrorTest{
init_buffer: vec![],
command_input: vec!["9999999999999999999+9999999999999999999"],
expected_error: EdError::IndexTooBig{
index: 18_446_744_073_709_551_615,
buffer_len: 0,
},
}.run()
}
7 changes: 5 additions & 2 deletions tests/shared/inner_fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::collections::HashMap;

use super::{
dummy_io::DummyIO,
fake_io::FakeIO,
mock_ui::{Print, MockUI},
};
use add_ed::{
Expand Down Expand Up @@ -33,7 +33,10 @@ pub fn inner_fixture(
expected_prints: Vec<Print>,
) {
// Instantiate dummy IO
let mut io = DummyIO::new();
let mut io = FakeIO{
fake_fs: HashMap::new(),
fake_shell: HashMap::new(),
};
// Apply given or default to no macros
let macros = init_macros.unwrap_or(HashMap::new());
// Create ed state and init ed.buffer
Expand Down

0 comments on commit db23210

Please sign in to comment.