Description
maudio-sys currently uses one pregenerated Unix binding file across multiple Unix
chitectures and libc environments. The bindings shipped in versions 0.1.3 and 0.1.4 appear to
ve been generated against x86-64 glibc headers and are ABI-incompatible with aarch64 glibc.
This causes maudio::Device to allocate less storage than ma_device_init_ex() expects. The
implementation then writes beyond the Rust allocation, corrupting the heap.
Environment
maudio: 0.1.6
maudio-sys: reproduced with 0.1.3 and 0.1.4
- Rust target:
aarch64-unknown-linux-gnu
- OS: NixOS ARM64
- libc: glibc 2.42
- Backend: PulseAudio
This appears to be an architecture/libc ABI issue rather than a NixOS-specific issue.
ABI measurements
The pregenerated Rust bindings report:
| Type |
Rust pregenerated binding |
pthread_mutex_t / ma_mutex |
40 |
ma_context |
1024 |
ma_device |
3776 |
A C translation unit compiled for aarch64-unknown-linux-gnu reports:
| Type |
AArch64 glibc C ABI |
pthread_mutex_t / ma_mutex |
48 |
ma_context |
1056 |
ma_device |
3832 |
The alignments match at 8 bytes, but the sizes and internal layouts do not.
Failure
Initializing and later destroying a PulseAudio playback device eventually aborts with:
free(): invalid size
SIGABRT
maudio::Device allocates using Rust’s smaller ma_device layout. ma_device_init_ex() is compiled
against the larger target C layout and overruns that allocation.
##Confirmation using generated bindings
I repeated the test against the published maudio 0.1.6 / maudio-sys 0.1.4 crates with the
generate-bindings feature enabled.
With bindings generated from the target aarch64 glibc headers, an explicit PulseAudio playback
device initializes and uninitializes successfully without heap corruption.
This confirms that the issue is in the pregenerated Unix bindings rather than the PulseAudio
backend itself.
On NixOS, bindgen needed to be pointed at the target glibc headers using
BINDGEN_EXTRA_CLANG_ARGS.
Workaround
Enable target-native binding generation:
[dependencies]
maudio = { version = "0.1.6", features = ["generate-bindings"] }
This requires Clang/libclang and access to the target headers.
Suggested fix
Select pregenerated bindings using Cargo’s full TARGET, including:
- architecture;
- operating system;
- libc/environment.
At minimum, Linux bindings should be separate for:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-musl
Alternatively, bindgen could run against the correct target sysroot.
Changing only aggregate size constants would not be sufficient because embedded pthread types,
field offsets, unions, alignment, and aggregate layouts all depend on the target headers.
It would also be useful to add a separately compiled C helper that returns sizeof and alignment
values for pthread_mutex_t, ma_mutex, ma_context, and ma_device, then compare those values with
Rust’s size_of and align_of.
Description
maudio-syscurrently uses one pregenerated Unix binding file across multiple Unixchitectures and libc environments. The bindings shipped in versions 0.1.3 and 0.1.4 appear to
ve been generated against x86-64 glibc headers and are ABI-incompatible with aarch64 glibc.
This causes
maudio::Deviceto allocate less storage thanma_device_init_ex()expects. Theimplementation then writes beyond the Rust allocation, corrupting the heap.
Environment
maudio: 0.1.6maudio-sys: reproduced with 0.1.3 and 0.1.4aarch64-unknown-linux-gnuThis appears to be an architecture/libc ABI issue rather than a NixOS-specific issue.
ABI measurements
The pregenerated Rust bindings report:
pthread_mutex_t/ma_mutexma_contextma_deviceA C translation unit compiled for
aarch64-unknown-linux-gnureports:pthread_mutex_t/ma_mutexma_contextma_deviceThe alignments match at 8 bytes, but the sizes and internal layouts do not.
Failure
Initializing and later destroying a PulseAudio playback device eventually aborts with:
maudio::Device allocates using Rust’s smaller ma_device layout. ma_device_init_ex() is compiled
against the larger target C layout and overruns that allocation.
##Confirmation using generated bindings
I repeated the test against the published maudio 0.1.6 / maudio-sys 0.1.4 crates with the
generate-bindings feature enabled.
With bindings generated from the target aarch64 glibc headers, an explicit PulseAudio playback
device initializes and uninitializes successfully without heap corruption.
This confirms that the issue is in the pregenerated Unix bindings rather than the PulseAudio
backend itself.
On NixOS, bindgen needed to be pointed at the target glibc headers using
BINDGEN_EXTRA_CLANG_ARGS.
Workaround
Enable target-native binding generation:
This requires Clang/libclang and access to the target headers.
Suggested fix
Select pregenerated bindings using Cargo’s full TARGET, including:
At minimum, Linux bindings should be separate for:
Alternatively, bindgen could run against the correct target sysroot.
Changing only aggregate size constants would not be sufficient because embedded pthread types,
field offsets, unions, alignment, and aggregate layouts all depend on the target headers.
It would also be useful to add a separately compiled C helper that returns sizeof and alignment
values for pthread_mutex_t, ma_mutex, ma_context, and ma_device, then compare those values with
Rust’s size_of and align_of.