Skip to content

newlib: correct RTEMS scalar type widths#5308

Closed
physwkim wants to merge 1 commit into
rust-lang:mainfrom
physwkim:rtems-type-widths
Closed

newlib: correct RTEMS scalar type widths#5308
physwkim wants to merge 1 commit into
rust-lang:mainfrom
physwkim:rtems-type-widths

Conversation

@physwkim

@physwkim physwkim commented Jul 21, 2026

Copy link
Copy Markdown

Six scalar types are wrong for target_os = "rtems". Measured with an
arm-rtems6 toolchain and run on armv7-rtems-eabihf under
qemu-system-arm, including only <sys/types.h> and <time.h>:

type libc measured this PR
time_t i32 8, align 8, signed c_longlong
dev_t u32 8, align 8, unsigned u64
ino_t u32 8, align 8, unsigned u64
rlim_t u32 8, align 8, signed i64
clock_t c_long 8, align 8, unsigned c_ulonglong
clockid_t c_ulong 4, signed c_int
TC time_t     size=8 align=8 signed=1      TC clock_t    size=8 align=8 signed=0
TC dev_t      size=8 align=8 signed=0      TC clockid_t  size=4 align=4 signed=1
TC ino_t      size=8 align=8 signed=0      TC rlim_t     size=8 align=8 signed=1

The other 13 newlib scalars were measured too and are correct, off_t
(already i64) included.

Impact

libc::timespec is { time_t, c_long }, so with time_t = i32 it is 8 bytes
where RTEMS's is 16. std's SystemTime::now/Instant::now pass a
MaybeUninit<libc::timespec> to clock_gettime, so every clock read writes
4 bytes past the end of that stack slot
(measured: 12 bytes written into an
8-byte slot; a canary 8 bytes past it is clobbered), and tv_nsec lands where
the 8-byte view never reads it:

std SystemTime[0] secs=567993600 subsec_nanos=0
std SystemTime[4] secs=567993600 subsec_nanos=0     <- several ms later
std Instant elapsed secs=0 subsec_nanos=0

So on RTEMS today every sub-second duration silently measures zero — every
Instant-based timeout, rate limit and watchdog reads 0 with no panic and no
diagnostic. That is the half that makes this urgent; the out-of-bounds write is
the half that makes it a soundness bug.

After the patch: timespec 16/align 8, subsec_nanos=15715519,
Instant::elapsed() nonzero. Derived layouts then match the target exactly —
timeval 16, itimerspec 32, struct stat 104 with st_size @40.

Changes

time_t, dev_t, ino_t, rlim_t, clockid_t gain a target_os = "rtems"
arm in src/unix/newlib/mod.rs, which already selects by target_os before
falling through to target_arch. clock_t is declared per-arch, so the RTEMS
value goes in src/unix/newlib/rtems/ (already glob-imported for RTEMS) and
newlib/arm's copy is gated #[cfg(not(target_os = "rtems"))].
No non-RTEMS target changes. timespec/timeval/itimerspec need no
separate fix — they follow from time_t.

Verification

  • A const _: () = assert!(...) file over all seven types: 0 errors on this
    branch, 16 errors on main.
  • riscv32imc-esp-espidf builds, unchanged. armv7-sony-vita-newlibeabihf and
    armv6k-nintendo-3ds fail identically before and after (pre-existing
    E0573 at src/unix/mod.rs:936).
  • cargo +nightly fmt --all -- --check clean.
  • Toolchain: RTEMS 6.0.0 2faafecb, gcc 13.3.0, newlib 1b3dcfd, BSP
    xilinx_zynq_a9_qemu. Standalone reproduction available (one crate, an RSB
    toolchain and qemu-system-arm, nothing else) — happy to attach.

Relation to #5132

#5132 proposes time_t = i64 for the non-espidf/vita branch, which covers the
time_t row here and is correct. It leaves dev_t/ino_t at u32 — measured
8 on RTEMS — and does not touch rlim_t, clock_t or clockid_t. Happy to
rebase this down to the four types it does not cover if it lands first
;
flagging so the two are not merged blind to each other.

Must reach 0.2 to change anything for std: library/std/Cargo.toml depends on
libc 0.2.x.

@rustbot label stable-nominated

Sibling: #5307 (RTEMS socket address types) — unrelated defect, but both add to
src/unix/newlib/rtems/mod.rs, so whichever lands second needs a one-hunk
context rebase there.

On RTEMS, `time_t`, `dev_t`, `ino_t`, `rlim_t` and `clock_t` are all 8 bytes
wide; `libc` declares them 4. `clockid_t` is signed, `libc` declares it
unsigned. Measured with `arm-rtems6-gcc` for `armv7-rtems-eabihf` against the
`xilinx_zynq_a9_qemu` BSP (RTEMS 6.0.0, newlib 1b3dcfd, gcc 13.3.0), from
`<sys/types.h>` alone:

    TC rlim_t       size=8 align=8 signed=1
    TC dev_t        size=8 align=8 signed=0
    TC ino_t        size=8 align=8 signed=0
    TC time_t       size=8 align=8 signed=1
    TC clock_t      size=8 align=8 signed=0
    TC clockid_t    size=4 align=4 signed=1

`time_t` is the one with teeth: it makes `struct timespec` 8 bytes where
RTEMS's is 16, so every `clock_gettime` writes 4 bytes past the end of the
caller's slot, and `std`'s `SystemTime`/`Instant` read `tv_nsec` as 0.

`clock_t` is per-arch in this tree, so the RTEMS value goes in
`newlib/rtems/` and `newlib/arm/`'s copy is gated with
`not(target_os = "rtems")`; no non-RTEMS newlib target changes.
@rustbot rustbot added O-arm O-newlib O-unix S-waiting-on-review stable-nominated This PR should be considered for cherry-pick to libc's stable release branch labels Jul 21, 2026
@physwkim

Copy link
Copy Markdown
Author

@rustbot label stable-nominated

@tgross35

Copy link
Copy Markdown
Contributor

#5132 is going to merge first, we'll see what remains after it does.

@rustbot blocked

No AI for PR descriptions, commit messages, or comments please.

@physwkim

Copy link
Copy Markdown
Author

#5132 is going to merge first, we'll see what remains after it does.

@rustbot blocked

No AI for PR descriptions, commit messages, or comments please.

@tgross35 Understood. I'll follow the guidelines.

@physwkim physwkim closed this Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-arm O-newlib O-unix S-blocked stable-nominated This PR should be considered for cherry-pick to libc's stable release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants