Skip to content

Commit

Permalink
Fix [7371b6270b]: AddressSanitizer use-after-return detection breaks …
Browse files Browse the repository at this point in the history
…NRE tests, coroutines
  • Loading branch information
jan.nijtmans committed Oct 4, 2023
2 parents 6c67bd0 + 9220b96 commit d6de3e2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 14 deletions.
39 changes: 37 additions & 2 deletions generic/tclBasic.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,42 @@
#include "tommath.h"
#include <math.h>
#include <assert.h>

/*
* 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
size_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
*/
size_t *volatile stackLevel = &unused;
return (void *)stackLevel;
#endif
}

#define INTERP_STACK_INITIAL_SIZE 2000
#define CORO_STACK_INITIAL_SIZE 200

Expand Down Expand Up @@ -8824,8 +8859,8 @@ TclNRCoroutineActivateCallback(
{
CoroutineData *corPtr = (CoroutineData *)data[0];
int type = PTR2INT(data[1]);
int numLevels, unused;
int *stackLevel = &unused;
int numLevels;
void *stackLevel = TclGetCStackPtr();

if (!corPtr->stackLevel) {
/*
Expand Down
6 changes: 5 additions & 1 deletion generic/tclInt.decls
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ declare 218 {
}

# for use in tclTest.c

# Bug 7371b6270b
declare 223 {
void *TclGetCStackPtr(void)
}
declare 224 {
TclPlatformType *TclGetPlatform(void)
}
Expand Down Expand Up @@ -586,7 +591,6 @@ declare 235 {
void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr)
}


# TIP 337 made this one public
declare 236 {
void TclBackgroundException(Tcl_Interp *interp, int code)
Expand Down
8 changes: 5 additions & 3 deletions generic/tclIntDecls.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,8 @@ EXTERN void TclPopStackFrame(Tcl_Interp *interp);
/* Slot 220 is reserved */
/* Slot 221 is reserved */
/* Slot 222 is reserved */
/* Slot 223 is reserved */
/* 223 */
EXTERN void * TclGetCStackPtr(void);
/* 224 */
EXTERN TclPlatformType * TclGetPlatform(void);
/* 225 */
Expand Down Expand Up @@ -875,7 +876,7 @@ typedef struct TclIntStubs {
void (*reserved220)(void);
void (*reserved221)(void);
void (*reserved222)(void);
void (*reserved223)(void);
void * (*tclGetCStackPtr) (void); /* 223 */
TclPlatformType * (*tclGetPlatform) (void); /* 224 */
Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 225 */
int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */
Expand Down Expand Up @@ -1289,7 +1290,8 @@ extern const TclIntStubs *tclIntStubsPtr;
/* Slot 220 is reserved */
/* Slot 221 is reserved */
/* Slot 222 is reserved */
/* Slot 223 is reserved */
#define TclGetCStackPtr \
(tclIntStubsPtr->tclGetCStackPtr) /* 223 */
#define TclGetPlatform \
(tclIntStubsPtr->tclGetPlatform) /* 224 */
#define TclTraceDictPath \
Expand Down
2 changes: 1 addition & 1 deletion generic/tclStubInit.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ static const TclIntStubs tclIntStubs = {
0, /* 220 */
0, /* 221 */
0, /* 222 */
0, /* 223 */
TclGetCStackPtr, /* 223 */
TclGetPlatform, /* 224 */
TclTraceDictPath, /* 225 */
TclObjBeingDeleted, /* 226 */
Expand Down
14 changes: 7 additions & 7 deletions generic/tclTest.c
Original file line number Diff line number Diff line change
Expand Up @@ -7390,23 +7390,23 @@ NREUnwind_callback(
Tcl_Interp *interp,
int result)
{
int none;
void *cStackPtr = TclGetCStackPtr();
(void)result;

if (data[0] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, &none, INT2PTR(-1),
Tcl_NRAddCallback(interp, NREUnwind_callback, cStackPtr, INT2PTR(-1),
INT2PTR(-1), NULL);
} else if (data[1] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], &none,
Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], cStackPtr,
INT2PTR(-1), NULL);
} else if (data[2] == INT2PTR(-1)) {
Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], data[1],
&none, NULL);
cStackPtr, NULL);
} else {
Tcl_Obj *idata[3];
idata[0] = Tcl_NewIntObj((int) ((char *) data[1] - (char *) data[0]));
idata[1] = Tcl_NewIntObj((int) ((char *) data[2] - (char *) data[0]));
idata[2] = Tcl_NewIntObj((int) ((char *) &none - (char *) data[0]));
idata[2] = Tcl_NewIntObj((int) ((char *) cStackPtr - (char *) data[0]));
Tcl_SetObjResult(interp, Tcl_NewListObj(3, idata));
}
return TCL_OK;
Expand Down Expand Up @@ -7452,10 +7452,10 @@ TestNRELevels(
(void)objv;

if (refDepth == NULL) {
refDepth = &depth;
refDepth = (ptrdiff_t *)TclGetCStackPtr();
}

depth = (refDepth - &depth);
depth = (refDepth - (ptrdiff_t *)TclGetCStackPtr());

levels[0] = Tcl_NewIntObj(depth);
levels[1] = Tcl_NewIntObj(iPtr->numLevels);
Expand Down

0 comments on commit d6de3e2

Please sign in to comment.