mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-08-28 23:30:21 +00:00
uim: Fix uim-module-manager segfault from a GC'd require filename
uim-module-manager crashes in uim_init() while requiring key.scm:
#0 __strlen_evex ()
#1 make_loaded_str (filename=0x7e)
#2 scm_p_require ()
...
#29 uim_init ()
scm_p_require() dereferences its FILENAME argument again after the
nested scm_load(), but nothing keeps a tagged ScmObj reference to it.
SigScheme's conservative collector only accepts properly tagged words
(within_heapp() / SCM_TAG_CONSISTENTP()), while the compiler keeps just
SCM_DROP_TAG(filename) and the interior char *, so the string is swept
and its cell recycled mid-load:
before load: cell=0x7ffff7d5a090 obj_x=0x555555569180 "key.scm"
after load: cell=0x7ffff7d5a090 obj_x=0x7e <- recycled
Whether it triggers is pure allocation timing, which is why uim-native
fell over while the cross-built uim ran the same scm files fine.
Add the patch to the common SRC_URI rather than the class-target one,
since it is uim-native that scm/Makefile runs at build time.
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
+103
@@ -0,0 +1,103 @@
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Sun, 2 Aug 2026 00:00:00 +0000
|
||||
Subject: [PATCH] sigscheme: GC-protect the objects used by require
|
||||
|
||||
uim-module-manager segfaults inside uim_init() while requiring key.scm:
|
||||
|
||||
#0 __strlen_evex ()
|
||||
#1 make_loaded_str (filename=0x7e)
|
||||
#2 scm_p_require ()
|
||||
...
|
||||
#26 uim_scm_require_file ()
|
||||
#29 uim_init ()
|
||||
|
||||
scm_p_require() dereferences its FILENAME argument again after
|
||||
scm_require_internal() has run, and scm_require_internal() keeps
|
||||
LOADED_STR live across a nested scm_load(). Neither object is
|
||||
GC-protected.
|
||||
|
||||
SigScheme's conservative collector only recognizes *tagged* ScmObj
|
||||
values: within_heapp() rejects any candidate word whose tag is not
|
||||
consistent with the cell it points to (SCM_TAG_CONSISTENTP()). An
|
||||
optimizing compiler is free to keep only SCM_DROP_TAG(filename) and the
|
||||
interior "char *" returned by SCM_STRING_STR(), and gcc does exactly
|
||||
that here:
|
||||
|
||||
scm_p_require:
|
||||
mov %rdi,%rbp
|
||||
and $0xfffffffffffffff8,%rbp # SCM_DROP_TAG(filename)
|
||||
mov 0x0(%rbp),%r12 # SCM_STRING_STR(filename)
|
||||
... # no tagged copy is kept anywhere
|
||||
|
||||
While the nested scm_load() runs, the string is therefore unreachable
|
||||
for the GC. A cons allocation inside that load triggers a mark & sweep,
|
||||
the string cell is put on the free list (its body free()d by
|
||||
SCM_CELL_STRING_FIN()) and the cell is immediately recycled. The
|
||||
following SCM_STRING_STR(filename) then returns whatever the new
|
||||
occupant stores in obj_x -- 0x7e above -- and strlen() faults:
|
||||
|
||||
before load: cell=0x7ffff7d5a090 obj_x=0x555555569180 "key.scm"
|
||||
after load: cell=0x7ffff7d5a090 obj_x=0x7e <- recycled
|
||||
|
||||
Whether this is hit depends purely on allocation timing, which is why it
|
||||
shows up for one build of uim and not for another built from the same
|
||||
sources on the same host.
|
||||
|
||||
Protect the objects for as long as they are needed.
|
||||
|
||||
Upstream-Status: Submitted [https://github.com/uim/uim/issues]
|
||||
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
sigscheme/src/module-sscm-ext.c | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/sigscheme/src/module-sscm-ext.c
|
||||
+++ b/sigscheme/src/module-sscm-ext.c
|
||||
@@ -224,11 +224,15 @@
|
||||
{
|
||||
ScmObj loaded_str;
|
||||
|
||||
- loaded_str = make_loaded_str(filename);
|
||||
+ /* scm_load() below can trigger a GC and the conservative collector only
|
||||
+ * recognizes tagged ScmObj values, so protect LOADED_STR explicitly. */
|
||||
+ scm_gc_protect_with_init(&loaded_str, make_loaded_str(filename));
|
||||
if (!scm_providedp(loaded_str)) {
|
||||
scm_load(filename);
|
||||
scm_provide(loaded_str);
|
||||
}
|
||||
+ scm_gc_unprotect(&loaded_str);
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -242,15 +246,28 @@
|
||||
|
||||
ENSURE_STRING(filename);
|
||||
|
||||
+ /* FILENAME is dereferenced again below and its body is handed to
|
||||
+ * scm_load() as a plain char *. Optimizing compilers keep only
|
||||
+ * SCM_DROP_TAG(filename) and SCM_STRING_STR(filename) live, and
|
||||
+ * within_heapp() rejects both, so without this explicit protection the
|
||||
+ * string is swept (and its body free()d) by a GC triggered from the
|
||||
+ * nested load. */
|
||||
+ scm_gc_protect(&filename);
|
||||
+
|
||||
scm_require_internal(SCM_STRING_STR(filename));
|
||||
|
||||
#if SCM_COMPAT_SIOD
|
||||
- loaded_str = make_loaded_str(SCM_STRING_STR(filename));
|
||||
+ scm_gc_protect_with_init(&loaded_str,
|
||||
+ make_loaded_str(SCM_STRING_STR(filename)));
|
||||
retsym = scm_intern(SCM_STRING_STR(loaded_str));
|
||||
SCM_SYMBOL_SET_VCELL(retsym, SCM_TRUE);
|
||||
+ scm_gc_unprotect(&loaded_str);
|
||||
+ scm_gc_unprotect(&filename);
|
||||
|
||||
return retsym;
|
||||
#else
|
||||
+ scm_gc_unprotect(&filename);
|
||||
+
|
||||
return SCM_TRUE;
|
||||
#endif
|
||||
}
|
||||
@@ -4,7 +4,9 @@ LICENSE = "BSD-3-Clause AND LGPL-2.0-or-later"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=ab2826b41ca0ff4030d38cc39791d1c8"
|
||||
SECTION = "inputmethods"
|
||||
|
||||
SRC_URI = "https://github.com/uim/uim/releases/download/${PV}/uim-${PV}.tar.bz2"
|
||||
SRC_URI = "https://github.com/uim/uim/releases/download/${PV}/uim-${PV}.tar.bz2 \
|
||||
file://0001-sigscheme-GC-protect-the-objects-used-by-require.patch \
|
||||
"
|
||||
SRC_URI:append:class-target = "\
|
||||
file://uim-module-manager.patch \
|
||||
"
|
||||
|
||||
Reference in New Issue
Block a user