Project

General

Profile

Actions

Bug #21569

open

[armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF

Added by amacxz (Aleksey Maximov) 1 day ago. Updated about 14 hours ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf]
[ruby-core:123209]

Description

Environment:
CPU: ARMv7-A (NVIDIA Tegra 2), VFPv3-D16, no NEON
OS/libc: Linux, musl (ld-musl-armhf.so.1)
Compiler: GCC 14.3.0
Ruby: 3.3.8 (built from source via Gentoo ebuild)
CFLAGS actually used by system: "-Os -pipe -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard"

During make install (or Gentoo’s ebuild install phase) Ruby runs:

./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- \
  --disable-gems -r./armv7a-linux-musleabihf-fake ./tool/rbinstall.rb \
  --make=make --dest-dir="$D" --extout=.ext --ext-build-dir=./ext \
  --mflags="-j1" --make-flags=" V=1" --gnumake --install=all --exclude=doc

This reliably triggers a SIGBUS on armv7 hard-float.

Observed crash:

Thread "ruby33" received signal SIGBUS (Bus error).
#0  ibf_load_object_float () from libruby33.so.3.3
(gdb) bt
#0  ibf_load_object_float
#1  ibf_load_object
#2  rb_ibf_load_iseq_complete
#3  ibf_load_iseq
#4  ...
(gdb) info reg
r0 = 0xb6f508b6  (not 8-byte aligned)
pc = 0xb6cacf78 <ibf_load_object_float+32>
(gdb) x/6i $pc-8
   ...
   0xb6cacf74: vldr d0, [r0]   <-- VFP double load from unaligned addr → SIGBUS

Root cause
In compile.c:

static VALUE
ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
    const double *dblp = IBF_OBJBODY(double, offset);
    return DBL2NUM(*dblp);
}

IBF_OBJBODY(double, ...) may return an unaligned pointer. On ARMv7, VFP vldr with an unaligned double address raises SIGBUS (no kernel fixup). Hence the crash while loading IBF.

Proposed fix
Read into an aligned local with memcpy:

--- a/compile.c
+++ b/compile.c
@@ -12921,10 +12921,12 @@ static VALUE
 ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
 {
-    const double *dblp = IBF_OBJBODY(double, offset);
-    return DBL2NUM(*dblp);
+    /* IBF buffer may be unaligned on some platforms. On ARMv7, a VFP
+     * double load from an unaligned address causes SIGBUS. */
+    double d;
+    memcpy(&d, IBF_OBJBODY(void, offset), sizeof(d));
+    return DBL2NUM(d);
 }

Notes:
The issue reproduces consistently on Tegra2 (armv7a, vfpv3-d16, no NEON) with musl, but (IMO) conceptually applies to any strict-alignment ARMv7 platform.
A similar audit may be required for other IBF loaders reading 8-byte types.
Please review and merge the fix (or implement an equivalent alignment-safe read for IBF floats).
I can test any proposed patch on this hardware.


Files

compile_and_debug_log.txt (31.3 KB) compile_and_debug_log.txt amacxz (Aleksey Maximov), 09/10/2025 05:58 PM

Updated by nobu (Nobuyoshi Nakada) about 14 hours ago

Thank you for the report.

amacxz (Aleksey Maximov) wrote:

+    memcpy(&d, IBF_OBJBODY(void, offset), sizeof(d));

I think void should be double since IBF_OBJBODY won't work on void.
At least the fallback definition, offsetof(struct { char _; T t; }, t), is invalid where T is void.

Actions

Also available in: Atom PDF

Like0
Like0Like0