Skip to content

Commit

Permalink
feat(safety): Add safety checks and fix bug in spell
Browse files Browse the repository at this point in the history
Signed-off-by: dark0dave <dark0dave@mykolab.com>
  • Loading branch information
dark0dave committed Nov 2, 2023
1 parent 928ed88 commit e8e2ecd
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 11 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/safety.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
permissions:
contents: read
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: safety
jobs:
sanitizers:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install nightly
uses: dtolnay/rust-toolchain@nightly
- run: |
# to get the symbolizer for debug symbol resolution
sudo apt install llvm
# to fix buggy leak analyzer:
# https://github.com/japaric/rust-san#unrealiable-leaksanitizer
# ensure there's a profile.dev section
if ! grep -qE '^[ \t]*[profile.dev]' Cargo.toml; then
echo >> Cargo.toml
echo '[profile.dev]' >> Cargo.toml
fi
# remove pre-existing opt-levels in profile.dev
sed -i '/^\s*\[profile.dev\]/,/^\s*\[/ {/^\s*opt-level/d}' Cargo.toml
# now set opt-level to 1
sed -i '/^\s*\[profile.dev\]/a opt-level = 1' Cargo.toml
cat Cargo.toml
name: Enable debug symbols
- name: cargo test -Zsanitizer=address
# only --lib --tests b/c of https://github.com/rust-lang/rust/issues/53945
run: cargo test --lib --tests --all-features --target x86_64-unknown-linux-gnu
env:
ASAN_OPTIONS: "detect_odr_violation=0:detect_leaks=0"
RUSTFLAGS: "-Z sanitizer=address"
- name: cargo test -Zsanitizer=leak
if: always()
run: cargo test --all-features --target x86_64-unknown-linux-gnu
env:
RUSTFLAGS: "-Z sanitizer=leak"
miri:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- run: |
echo "NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)" >> $GITHUB_ENV
- name: Install ${{ env.NIGHTLY }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.NIGHTLY }}
components: miri
- name: cargo miri test
run: cargo miri test
env:
MIRIFLAGS: ""
2 changes: 1 addition & 1 deletion models/src/common/feature_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::Serialize;
use super::fixed_char_array::FixedCharSlice;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, Serialize)]
#[derive(Debug, Copy, Clone, Serialize, PartialEq, Eq)]
pub struct FeatureBlock {
pub opcode_number: u16,
pub target_type: u8,
Expand Down
2 changes: 1 addition & 1 deletion models/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Model for Ids {
fn new(buffer: &[u8]) -> Self {
let (headers, mut end) = row_parser(buffer, 0);

let signature = if let Some(_) = headers.first() {
let signature = if headers.first().is_some() {
FixedCharSlice::<3>::from(&buffer[0..3])
} else {
FixedCharSlice::<3>::default()
Expand Down
44 changes: 36 additions & 8 deletions models/src/spell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::tlk::Lookup;
pub struct Spell {
pub header: SpellHeader,
pub extended_headers: Vec<SpellExtendedHeader>,
pub equiping_feature_blocks: Vec<SpellFeatureBlock>,
pub equipping_feature_blocks: Vec<SpellFeatureBlock>,
}

impl Model for Spell {
Expand All @@ -26,15 +26,14 @@ impl Model for Spell {
let count = usize::try_from(header.count_of_extended_headers).unwrap_or(0);
let extended_headers = copy_transmute_buff::<SpellExtendedHeader>(buffer, start, count);

let start = usize::try_from(header.offset_to_casting_feature_blocks).unwrap_or(0);
let count = usize::try_from(header.count_of_casting_feature_blocks).unwrap_or(0);
let equiping_feature_blocks =
let start = usize::try_from(header.offset_to_feature_block_table).unwrap_or(0);
let count = usize::try_from(extended_headers[0].count_of_feature_blocks).unwrap_or(0);
let equipping_feature_blocks =
copy_transmute_buff::<SpellFeatureBlock>(buffer, start, count);

Self {
header,
extended_headers,
equiping_feature_blocks,
extended_headers,equipping_feature_blocks,
}
}
fn create_as_rc(buffer: &[u8]) -> Rc<dyn Model> {
Expand Down Expand Up @@ -78,7 +77,7 @@ pub struct SpellHeader {
primary_spell_school: u8,
min_strength: u8,
secondary_spell_school: u8,
min_strenth_bonus: u8,
min_strength_bonus: u8,
kit_usability_1: u8,
min_intelligence: u8,
kit_usability_2: u8,
Expand Down Expand Up @@ -126,6 +125,7 @@ pub struct SpellExtendedHeader {
count_of_feature_blocks: i16,
offset_to_feature_blocks: i16,
charges: u16,
charge_depletion_behaviour: u16,
projectile: u16,
}

Expand All @@ -143,6 +143,13 @@ mod tests {
io::{BufReader, Read},
};

#[test]
fn valid_sizes() {
assert_eq!(std::mem::size_of::<SpellHeader>(), 114);
assert_eq!(std::mem::size_of::<SpellExtendedHeader>(), 40);
assert_eq!(std::mem::size_of::<SpellFeatureBlock>(), 48);
}

#[test]
fn valid_creature_file_item_table_parsed() {
let file = File::open("fixtures/gate1.spl").unwrap();
Expand Down Expand Up @@ -171,7 +178,7 @@ mod tests {
primary_spell_school: 2,
min_strength: 0,
secondary_spell_school: 6,
min_strenth_bonus: 0,
min_strength_bonus: 0,
kit_usability_1: 0,
min_intelligence: 0,
kit_usability_2: 0,
Expand All @@ -197,6 +204,27 @@ mod tests {
offset_to_casting_feature_blocks: 0,
count_of_casting_feature_blocks: 0
}
);
assert_eq!(
spell.equipping_feature_blocks,
vec![FeatureBlock {
opcode_number: 177,
target_type: 1,
power: 9,
parameter_1: 0,
parameter_2: 2,
timing_mode: 0,
dispel_resistance: 2,
duration: 100000,
propability_1: 39,
propability_2: 0,
resource: "balorsu".into(),
dice_thrown_max_level: 0,
dice_sides_min_level: 0,
saving_throw_type: "".into(),
saving_throw_bonus: 0,
stacking_id: 0
}]
)
}
}
2 changes: 1 addition & 1 deletion models/src/twoda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl Model for TwoDA {
end = row_end;
}

let signature = if let Some(_) = headers.first() {
let signature = if headers.first().is_some() {
FixedCharSlice::<3>::from(&buffer[0..3])
} else {
FixedCharSlice::<3>::default()
Expand Down

0 comments on commit e8e2ecd

Please sign in to comment.