summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2023-10-04 21:12:59 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2023-10-04 21:12:59 (GMT)
commit8f1f56d42b418a9e91029a8c59be886facf7cb21 (patch)
treee56c722c99076cf07c7240789f95436896d39eed /generic/tclBasic.c
parentcb6c9c4787b898a85c3b1577906d50d0ba793118 (diff)
parent600c5b59541d100659c84992a2e118b7eba65e41 (diff)
downloadtcl-8f1f56d42b418a9e91029a8c59be886facf7cb21.zip
tcl-8f1f56d42b418a9e91029a8c59be886facf7cb21.tar.gz
tcl-8f1f56d42b418a9e91029a8c59be886facf7cb21.tar.bz2
Merge 8.7
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 3ceb427..4f43ca5 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -64,6 +64,41 @@
#endif /* !TCL_FPCLASSIFY_MODE */
+/*
+ * Bug 7371b6270b: to check C call stack depth, prefer an approach which is
+ * compatible with AddressSanitizer (ASan) use-after-return detection.
+ */
+
+#if defined(HAVE_INTRIN_H)
+#include <intrin.h> /* for _AddressOfReturnAddress() */
+#endif
+
+/*
+ * As suggested by
+ * https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin
+ */
+#ifndef __has_builtin
+#define __has_builtin(x) 0 /* for non-clang compilers */
+#endif
+
+void *
+TclGetCStackPtr(void)
+{
+#if defined(HAVE_INTRIN_H)
+ return _AddressOfReturnAddress();
+#elif __GNUC__ || __has_builtin(__builtin_frame_address)
+ return __builtin_frame_address(0);
+#else
+ ptrdiff_t unused = 0;
+ /*
+ * LLVM recommends using volatile:
+ * https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0-rc1/clang/lib/Basic/Stack.cpp#L31
+ */
+ ptrdiff_t *volatile stackLevel = &unused;
+ return (void *)stackLevel;
+#endif
+}
+
#define INTERP_STACK_INITIAL_SIZE 2000
#define CORO_STACK_INITIAL_SIZE 200
@@ -9211,6 +9246,7 @@ TclNRCoroutineActivateCallback(
TCL_UNUSED(int) /*result*/)
{
CoroutineData *corPtr = (CoroutineData *)data[0];
+ void *stackLevel = TclGetCStackPtr();
if (!corPtr->stackLevel) {
/*
@@ -9227,7 +9263,7 @@ TclNRCoroutineActivateCallback(
* the interp's environment to make it suitable to run this coroutine.
*/
- corPtr->stackLevel = &corPtr;
+ corPtr->stackLevel = stackLevel;
Tcl_Size numLevels = corPtr->auxNumLevels;
corPtr->auxNumLevels = iPtr->numLevels;
@@ -9241,7 +9277,7 @@ TclNRCoroutineActivateCallback(
* Coroutine is active: yield
*/
- if (corPtr->stackLevel != &corPtr) {
+ if (corPtr->stackLevel != stackLevel) {
NRE_callback *runPtr;
iPtr->execEnvPtr = corPtr->callerEEPtr;