Skip to content

Commit

Permalink
polkavm-linker: Fix multiple issues reported by the fuzzer
Browse files Browse the repository at this point in the history
The fuzzer reported several valid bugs, this patch takes care of them.

Following categories of bugs were reported:

1. RegKind with a zero register.

[
    Reg {
        kind: ReverseByte,
        dst: A2,
        src: Zero,
    },
]

2. apply() does not implement Rem32AndSignExtend and RemUnsigned32AndSignExtend.

[
    RegReg {
        kind: RemUnsigned32AndSignExtend,
        dst: A2,
        src1: T0,
        src2: Zero,
    },
]

3. apply() does not implement Div32AndSignExtend and DivUnsigned32AndSignExtend/

[
    RegReg {
        kind: DivUnsigned32AndSignExtend,
        dst: T1,
        src1: T2,
        src2: Zero,
    },
]

4. apply() does not implement Rem*/Div* Zero src1 register case.

[
    RegReg {
        kind: Rem64,
        dst: S0,
        src1: Zero,
        src2: A3,
    },
]

Signed-off-by: Aman <[email protected]>
  • Loading branch information
aman4150 committed Jan 28, 2025
1 parent 9337e13 commit bffab49
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 27 deletions.
54 changes: 43 additions & 11 deletions crates/polkavm-linker/src/program_from_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2082,12 +2082,26 @@ where
return Ok(());
};

use crate::riscv::RegKind as K;

if src == RReg::Zero {
let imm = match kind {
K::CountLeadingZeroBits32 | K::CountTrailingZeroBits32 => 32,
K::CountLeadingZeroBits64 | K::CountTrailingZeroBits64 => 64,
K::CountSetBits32 | K::CountSetBits64 => 0,
K::ReverseByte => 0,
K::OrCombineByte => 0,
K::SignExtend8 | K::SignExtend16 | K::ZeroExtend16 => 0,
};

emit(InstExt::Basic(BasicInst::LoadImmediate { dst, imm }));
return Ok(());
}

let Some(src) = cast_reg_non_zero(src)? else {
return Err(ProgramFromElfError::other("found an invalid instruction"));
};

use crate::riscv::RegKind as K;

let kind = match kind {
K::CountLeadingZeroBits32 => RegKind::CountLeadingZeroBits32,
K::CountLeadingZeroBits64 => RegKind::CountLeadingZeroBits64,
Expand Down Expand Up @@ -4315,11 +4329,19 @@ impl OperationKind {
(O::ShiftArithmeticRight32, lhs, C(0)) => lhs,
(O::ShiftArithmeticRight64, lhs, C(0)) => lhs,
// x % 0 = x
(O::Rem32, lhs, C(0)) => lhs,
(O::Rem64, lhs, C(0)) => lhs,
// x % 0 = x
(O::RemUnsigned32, lhs, C(0)) => lhs,
(O::RemUnsigned64, lhs, C(0)) => lhs,
(O::Rem32, lhs, C(0)) => lhs,
(O::Rem64, lhs, C(0)) => lhs,
(O::RemUnsigned32, lhs, C(0)) => lhs,
(O::RemUnsigned64, lhs, C(0)) => lhs,
(O::Rem32AndSignExtend, lhs, C(0)) => lhs,
(O::RemUnsigned32AndSignExtend, lhs, C(0)) => lhs,
// 0 % x = 0
(O::Rem32, C(0), _) => C(0),
(O::Rem64, C(0), _) => C(0),
(O::RemUnsigned32, C(0), _) => C(0),
(O::RemUnsigned64, C(0), _) => C(0),
(O::Rem32AndSignExtend, C(0), _) => C(0),
(O::RemUnsigned32AndSignExtend, C(0), _) => C(0),

// x & 0 = 0
(O::And32, _, C(0)) => C(0),
Expand Down Expand Up @@ -4347,10 +4369,20 @@ impl OperationKind {
(O::MulUpperUnsignedUnsigned64, C(0), _) => C(0),

// x / 0 = -1
(O::Div32, _, C(0)) => C(-1),
(O::Div64, _, C(0)) => C(-1),
(O::DivUnsigned32, _, C(0)) => C(-1),
(O::DivUnsigned64, _, C(0)) => C(-1),
(O::Div32, _, C(0)) => C(-1),
(O::Div64, _, C(0)) => C(-1),
(O::DivUnsigned32, _, C(0)) => C(-1),
(O::DivUnsigned64, _, C(0)) => C(-1),
(O::Div32AndSignExtend, _, C(0)) => C(-1),
(O::DivUnsigned32AndSignExtend, _, C(0)) => C(-1),

// 0 / x = 0
(O::Div32, C(0), _) => C(0),
(O::Div64, C(0), _) => C(0),
(O::DivUnsigned32, C(0), _) => C(0),
(O::DivUnsigned64, C(0), _) => C(0),
(O::Div32AndSignExtend, C(0), _) => C(0),
(O::DivUnsigned32AndSignExtend, C(0), _) => C(0),

// (x & ~0) = x
(O::AndInverted, lhs, C(0)) => lhs,
Expand Down
2 changes: 1 addition & 1 deletion fuzz/Cargo.lock

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

31 changes: 16 additions & 15 deletions fuzz/fuzz_targets/fuzz_linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@ use libfuzzer_sys::fuzz_target;
#[derive(Arbitrary, Debug)]
pub enum Reg {
Zero = 0,
RA,
SP,
GP,
TP,
T0,
T1,
T2,
S0,
S1,
A0,
A1,
A2,
A3,
A4,
A5,
RA = 1,
SP = 2,
// These registers are not supported
// GP = 3,
// TP = 4,
T0 = 5,
T1 = 6,
T2 = 7,
S0 = 8,
S1 = 9,
A0 = 10,
A1 = 11,
A2 = 12,
A3 = 13,
A4 = 14,
A5 = 15,
}

#[derive(Arbitrary, Debug)]
Expand Down

0 comments on commit bffab49

Please sign in to comment.