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

wasm extractor - fix report parameters #1775

Merged
merged 4 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions framework/meta-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ hex = "0.4"
wasmparser = "0.216"
wasmprinter = "0.216"
semver = "1.0.20"
wat = "1.217.0"

[dependencies.multiversx-sc]
version = "=0.53.0"
Expand Down
2 changes: 1 addition & 1 deletion framework/meta-lib/src/code_report_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl CodeReportJson {
path: report.path.clone(),
size,
has_allocator: report.has_allocator,
has_panic: report.has_panic.clone(),
has_panic: report.has_panic.to_string(),
}
}
}
1 change: 1 addition & 0 deletions framework/meta-lib/src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod git_describe;
pub(crate) mod report_creator;
pub mod twiggy;
mod wasm_extractor;
mod wasm_extractor_test;
mod wasm_opt;
mod wasm_to_wat;

Expand Down
24 changes: 21 additions & 3 deletions framework/meta-lib/src/tools/report_creator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
pub const WITH_MESSAGE: &str = "with message";
pub const WITHOUT_MESSAGE: &str = "without message";
use std::fmt::Display;

#[derive(Default)]
pub enum PanicMessage {
#[default]
None,
WithoutMessage,
WithMessage,
}

impl Display for PanicMessage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let panic_status = match self {
PanicMessage::None => "None",
PanicMessage::WithoutMessage => "without message",
PanicMessage::WithMessage => "with message",
};
write!(f, "{}", panic_status)
}
}

pub struct ReportCreator {
pub path: String,
pub has_allocator: bool,
pub has_panic: String,
pub has_panic: PanicMessage,
}

impl ReportCreator {}
46 changes: 30 additions & 16 deletions framework/meta-lib/src/tools/wasm_extractor.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use colored::Colorize;
use std::fs;
use wasmparser::{
BinaryReaderError, DataSectionReader, FunctionBody, ImportSectionReader, Parser, Payload,
BinaryReaderError, DataSectionReader, FunctionBody, ImportSectionReader, Operator, Parser,
Payload,
};

use crate::ei::EIVersion;

use super::report_creator::{ReportCreator, WITHOUT_MESSAGE, WITH_MESSAGE};
use super::report_creator::{PanicMessage, ReportCreator};

const PANIC_WITH_MESSAGE: &[u8; 16] = b"panic occurred: ";
const PANIC_WITHOUT_MESSAGE: &[u8; 14] = b"panic occurred";
const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden";
const MEMORY_GROW_OPCODE: u8 = 0x40;

pub struct WasmInfo {
pub imports: Vec<String>,
Expand Down Expand Up @@ -39,7 +39,7 @@ impl WasmInfo {
}
}

fn populate_wasm_info(
pub(crate) fn populate_wasm_info(
path: String,
wasm_data: Vec<u8>,
extract_imports_enabled: bool,
Expand All @@ -49,25 +49,35 @@ fn populate_wasm_info(
let mut allocator_trigger = false;
let mut ei_check = false;
let mut memory_grow_flag = false;
let mut has_panic = "none";
let mut has_panic: PanicMessage = PanicMessage::default();

let parser = Parser::new(0);
for payload in parser.parse_all(&wasm_data) {
match payload? {
Payload::ImportSection(import_section) => {
imports = extract_imports(import_section, extract_imports_enabled);
ei_check = is_ei_valid(imports.clone(), check_ei);
ei_check |= is_ei_valid(imports.clone(), check_ei);
},
Payload::DataSection(data_section) => {
allocator_trigger = is_fail_allocator_triggered(data_section.clone());
if is_panic_with_message_triggered(data_section.clone()) {
has_panic = WITH_MESSAGE;
} else if is_panic_without_message_triggered(data_section) {
has_panic = WITHOUT_MESSAGE;
allocator_trigger |= is_fail_allocator_triggered(data_section.clone());
match has_panic {
Copy link
Contributor

Choose a reason for hiding this comment

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

This match belongs to a method in PanicMessage. Something like max_severity. We should also have a separate function that gives the PanicMessage for the current section.

We should also rename it to something like PanicReport or PanicStatus, since it is a flag, rather than just a message.

PanicMessage::None => {
if is_panic_with_message_triggered(data_section.clone()) {
has_panic = PanicMessage::WithMessage;
} else if is_panic_without_message_triggered(data_section) {
has_panic = PanicMessage::WithoutMessage;
}
},
PanicMessage::WithoutMessage => {
if is_panic_with_message_triggered(data_section.clone()) {
has_panic = PanicMessage::WithMessage;
}
},
PanicMessage::WithMessage => continue,
}
},
Payload::CodeSectionEntry(code_section) => {
memory_grow_flag = is_mem_grow(code_section);
memory_grow_flag |= is_mem_grow(code_section);
},
_ => (),
}
Expand All @@ -76,7 +86,7 @@ fn populate_wasm_info(
let report = ReportCreator {
path,
has_allocator: allocator_trigger,
has_panic: has_panic.to_string(),
has_panic,
};

Ok(WasmInfo {
Expand Down Expand Up @@ -173,11 +183,15 @@ fn is_ei_valid(imports: Vec<String>, check_ei: &Option<EIVersion>) -> bool {
}

fn is_mem_grow(code_section: FunctionBody) -> bool {
let mut code = code_section.get_binary_reader();
while code.bytes_remaining() > 0 {
if code.read_u8().unwrap() == MEMORY_GROW_OPCODE {
let mut instructions_reader = code_section
.get_operators_reader()
.expect("Failed to get operators reader");

while let Ok(op) = instructions_reader.read() {
if let Operator::MemoryGrow { mem: _ } = op {
return true;
}
}

false
}
Loading
Loading