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

Missing Alignment Check During AbstractIns #6812

Open
IGI-111 opened this issue Jan 6, 2025 · 0 comments
Open

Missing Alignment Check During AbstractIns #6812

IGI-111 opened this issue Jan 6, 2025 · 0 comments
Assignees
Labels
bug Something isn't working compiler: codegen Everything to do with IR->ASM, register allocation, etc. P: high Should be looked at if there are no critical issues left

Comments

@IGI-111
Copy link
Contributor

IGI-111 commented Jan 6, 2025

From https://reports.immunefi.com/fuel-network-or-attackathon/attackathon-_-fuel-network-32439-smart-contract-low-missing-alignment-check-during-abstractinstructi

const_indexing_aggregates_function process VirtualOp::SW without checking the offset in addr_reg is aligned to 8, cause the wrong constant being calculated and leads to incorrect program behavior.

Vulnerability Details

const_indexing_aggregates_function is an optimization pass of AbstractInstructionSet, it is used to propagate constants in the function. During the handling of VirtualOp::SW instruction, the function does not properly validate the offset of BaseOffset. Since the imm argument of VirtualOp::SW representing an offset equals to imm * 8, the conversion (divide by 8) here will truncate offset which isn't aligned to 8 bytes, causing SW instruction to write to incorrect address.

VirtualOp::SW(addr_reg, src, imm) => match reg_contents.get(addr_reg) {
    Some(RegContents::BaseOffset(base_reg, offset))
        if get_def_version(&latest_version, &base_reg.reg) == base_reg.ver
            && ((offset / 8) + imm.value as u64)
                < compiler_constants::TWELVE_BITS =>
    {
        let new_imm = VirtualImmediate12::new_unchecked(
            (offset / 8) + imm.value as u64,
            "Immediate offset too big for SW",
        );
        let new_sw = VirtualOp::SW(base_reg.reg.clone(), src.clone(), new_imm);
        // Replace the SW with a new one in-place.
        *op = new_sw;
    }
    _ => (),
},

Impact Details

As usual, it is hard to come up with a precise impact estimation of incorrect code generation because it depends on what code the user writes. The best case scenario would be contracts that run into those bugs getting bricked, and the worst case scenario would be that incorrect program behaviors lead to loss of funds.

References

(offset / 8) + imm.value as u64,

Proof of Concept

This test would fail because buf[16] is not overwritten by sw b a i1.

#[test]
fn sw_missing_alignment_check() -> u64 {
    let a = asm(a, b) {
        movi a i24;     // a = 24
        aloc a;         // hp = buf[0;24]

        movi a i1;      // a = 1
        sb hp a i16;    // buf[16] = a = 1

        movi a i0;      // a = 0
        addi b hp i1;   // b = &buf[1]
        sw b a i1;      // expected : buf[9:17] = a = 0     real : buf[8:16] = a = 0

        lb a hp i16;    // a = &buf[16]
        a: u64
    };

    assert(a == 0);
    a
}
@IGI-111 IGI-111 added bug Something isn't working compiler: codegen Everything to do with IR->ASM, register allocation, etc. P: high Should be looked at if there are no critical issues left labels Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working compiler: codegen Everything to do with IR->ASM, register allocation, etc. P: high Should be looked at if there are no critical issues left
Projects
None yet
Development

No branches or pull requests

2 participants