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

Null pointer de-reference / UB on Android #636

Closed
kanerogers opened this issue Feb 1, 2022 · 2 comments
Closed

Null pointer de-reference / UB on Android #636

kanerogers opened this issue Feb 1, 2022 · 2 comments

Comments

@kanerogers
Copy link

Hi, cpal team! 👋🏻

When attempting to play Audio on Android (specifically, the Oculus Quest 2 running v37), I am encountering the following crash:

02-01 12:55:52.959  7140  7140 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-01 12:55:52.959  7140  7140 F DEBUG   : Build fingerprint: 'oculus/hollywood/hollywood:10/QQ3A.200805.001/22310100587300000:user/release-keys'
02-01 12:55:52.959  7140  7140 F DEBUG   : Revision: '0'
02-01 12:55:52.959  7140  7140 F DEBUG   : ABI: 'arm64'
02-01 12:55:52.961  7140  7140 F DEBUG   : Timestamp: 2022-02-01 12:55:52+1100
02-01 12:55:52.961  7140  7140 F DEBUG   : pid: 7016, tid: 7074, name: AudioTrack  >>> rust.beat_saber_example <<<
02-01 12:55:52.961  7140  7140 F DEBUG   : uid: 10044
02-01 12:55:52.961  7140  7140 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
02-01 12:55:52.961  7140  7140 F DEBUG   : Cause: null pointer dereference
02-01 12:55:52.961  7140  7140 F DEBUG   :     x0  00000074312f57e0  x1  0000000000000000  x2  ffffffffffffffe0  x3  00000074312f8ec0
02-01 12:55:52.961  7140  7140 F DEBUG   :     x4  00000074312f8f20  x5  0000000000000004  x6  0000007543fcc000  x7  0000000000038a32
02-01 12:55:52.961  7140  7140 F DEBUG   :     x8  0000000000000000  x9  0000007432aea8b0  x10 0000000000000002  x11 0000000000000000
02-01 12:55:52.961  7140  7140 F DEBUG   :     x12 0000000000000486  x13 0000000000000480  x14 0000000000000001  x15 00000000ffffffff
02-01 12:55:52.961  7140  7140 F DEBUG   :     x16 0000007458d24238  x17 0000007542081180  x18 0000007431fda000  x19 0000007449de1b60
02-01 12:55:52.961  7140  7140 F DEBUG   :     x20 0000007449df5b10  x21 00000000000006e8  x22 0000007449e21018  x23 0000007449df5bc0
02-01 12:55:52.962  7140  7140 F DEBUG   :     x24 0000000000000001  x25 0000000000000009  x26 0000007542495db8  x27 00000074312f8f20
02-01 12:55:52.962  7140  7140 F DEBUG   :     x28 0000007449e21010  x29 0000000000000008
02-01 12:55:52.962  7140  7140 F DEBUG   :     sp  0000007432aea840  lr  00000074589a618c  pc  00000074589a61c0
02-01 12:55:52.963  7140  7140 F DEBUG   :
02-01 12:55:52.963  7140  7140 F DEBUG   : backtrace:
02-01 12:55:52.963  7140  7140 F DEBUG   :       #00 pc 000000000270b1c0  /data/app/rust.beat_saber_example-NNT7xdMklMIjjQstNCNAWQ==/lib/arm64/libbeat_saber_example.so (_$LT$oddio..mixer..Mixer$LT$T$GT$$u20$as$u20$oddio..signal..Signal$GT$::sample::hc4b93e6922dcee08+728)
02-01 12:55:52.963  7140  7140 F DEBUG   :       #01 pc 0000000000000486  <unknown>

The specific line in the backtrace points to this section of my code:

fn setup_audio() {
         // Configure cpal
        let host = cpal::default_host();
        let device = host
            .default_output_device()
            .expect("no output device available");
        let sample_rate = device.default_output_config().unwrap().sample_rate();
        let config = cpal::StreamConfig {
            channels: 2,
            sample_rate,
            buffer_size: cpal::BufferSize::Default,
        };

        // Pipe the mixer to the audio hardware.
        let stream = device
            .build_output_stream(
                &config,
                move |out_flat: &mut [f32], _: &cpal::OutputCallbackInfo| {
                    let out_stereo: &mut [[f32; 2]] = oddio::frame_stereo(out_flat);
                    oddio::run(&mixer, sample_rate.0, out_stereo);
                },
                |err| {
                    eprintln!(
                        "[HOTHAM_AUDIO_CONTEXT] An error occurred playing the audio stream: {}",
                        err
                    )
                },
            )
            .unwrap();
}

