Skip to content

fix(pcm): htstamp segfaults on 32-bit time64 platforms - #151

Closed
roderickvd wants to merge 2 commits into
diwic:masterfrom
roderickvd:fix/htstamp-time64-overflow
Closed

fix(pcm): htstamp segfaults on 32-bit time64 platforms #151
roderickvd wants to merge 2 commits into
diwic:masterfrom
roderickvd:fix/htstamp-time64-overflow

Conversation

@roderickvd

Copy link
Copy Markdown
Contributor

This popped up downstream in RustAudio/cpal#1134 and fixes #150 without the need to set RUST_LIBC_UNSTABLE_GNU_TIME_BITS=64.

On 32-bit Linux with a time64 glibc, snd_pcm_status_get_htstamp and friends write a 16-byte struct timespec into the pointer passed to them. Since libc::timespec is only 8 bytes on these targets, the alsa function then wrote 8 bytes past it, corrupting the stack and causing a segfault. This PR passes a 16-byte buffer on 32-bit targets to reconstruct a timespec from it.

I don't have a big-endian system to test with, but I made it endianness-aware from what I could gather. glibc's time64 seems to place a 4-byte padding before tv_nsec on big-endian and after it on little-endian, so tv_nsec sits at offset 8 on LE and offset 12 on BE. Other libcs seem to use offset 8 regardless of endianness, hence the target_env = "gnu" guard.

On 64-bit targets, libc::timespec is already 16 bytes, so the original zeroed() + direct call is left untouched.

One limitation, likely significant: 32-bit systems with a time32 alsa-lib were never affected by the segfault, but will now regress to have tv_nsec silently read as zero. While the time64 transition is effectively done on modern distros, this is almost a case of "pick your poison": segfault on 32-bit targets with time64 or return zero tv_nsec on 32-bit targets.

I say almost because it probably can be fixed using a build.rs probe of sizeof(time_t) in C to set a cfg flag. I wasn't sure whether that's worth the added complexity here, so leaving it to your judgement.

@diwic

diwic commented Mar 30, 2026

Copy link
Copy Markdown
Owner

Hi and thanks for the investigation,

On 32-bit Linux with a time64 glibc, snd_pcm_status_get_htstamp and friends write a 16-byte struct timespec into the pointer passed to them. Since libc::timespec is only 8 bytes on these targets

...but, shouldn't this be fixed in the libc crate then? So that libc::timespec is the correct 16 bytes on this target?
It seems like you're trying to work around a "bug" in the libc crate here.

@roderickvd

Copy link
Copy Markdown
Contributor Author

Yeah, I think this may be rust-lang/libc#3223. Looking at its timeline I'm not too hopeful though: open since 2023 and no clear activity since May 2025.

This PR would be defensive workaround for as long as that takes. The remaining downside is the silent tv_nsec regression on 32-bit platforms with 32-bit time_t (legacy, but not that old).

A proper fix would be a build.rs probe of sizeof(time_t) in a C compilation context. I held off because it adds complexity, but can add it if we think that's best.

@diwic

diwic commented Apr 1, 2026

Copy link
Copy Markdown
Owner

@roderickvd
See rust-lang/libc@8a28ac4 which is from three months ago. So to me it seems like there is current activity going on upstream.

I would kindly ask you to at least make an attempt to fix/raise this with the libc crate people first, since that would fix things for many more people than just alsa. If that attempt is unsuccessful, let's revisit and see what the least ugly workaround in alsa would be.

Thanks!

@diwic

diwic commented Jun 17, 2026

Copy link
Copy Markdown
Owner

@roderickvd Any news on this?

Maybe a feature in alsa-sys to force 64 bit timespec if we can't make it in libc?

@roderickvd

Copy link
Copy Markdown
Contributor Author

I didn't follow up on it with libc.

You are probably right that this is better fixed in alsa-sys than here. What's your view on that feature flag you're proposing vs. a build-time probe?

@diwic

diwic commented Jun 17, 2026

Copy link
Copy Markdown
Owner

@roderickvd

A feature flag named, say libc_time64_workaround makes it obvious what it is. A build time probe would complicate the build, right? If it would require more C headers to be installed for the build to succeed, it would be a bad thing.

But I'm not an expert on the topic and open to be convinced otherwise if you have a compelling reason to prefer the probe?

@diwic

diwic commented Jun 17, 2026

Copy link
Copy Markdown
Owner

@roderickvd

Just brainstorming - there's no way we can detect this at runtime/ program startup? Like if there's a function in libc we can call to get the current time, wait a few 100 us and call it again and see which bytes changed values, and then go from there?

@diwic

diwic commented Jun 18, 2026

Copy link
Copy Markdown
Owner

@roderickvd What do you think of this: diwic/alsa-sys#18

@roderickvd

Copy link
Copy Markdown
Contributor Author

Yes, that seems better. I'll close this one so we can continue there.

@roderickvd roderickvd closed this Jun 22, 2026
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 this pull request may close these issues.

Segfault when using with sendspin-rs on 32-bit Raspberry PI Zero W

2 participants