coremidi
coremidi copied to clipboard
`misaligned pointer dereference` error in `PacketListIterator::next`
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 https://github.com/Boddlnagg/midir/pull/139 and https://github.com/Boddlnagg/midir/pull/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
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...
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?
Actually I'm not sure whether that fix is correct. MIDIPacket should be 4-byte aligned on ARM (see also https://github.com/chris-zen/coremidi/pull/9), so read_unaligned shouldn't be necessary. The error must be somewhere else where MIDIPackets are constructed that are not aligned.
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.
@jmbarbier @arteme @oilcake Can you confirm that you're seeing this on Intel processors?
@jmbarbier @arteme @oilcake Can you confirm that you're seeing this on Intel processors?
Yep, my one is intel.
This should be fixed with the latest version of coremidi-sys
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.
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.
I think, @Boddlnagg means coremidi-sys version 3.1.1 released a couple hours ago.
Yes, that's right
I think, @Boddlnagg means coremidi-sys version 3.1.1 released a couple hours ago.
Yes, that's right
Sorry, did not get it.
@oilcake So does that mean that it works now?
@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?
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
Since neither
midirnorcoremidilock to a specific version,cargo updateshould 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! 👍
@chris-zen Maybe you can increase the version requirement of coremidi-sys for the next release, so everybody gets the fix then.