Which I believe is calling this function in oddio:

    fn sample(&self, interval: f32, out: &mut [T]) {
        let this = &mut *self.recv.borrow_mut();
        this.set.update();

        for o in out.iter_mut() {
            *o = T::ZERO;
        }

        for i in (0..this.set.len()).rev() {
            let signal = &this.set[i];
            if Arc::strong_count(signal) == 1 {
                signal.handle_dropped();
            }
            if signal.remaining() <= 0.0 {
                signal.stop();
            }
            if signal.is_stopped() {
                this.set.remove(i);
                continue;
            }
            if signal.is_paused() {
                continue;
            }

            // Sample into `buffer`, then mix into `out`
            let mut iter = out.iter_mut();
            while iter.len() > 0 {
                let n = iter.len().min(this.buffer.len());
                let staging = &mut this.buffer[..n];
                signal.sample(interval, staging);
                for (staged, o) in staging.iter().zip(&mut iter) {
                    *o = frame::mix(o, staged);
                }
            }
        }
    }

As there isn't any unsafe code in any of these functions, I believe the problem is somewhere inside of cpal.

After digging further, I was able to determine the problem is setup_audio was called too early in the Android lifecycle. If the code is called only after ndk_glue::Event::Resume is received, then the issue is resolved.

I'm not familiar enough with cpal to dig into why the UB is being triggered, but as this was quite a tricky problem to track down and resolve, it may be worth investigating why UB was triggered in cpal's safe API.

Please let me know if there's any further information I can provide!

@kanerogers
Copy link
Author

Unfortunately the issue is now occurring even when the app is in the Resumed state.

Compiling with debug symbols enabled I can now see that the issue is inside of oboe:

02-02 12:40:35.768 13060 13060 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
02-02 12:40:35.784 13060 13060 I crash_dump64: performing dump of process 12799 (target tid = 12914)
02-02 12:40:35.826 13060 13060 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-02 12:40:35.826 13060 13060 F DEBUG   : Build fingerprint: 'oculus/hollywood/hollywood:10/QQ3A.200805.001/22310100587300000:user/release-keys'
02-02 12:40:35.826 13060 13060 F DEBUG   : Revision: '0'
02-02 12:40:35.826 13060 13060 F DEBUG   : ABI: 'arm64'
02-02 12:40:35.828 13060 13060 F DEBUG   : Timestamp: 2022-02-02 12:40:35+1100
02-02 12:40:35.829 13060 13060 F DEBUG   : pid: 12799, tid: 12914, name: AudioTrack  >>> rust.beat_saber_example <<<
02-02 12:40:35.829 13060 13060 F DEBUG   : uid: 10044
02-02 12:40:35.829 13060 13060 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
02-02 12:40:35.829 13060 13060 F DEBUG   : Cause: null pointer dereference
02-02 12:40:35.829 13060 13060 F DEBUG   :     x0  000000744aa88700  x1  0000000000000001  x2  00000074336ea610  x3  00000074336ea618
02-02 12:40:35.829 13060 13060 F DEBUG   :     x4  001e3af03b000000  x5  0000000000000000  x6  0000007543fcc000  x7  0000000000ab7602
02-02 12:40:35.829 13060 13060 F DEBUG   :     x8  00000074336ea678  x9  000000744aa88700  x10 00000074336ea610  x11 0000000000000000
02-02 12:40:35.829 13060 13060 F DEBUG   :     x12 000000000000da30  x13 000000000000da2f  x14 0000000000000001  x15 00000000ffffffff
02-02 12:40:35.829 13060 13060 F DEBUG   :     x16 0000007459120260  x17 00000075420807f8  x18 0000007432a04000  x19 000000744aa88880
02-02 12:40:35.829 13060 13060 F DEBUG   :     x20 00000000000006a0  x21 0000007431ef3aa0  x22 0000007458ae0bb8  x23 0100804010040101
02-02 12:40:35.829 13060 13060 F DEBUG   :     x24 00000074b6505b78  x25 0000000000000009  x26 0000007542495db8  x27 000000000d000000
02-02 12:40:35.829 13060 13060 F DEBUG   :     x28 00000000000006a0  x29 00000074336ea630
02-02 12:40:35.829 13060 13060 F DEBUG   :     sp  00000074336ea5e0  lr  0000007458adcd54  pc  0000000000000000
02-02 12:40:35.871 13060 13060 F DEBUG   :
02-02 12:40:35.871 13060 13060 F DEBUG   : backtrace:
02-02 12:40:35.871 13060 13060 F DEBUG   :       #00 pc 0000000000000000  <unknown>
02-02 12:40:35.871 13060 13060 F DEBUG   :       #01 pc 0000000001796d50  /data/app/rust.beat_saber_example-lTJcL8SefsPB6JHa8_r0cg==/lib/arm64/libbeat_saber_example.so (oboe::AudioStream::getTimestamp(int)+56)
02-02 12:40:35.871 13060 13060 F DEBUG   :       #02 pc 2d52474f00000670  <unknown>

I'll file an issue with them and link back to this one.

@kanerogers
Copy link
Author

Looks like the true source of the error was the cpal stream getting dropped too early, hence oboe getting a null pointer de-reference. I'll follow up there!

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

No branches or pull requests

1 participant