Skip to content

Commit a40c139

Browse files
committed
build: patch yosys 0.62 with the Tcl 9 use-after-free fix from main
YosysHQ/yosys 167c6c4 ("Replace deprecated Tcl API to fix use-after-free", povik, 2026-03-06) replaces five Tcl_SetResult(..., TCL_VOLATILE) callsites in kernel/tclapi.cc with Tcl_SetObjResult + Tcl_NewStringObj, the right idiom now that Tcl_SetResult is a macro under Tcl 9. Without it, rtlil::get_attr -string returns memory whose backing std::string has already been destructed, producing module names with stray control characters when synth_wrap_operators.tcl concatenates ${base}_${suffix}. Symptom: 'Found control character or space (0x18) in string \\K B-W_KOGGE_STONE'. Fix is in yosys main but not yet in BCR-tagged 0.62. Carry as patch on the BCR pin via single_version_override. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
1 parent 5d36873 commit a40c139

3 files changed

Lines changed: 93 additions & 0 deletions

File tree

MODULE.bazel

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ git_override(
7474
remote = "https://github.com/povik/yosys-slang.git",
7575
)
7676

77+
# YosysHQ/yosys 167c6c4 ("Replace deprecated Tcl API to fix use-after-free")
78+
# fixes a Tcl 9 use-after-free in rtlil::get_attr/get_param that produces
79+
# corrupted module names like '\K B-W_KOGGE_STONE' during ORFS-style
80+
# wrapcell flows. The fix is in yosys main but not yet in the BCR-tagged
81+
# 0.62; carry it as a patch until the next release lands.
82+
single_version_override(
83+
module_name = "yosys",
84+
patch_strip = 1,
85+
patches = [
86+
"//bazel/yosys-patches:0001-Replace-deprecated-Tcl-API-to-fix-use-after-free.patch",
87+
],
88+
version = "0.62.bcr.2",
89+
)
90+
7791
# --- Extensions ---
7892

7993
llvm = use_extension(
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
From 167c6c45858fa637a872a57cdcdb758cd9e6c77a Mon Sep 17 00:00:00 2001
2+
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik@cutebit.org>
3+
Date: Fri, 6 Mar 2026 11:52:17 +0100
4+
Subject: [PATCH] Replace deprecated Tcl API to fix use-after-free
5+
6+
Under Tcl 9.0 the Tcl_SetResult utility is a macro:
7+
8+
#define Tcl_SetResult(interp, result, freeProc) \
9+
do { \
10+
const char *__result = result; \
11+
Tcl_FreeProc *__freeProc = freeProc; \
12+
Tcl_SetObjResult(interp, Tcl_NewStringObj(__result, -1)); \
13+
if (__result != NULL && __freeProc != NULL && __freeProc != TCL_VOLATILE) { \
14+
if (__freeProc == TCL_DYNAMIC) { \
15+
Tcl_Free((char *)__result); \
16+
} else { \
17+
(*__freeProc)((char *)__result); \
18+
} \
19+
} \
20+
} while(0)
21+
22+
Temporaries constructed as part of the 'result' expression will be
23+
dropped before the 'result' pointer is used. What was safe when
24+
Tcl_SetResult was a function isn't safe with the macro definition.
25+
Transition away from deprecated SetResult to calling
26+
SetObjResult/MewStringObj directly.
27+
---
28+
kernel/tclapi.cc | 10 +++++-----
29+
1 file changed, 5 insertions(+), 5 deletions(-)
30+
31+
diff --git a/kernel/tclapi.cc b/kernel/tclapi.cc
32+
index ec0483a4a02..9866f5c9820 100644
33+
--- a/kernel/tclapi.cc
34+
+++ b/kernel/tclapi.cc
35+
@@ -279,7 +279,7 @@ static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *ar
36+
ERROR("object not found")
37+
38+
if (string_flag) {
39+
- Tcl_SetResult(interp, (char *) obj->get_string_attribute(attr_id).c_str(), TCL_VOLATILE);
40+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(obj->get_string_attribute(attr_id).c_str(), -1));
41+
} else if (int_flag || uint_flag || sint_flag) {
42+
if (!obj->has_attribute(attr_id))
43+
ERROR("attribute missing (required for -int)");
44+
@@ -295,7 +295,7 @@ static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *ar
45+
if (!obj->has_attribute(attr_id))
46+
ERROR("attribute missing (required unless -bool or -string)")
47+
48+
- Tcl_SetResult(interp, (char *) obj->attributes.at(attr_id).as_string().c_str(), TCL_VOLATILE);
49+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(obj->attributes.at(attr_id).as_string().c_str(), -1));
50+
}
51+
52+
return TCL_OK;
53+
@@ -341,7 +341,7 @@ static int tcl_has_attr(ClientData, Tcl_Interp *interp, int argc, const char *ar
54+
if (!obj)
55+
ERROR("object not found")
56+
57+
- Tcl_SetResult(interp, (char *) std::to_string(obj->has_attribute(attr_id)).c_str(), TCL_VOLATILE);
58+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(std::to_string(obj->has_attribute(attr_id)).c_str(), -1));
59+
return TCL_OK;
60+
}
61+
62+
@@ -465,14 +465,14 @@ static int tcl_get_param(ClientData, Tcl_Interp *interp, int argc, const char *a
63+
const RTLIL::Const &value = cell->getParam(param_id);
64+
65+
if (string_flag) {
66+
- Tcl_SetResult(interp, (char *) value.decode_string().c_str(), TCL_VOLATILE);
67+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(value.decode_string().c_str(), -1));
68+
} else if (int_flag || uint_flag || sint_flag) {
69+
mp_int value_mp;
70+
if (!const_to_mp_int(value, &value_mp, sint_flag, uint_flag))
71+
ERROR("bignum manipulation failed");
72+
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&value_mp));
73+
} else {
74+
- Tcl_SetResult(interp, (char *) value.as_string().c_str(), TCL_VOLATILE);
75+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(value.as_string().c_str(), -1));
76+
}
77+
return TCL_OK;
78+
}

bazel/yosys-patches/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports_files(glob(["*.patch"]))

0 commit comments

Comments
 (0)