Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fuzzing test to flowgger #79

Merged
merged 8 commits into from May 17, 2024
Merged

Add fuzzing test to flowgger #79

merged 8 commits into from May 17, 2024

Conversation

cahakgeorge
Copy link
Contributor

Description of changes:
This change seeks to add fuzzing tests to Flowgger. With arbitrary strings as inputs, Flowgger is expected to either throw an error or successfully parse the log entry.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
@@ -7,7 +7,7 @@ mod tcp;
#[cfg(feature = "tls")]
mod tls;
#[cfg(feature = "syslog")]
mod udp_input;
pub mod udp_input;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make those public only in test mode ? and keep them private otherwise ? Applicable to all scope changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack!

flowgger.toml Outdated
###################
# Fuzzing Test #
###################
fuzzed_message_count = 500
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this in the prod config ? this should be in the test file as constant or in a dedicated file. not in the config file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do. Thanks

tests/fuzzer.rs Outdated

const DEFAULT_FUZZED_MESSAGE_COUNT: u64 = 500;

fn get_file_output(config: &Config) -> Box<dyn Output> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is not a single comment in the file. please explain what you're doing, why, what are the success criteria, when is this run....

tests/fuzzer.rs Outdated
};

if let Some(entry) = config.config.get_mut("output").unwrap().get_mut("file_rotation_time"){
*entry = Value::Integer(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you checking for the file rotation time ? it's an optional config entry anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets the file_rotation_time to 0, so that multiple output files are not created during the test. Will add comments related to this.

tests/fuzzer.rs Outdated
let file_output_path = config.lookup("output.file_path").map_or(DEFAULT_OUTPUT_FILEPATH, |x| {
x.as_str().expect("File output path missing in config")
});
remove_output_file(&file_output_path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the output file doesn't exist, will you panic ? shouldn't you expect the output to not be found ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This refers to the output filename defined in the config file, not the actual file on the physical filesystem.
If it's missing, this defaults to the constant value defined, else panics

tests/fuzzer.rs Outdated
#[test]
fn test_fuzzer(){
let config = get_config();
let fuzzed_message_count = match config.lookup("test.fuzzed_message_count"){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test config shouldnt' be in the prod config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in the next rev

tests/fuzzer.rs Outdated
});
remove_output_file(&file_output_path);

if let Ok(s) = std::str::from_utf8(data) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s as a variable is not a readable name, please update

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

tests/fuzzer.rs Outdated
fs::remove_file(file_output_path);
}

pub fn fuzz_target_rfc3164(data: &[u8]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, am i getting this right ?are you creating a listener for each message, send the message, check the output file, delete it, close the listeners, and do that again ? 500 times ???

why not just create the listeners, fuzz data with handle_record_maybe_compressed and open the output file just once, parse the records, and error out if one can't be read ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in next rev

cahakgeorge and others added 2 commits May 15, 2024 09:48
Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
@cahakgeorge cahakgeorge requested a review from vche May 15, 2024 09:52
@@ -0,0 +1,210 @@
extern crate quickcheck;

use crate::flowgger;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is in source file, and only used for test, make it clear. e.g. like in test_utils: prefix the file with test_ to make it clear it is not a source file. and don't make any import outside the test clause to make sure nothing is imported


use crate::flowgger;

use quickcheck::QuickCheck;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all those modules will be imported in prod compilation as well, even thoguh no code. and modules like quickcheck should are only available as dev dependency, so it would fail.

Comment on lines 170 to 173
let encoder = get_encoder_rfc3164(&config);
let decoder = get_decoder_rfc3164(&config);
let (decoder, encoder): (Box<dyn Decoder>, Box<dyn Encoder>) =
(decoder.clone_boxed(), encoder.clone_boxed());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we talked that basically only the handle_record needs to be called fore very message. cloning the static config and recreating the same encoder and decoder for every message is useless.

I expect tx, decoder, and encoder to be shared. E.g. have a structure containing the 3 of them which you chsare with your mutex ?

let tx: SyncSender<Vec<u8>> = sender_guard.take().unwrap();
drop(tx);

thread::sleep(time::Duration::from_millis(1000));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain why you need to sleep please. if the drop is not blocking and you're waiting, how do you know 1 sec is enough ?

Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
@cahakgeorge cahakgeorge requested a review from vche May 16, 2024 15:14
cahakgeorge and others added 3 commits May 16, 2024 18:57
Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
pub fn fuzz_target_rfc3164(data: String) {
unsafe{
// Extract the required fields from the global context structure, which is wrapped around by a Mutex
let mut guard = match GLOBAL_CONTEXT.lock() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set_context(), we could hsve had a get_context() 😬. I'm being picky

@vche
Copy link
Contributor

vche commented May 16, 2024

Nice improvements since the first commit !

Co-authored-by: Chukwuemeka Ewurum <cewurum@amazon.com>
@cahakgeorge cahakgeorge requested a review from vche May 16, 2024 21:04
Copy link
Contributor

@rejao rejao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@vche
Copy link
Contributor

vche commented May 17, 2024

Build fails due to workflow and cross compilation being broken. I've enabled manual runs for the workflow and re ran it on the current release (which previously passed) https://github.com/awslabs/flowgger/actions/runs/9127101215.

And it fails the same way. Since we're using a cross build and openssl is not included anymore, we were using an older version. we'll have to fix this. I've opened an issue for us to fix the workflow - again -.

In the meantime, having tested this locally, and no production code being modified, it is safe to merge.

@vche vche merged commit 72f86cf into awslabs:master May 17, 2024
1 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants