summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2023-10-04 20:54:28 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2023-10-04 20:54:28 (GMT)
commit600c5b59541d100659c84992a2e118b7eba65e41 (patch)
tree3559aad7f431a5adbdb7ed219044955faceaa83d /generic/tclBasic.c
parent1081ce3d811ca2df171d764f1611eb89d8a891b3 (diff)
parentd6de3e27b418588da31a5a14d20a6bf03289c876 (diff)
downloadtcl-600c5b59541d100659c84992a2e118b7eba65e41.zip
tcl-600c5b59541d100659c84992a2e118b7eba65e41.tar.gz
tcl-600c5b59541d100659c84992a2e118b7eba65e41.tar.bz2
Merge 8.6
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 318374e..4187462 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
@@ -9726,6 +9761,7 @@ TclNRCoroutineActivateCallback(
TCL_UNUSED(int) /*result*/)
{
CoroutineData *corPtr = (CoroutineData *)data[0];
+ void *stackLevel = TclGetCStackPtr();
if (!corPtr->stackLevel) {
/*
@@ -9742,7 +9778,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;
@@ -9756,7 +9792,7 @@ TclNRCoroutineActivateCallback(
* Coroutine is active: yield
*/
- if (corPtr->stackLevel != &corPtr) {
+ if (corPtr->stackLevel != stackLevel) {
NRE_callback *runPtr;
iPtr->execEnvPtr = corPtr->callerEEPtr;