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

misaligned pointer dereference error in PacketListIterator::next #49

Closed
arteme opened this issue Jan 16, 2024 · 16 comments · Fixed by #52
Closed

misaligned pointer dereference error in PacketListIterator::next #49

arteme opened this issue Jan 16, 2024 · 16 comments · Fixed by #52

Comments

@arteme
Copy link

arteme commented Jan 16, 2024

Hi,

In pod-ui I'm using coremidi through midir. I have a badly-behaving M-Vave MS-1 bluetooth MIDI device that keeps crashing the app. I know, midir 0.9.x uses an old version of coremidi, I've tried Boddlnagg/midir#139 and Boddlnagg/midir#142, but the error still prevails.

I understand that MS-1 is the culprit here, but is there some sanity-checking in PacketListIterator that can be done to prevent crashing?

Here are the backtraces:
coremidi-panic-midir0.9.1.txt
coremidi-panic-midir0.9.2+coremidi0.7.0.txt
coremidi-panic-midir0.9.2+coremidi0.8.0.txt

@jmbarbier
Copy link

Same bug here, fixed it by adding read_unaligned for those lines

#[inline]
pub unsafe fn MIDIPacketNext(pkt: *const MIDIPacket) -> *const MIDIPacket {
    // Get pointer to potentially unaligned data without triggering undefined behavior
    // addr_of does not require creating an intermediate reference to unaligned data.
    let ptrx = ptr::addr_of!((*pkt).data) as *const u8;
    let rawl = ptr::addr_of!((*pkt).length) as *const u16;
    let offset = rawl.read_unaligned() as isize;
    if cfg!(any(target_arch = "arm", target_arch = "aarch64")) {
        // MIDIPacket must be 4-byte aligned on ARM
        ((ptrx.offset(offset + 3) as usize) & !(3usize)) as *const MIDIPacket
    } else {
        ptrx.offset(offset) as *const MIDIPacket
    }
}

#[inline]
pub unsafe fn MIDIEventPacketNext(pkt: *const MIDIEventPacket) -> *const MIDIEventPacket {
    // Get pointer to potentially unaligned data without triggering undefined behavi
    // or
    // addr_of does not require creating an intermediate reference to unaligned data.
    let ptrx = ptr::addr_of!((*pkt).words) as *const u8;
    let rawwc = ptr::addr_of!((*pkt).wordCount) as *const u32;
    let wc = rawwc.read_unaligned() as usize;
    let offset = (wc * mem::size_of::<u32>()) as isize;
    if cfg!(any(target_arch = "arm", target_arch = "aarch64")) {
        // MIDIEventPacket must be 4-byte aligned on ARM
        ((ptrx.offset(offset + 3) as usize) & !(3usize)) as *const MIDIEventPacket
    } else {
        ptrx.offset(offset) as *const MIDIEventPacket
    }
}

Take this as a hack without any warranty ("it works for me"), i have no knowledge of the internals used here...

@Boddlnagg
Copy link
Contributor

Boddlnagg commented May 9, 2024

This has repeatedly hit users of midir. I think the proposed fix by @jmbarbier is correct, but that code is actually part of https://github.com/jonas-k/coremidi-sys.
@jmbarbier Maybe you can open a PR against coremidi-sys?

@Boddlnagg
Copy link
Contributor

Actually I'm not sure whether that fix is correct. MIDIPacket should be 4-byte aligned on ARM (see also #9), so read_unaligned shouldn't be necessary. The error must be somewhere else where MIDIPackets are constructed that are not aligned.

@Boddlnagg
Copy link
Contributor

Boddlnagg commented May 9, 2024

Okay, I think the problem is this: "The alignment requirements of MIDIPacket may differ between CPU architectures. On Intel and PowerPC, MIDIPacket is unaligned. On ARM, MIDIPacket must be 4-byte aligned."
(https://github.com/phracker/MacOSX-SDKs/blob/041600eda65c6a668f66cb7d56b7d1da3e8bcc93/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Versions/A/Headers/MIDIServices.h#L420-L423)

So I'm assuming that this issue occurs on Intel processors? That would make sense because then Rust sees an unaligned MIDIPacket that should be 4-byte aligned but isn't, so the read_unaligned is needed to not trigger Rust's UB check. On ARM this would not be needed and would actually make performance worse, because on ARM the packets are aligned and explicit unaligned reads would generate worse machine code.

Furthermore, this can only affect MIDIPacket, not MIDIEvent (its length will always be a multiple of 4 bytes), so the fix does not need to be applied to MIDIEventPacketNext.

@Boddlnagg
Copy link
Contributor

@jmbarbier @arteme @oilcake Can you confirm that you're seeing this on Intel processors?

@oilcake
Copy link

oilcake commented May 9, 2024

@jmbarbier @arteme @oilcake Can you confirm that you're seeing this on Intel processors?

Yep, my one is intel.

@Boddlnagg
Copy link
Contributor

This should be fixed with the latest version of coremidi-sys

@oilcake
Copy link

oilcake commented Jun 11, 2024

This should be fixed with the latest version of coremidi-sys

Just checked - still panicking on my side with the same error :(
Project was recompiled with coremidi-sys==0.8.0 which I believe is the latest.

@arteme
Copy link
Author

arteme commented Jun 11, 2024

I think, @Boddlnagg means coremidi-sys version 3.1.1 released a couple hours ago.

Unfortunately I no longer have my MS-1 device to check with, so I can be of little help.

@Boddlnagg
Copy link
Contributor

I think, @Boddlnagg means coremidi-sys version 3.1.1 released a couple hours ago.

Yes, that's right

@oilcake
Copy link

oilcake commented Jun 20, 2024

I think, @Boddlnagg means coremidi-sys version 3.1.1 released a couple hours ago.

Yes, that's right

Sorry, did not get it.

@Boddlnagg
Copy link
Contributor

@oilcake So does that mean that it works now?

@oilcake
Copy link

oilcake commented Jun 27, 2024

@oilcake So does that mean that it works now?

Sorry, I just did not still figure out how to check - when I do cargo tree cargo tells me that my project depends on midir v0.10.0, which is as I can see is the latest, and it depends on coremidi v3.1.0. Should I try to fork midir and set 3.1.1 in midir's Cargo.toml?

@Boddlnagg
Copy link
Contributor

Boddlnagg commented Jun 27, 2024

Since neither midir nor coremidi lock to a specific version, cargo update should be able to update to the latest (compatible) version.
And indeed when I do cargo update I see:

Updating coremidi-sys v3.1.0 -> v3.1.1

If that doesn't work, you can try

cargo update --precise 3.1.1 coremidi-sys

@oilcake
Copy link

oilcake commented Jun 27, 2024

Since neither midir nor coremidi lock to a specific version, cargo update should be able to update to the latest (compatible) version.

Thank you so much! I am new to rust and did not know cargo can do such a thing.
It works after cargo update! 👍

@Boddlnagg
Copy link
Contributor

@chris-zen Maybe you can increase the version requirement of coremidi-sys for the next release, so everybody gets the fix then.

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 a pull request may close this issue.

4 participants