From 462e3dd262738368000603e841b1365c4dc115b4 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 10 Oct 2023 11:35:22 +0000 Subject: Proposed fix for [8ab8a138c9]: Do not pass incompatible function pointers to Tcl_EventuallyFree(). This should eliminate all warnings when using -fsanitize=function. --- generic/tclBasic.c | 7 ++++--- generic/tclIORChan.c | 9 +++++---- generic/tclIORTrans.c | 17 +++++++++-------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 9d84de2..f46a778 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -136,7 +136,7 @@ static int CancelEvalProc(ClientData clientData, Tcl_Interp *interp, int code); static int CheckDoubleResult(Tcl_Interp *interp, double dResult); static void DeleteCoroutine(ClientData clientData); -static void DeleteInterpProc(Tcl_Interp *interp); +static void DeleteInterpProc(void *blockPtr); static void DeleteOpCmdClientData(ClientData clientData); #ifdef USE_DTRACE static Tcl_ObjCmdProc DTraceObjCmd; @@ -1392,7 +1392,7 @@ Tcl_DeleteInterp( * Ensure that the interpreter is eventually deleted. */ - Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc); + Tcl_EventuallyFree(interp, (Tcl_FreeProc *)(void *)DeleteInterpProc); } /* @@ -1418,8 +1418,9 @@ Tcl_DeleteInterp( static void DeleteInterpProc( - Tcl_Interp *interp) /* Interpreter to delete. */ + void *blockPtr) /* Interpreter to delete. */ { + Tcl_Interp *interp = (Tcl_Interp *) blockPtr; Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; Tcl_HashSearch search; diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 3eca3f8..792cf80 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -430,7 +430,7 @@ static Tcl_Obj * DecodeEventMask(int mask); static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj); static Tcl_Obj * NextHandle(void); -static void FreeReflectedChannel(ReflectedChannel *rcPtr); +static void FreeReflectedChannel(void *blockPtr); static int InvokeTclMethod(ReflectedChannel *rcPtr, MethodName method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); @@ -1170,7 +1170,7 @@ ReflectClose( ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *)(void *)FreeReflectedChannel); return EOK; } @@ -1239,7 +1239,7 @@ ReflectClose( ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *)(void *)FreeReflectedChannel); return (result == TCL_OK) ? EOK : EINVAL; } @@ -2210,8 +2210,9 @@ NextHandle(void) static void FreeReflectedChannel( - ReflectedChannel *rcPtr) + void *blockPtr) { + ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; Channel *chanPtr = (Channel *) rcPtr->chan; TclChannelRelease((Tcl_Channel)chanPtr); diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index 730820e..d8d8b25 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -417,7 +417,7 @@ static ReflectedTransform * NewReflectedTransform(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj, Tcl_Channel parentChan); static Tcl_Obj * NextHandle(void); -static void FreeReflectedTransform(ReflectedTransform *rtPtr); +static void FreeReflectedTransform(void *blockPtr); static void FreeReflectedTransformArgs(ReflectedTransform *rtPtr); static int InvokeTclMethod(ReflectedTransform *rtPtr, const char *method, Tcl_Obj *argOneObj, @@ -718,7 +718,7 @@ TclChanPushObjCmd( * structure. */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); return TCL_ERROR; #undef CHAN @@ -924,7 +924,7 @@ ReflectClose( } #endif /* TCL_THREADS */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); return EOK; } @@ -941,7 +941,7 @@ ReflectClose( #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *) FreeReflectedTransform); + (Tcl_FreeProc *)(void *)FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ @@ -955,7 +955,7 @@ ReflectClose( #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *) FreeReflectedTransform); + (Tcl_FreeProc *)(void *)FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ @@ -975,7 +975,7 @@ ReflectClose( ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p); result = p.base.code; - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); @@ -1034,7 +1034,7 @@ ReflectClose( #endif /* TCL_THREADS */ } - Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL); } @@ -1920,8 +1920,9 @@ FreeReflectedTransformArgs( static void FreeReflectedTransform( - ReflectedTransform *rtPtr) + void *blockPtr) { + ReflectedTransform *rtPtr = (ReflectedTransform *) blockPtr; TimerKill(rtPtr); ResultClear(&rtPtr->result); -- cgit v0.12 From 0cc51f1259bd11611fce289213ceb3ae398d2406 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 10 Oct 2023 11:37:16 +0000 Subject: Follow-up for extensions: This way, usage of Tcl_EventuallyFree() won't give warnings any more. Only do this for 8.6 and 8.7, _not_ for 9.0! --- generic/tclDecls.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 8a226a9..79a2f7b 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -3973,6 +3973,9 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_SetVar(interp, varName, newValue, flags)) # define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \ (tclStubsPtr->tcl_ObjSetVar2(interp, part1, part2, newValue, flags)) +# undef Tcl_EventuallyFree +# define Tcl_EventuallyFree \ + ((void (*)(void *,void *))(void *)(tclStubsPtr->tcl_EventuallyFree)) /* 132 */ #endif #if defined(_WIN32) && defined(UNICODE) -- cgit v0.12 From 9d1989bb3d587463c572ff5d4dd49ec042c68d19 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 10 Oct 2023 11:49:11 +0000 Subject: Handle Tcl_SetResult() the same way as Tcl_EventuallyFree --- generic/tclDecls.h | 3 +++ generic/tclTest.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 79a2f7b..f8e9bcf 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -3976,6 +3976,9 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_EventuallyFree # define Tcl_EventuallyFree \ ((void (*)(void *,void *))(void *)(tclStubsPtr->tcl_EventuallyFree)) /* 132 */ +# undef Tcl_SetResult +# define Tcl_SetResult \ + ((void (*)(Tcl_Interp *, char *, void *))(void *)(tclStubsPtr->tcl_SetResult)) /* 232 */ #endif #if defined(_WIN32) && defined(UNICODE) diff --git a/generic/tclTest.c b/generic/tclTest.c index d05ef7d..c623b36 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -204,7 +204,7 @@ static int ObjTraceProc(ClientData clientData, Tcl_Obj *const objv[]); static void ObjTraceDeleteProc(ClientData clientData); static void PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr); -static void SpecialFree(char *blockPtr); +static void SpecialFree(void *blockPtr); static int StaticInitProc(Tcl_Interp *interp); static Tcl_CmdProc TestasyncCmd; static Tcl_ObjCmdProc TestbumpinterpepochObjCmd; @@ -265,7 +265,7 @@ static Tcl_ObjCmdProc TestreturnObjCmd; static void TestregexpXflags(const char *string, int length, int *cflagsPtr, int *eflagsPtr); static Tcl_ObjCmdProc TestsaveresultCmd; -static void TestsaveresultFree(char *blockPtr); +static void TestsaveresultFree(void *blockPtr); static Tcl_CmdProc TestsetassocdataCmd; static Tcl_CmdProc TestsetCmd; static Tcl_CmdProc Testset2Cmd; @@ -1764,7 +1764,7 @@ TestdstringCmd( } else if (strcmp(argv[2], "special") == 0) { char *s = (char *)ckalloc(100) + 16; strcpy(s, "This is a specially-allocated string"); - Tcl_SetResult(interp, s, SpecialFree); + Tcl_SetResult(interp, s, (Tcl_FreeProc *)(void *)SpecialFree); } else { Tcl_AppendResult(interp, "bad gresult option \"", argv[2], "\": must be staticsmall, staticlarge, free, or special", @@ -1811,9 +1811,9 @@ TestdstringCmd( */ static void SpecialFree( - char *blockPtr /* Block to free. */ + void *blockPtr /* Block to free. */ ) { - ckfree(blockPtr - 16); + ckfree((char *)blockPtr - 16); } /* @@ -5428,7 +5428,7 @@ TestsaveresultCmd( break; } case RESULT_DYNAMIC: - Tcl_SetResult(interp, (char *)"dynamic result", TestsaveresultFree); + Tcl_SetResult(interp, (char *)"dynamic result", (Tcl_FreeProc *)(void *)TestsaveresultFree); break; case RESULT_OBJECT: objPtr = Tcl_NewStringObj("object result", -1); @@ -5454,7 +5454,7 @@ TestsaveresultCmd( switch ((enum options) index) { case RESULT_DYNAMIC: { - int present = iPtr->freeProc == TestsaveresultFree; + int present = iPtr->freeProc == (Tcl_FreeProc *)(void *)TestsaveresultFree; int called = freeCount; Tcl_AppendElement(interp, called ? "called" : "notCalled"); @@ -5489,7 +5489,7 @@ TestsaveresultCmd( static void TestsaveresultFree( - char *blockPtr) + void *blockPtr) { freeCount++; } -- cgit v0.12 From a64802e7ede7f1794273c96ae87b61920c268964 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 11 Oct 2023 09:15:09 +0000 Subject: Remove typecasts, just define directly as Tcl_FreeProc --- generic/tclBasic.c | 12 ++++++------ generic/tclIORChan.c | 8 ++++---- generic/tclIORTrans.c | 16 ++++++++-------- generic/tclTest.c | 18 +++++++++++++----- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index f46a778..ff8333f 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -7,10 +7,10 @@ * * Copyright (c) 1987-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. + * Copyright (c) 1998-1999 Scriptics Corporation. + * Copyright (c) 2001, 2002 Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen - * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. + * Copyright (c) 2006-2008 Joe Mistachkin. All rights reserved. * Copyright (c) 2008 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of @@ -136,7 +136,7 @@ static int CancelEvalProc(ClientData clientData, Tcl_Interp *interp, int code); static int CheckDoubleResult(Tcl_Interp *interp, double dResult); static void DeleteCoroutine(ClientData clientData); -static void DeleteInterpProc(void *blockPtr); +static Tcl_FreeProc DeleteInterpProc; static void DeleteOpCmdClientData(ClientData clientData); #ifdef USE_DTRACE static Tcl_ObjCmdProc DTraceObjCmd; @@ -1392,7 +1392,7 @@ Tcl_DeleteInterp( * Ensure that the interpreter is eventually deleted. */ - Tcl_EventuallyFree(interp, (Tcl_FreeProc *)(void *)DeleteInterpProc); + Tcl_EventuallyFree(interp, DeleteInterpProc); } /* @@ -1418,7 +1418,7 @@ Tcl_DeleteInterp( static void DeleteInterpProc( - void *blockPtr) /* Interpreter to delete. */ + char *blockPtr) /* Interpreter to delete. */ { Tcl_Interp *interp = (Tcl_Interp *) blockPtr; Interp *iPtr = (Interp *) interp; diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 792cf80..69a8e11 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -430,7 +430,7 @@ static Tcl_Obj * DecodeEventMask(int mask); static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj); static Tcl_Obj * NextHandle(void); -static void FreeReflectedChannel(void *blockPtr); +static Tcl_FreeProc FreeReflectedChannel; static int InvokeTclMethod(ReflectedChannel *rcPtr, MethodName method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); @@ -1170,7 +1170,7 @@ ReflectClose( ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *)(void *)FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, FreeReflectedChannel); return EOK; } @@ -1239,7 +1239,7 @@ ReflectClose( ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *)(void *)FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, FreeReflectedChannel); return (result == TCL_OK) ? EOK : EINVAL; } @@ -2210,7 +2210,7 @@ NextHandle(void) static void FreeReflectedChannel( - void *blockPtr) + char *blockPtr) { ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; Channel *chanPtr = (Channel *) rcPtr->chan; diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index d8d8b25..bc0e20c 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -417,7 +417,7 @@ static ReflectedTransform * NewReflectedTransform(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj, Tcl_Channel parentChan); static Tcl_Obj * NextHandle(void); -static void FreeReflectedTransform(void *blockPtr); +static Tcl_FreeProc FreeReflectedTransform; static void FreeReflectedTransformArgs(ReflectedTransform *rtPtr); static int InvokeTclMethod(ReflectedTransform *rtPtr, const char *method, Tcl_Obj *argOneObj, @@ -718,7 +718,7 @@ TclChanPushObjCmd( * structure. */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return TCL_ERROR; #undef CHAN @@ -924,7 +924,7 @@ ReflectClose( } #endif /* TCL_THREADS */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return EOK; } @@ -941,7 +941,7 @@ ReflectClose( #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *)(void *)FreeReflectedTransform); + FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ @@ -955,7 +955,7 @@ ReflectClose( #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *)(void *)FreeReflectedTransform); + FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ @@ -975,7 +975,7 @@ ReflectClose( ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p); result = p.base.code; - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); @@ -1034,7 +1034,7 @@ ReflectClose( #endif /* TCL_THREADS */ } - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *)(void *)FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL); } @@ -1920,7 +1920,7 @@ FreeReflectedTransformArgs( static void FreeReflectedTransform( - void *blockPtr) + char *blockPtr) { ReflectedTransform *rtPtr = (ReflectedTransform *) blockPtr; TimerKill(rtPtr); diff --git a/generic/tclTest.c b/generic/tclTest.c index c623b36..ea23d40 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -204,7 +204,7 @@ static int ObjTraceProc(ClientData clientData, Tcl_Obj *const objv[]); static void ObjTraceDeleteProc(ClientData clientData); static void PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr); -static void SpecialFree(void *blockPtr); +static Tcl_FreeProc SpecialFree; static int StaticInitProc(Tcl_Interp *interp); static Tcl_CmdProc TestasyncCmd; static Tcl_ObjCmdProc TestbumpinterpepochObjCmd; @@ -265,7 +265,7 @@ static Tcl_ObjCmdProc TestreturnObjCmd; static void TestregexpXflags(const char *string, int length, int *cflagsPtr, int *eflagsPtr); static Tcl_ObjCmdProc TestsaveresultCmd; -static void TestsaveresultFree(void *blockPtr); +static Tcl_FreeProc TestsaveresultFree; static Tcl_CmdProc TestsetassocdataCmd; static Tcl_CmdProc TestsetCmd; static Tcl_CmdProc Testset2Cmd; @@ -1764,7 +1764,7 @@ TestdstringCmd( } else if (strcmp(argv[2], "special") == 0) { char *s = (char *)ckalloc(100) + 16; strcpy(s, "This is a specially-allocated string"); - Tcl_SetResult(interp, s, (Tcl_FreeProc *)(void *)SpecialFree); + Tcl_SetResult(interp, s, SpecialFree); } else { Tcl_AppendResult(interp, "bad gresult option \"", argv[2], "\": must be staticsmall, staticlarge, free, or special", @@ -1811,7 +1811,11 @@ TestdstringCmd( */ static void SpecialFree( +#if TCL_MAJOR_VERSION > 8 void *blockPtr /* Block to free. */ +#else + char *blockPtr /* Block to free. */ +#endif ) { ckfree((char *)blockPtr - 16); } @@ -5428,7 +5432,7 @@ TestsaveresultCmd( break; } case RESULT_DYNAMIC: - Tcl_SetResult(interp, (char *)"dynamic result", (Tcl_FreeProc *)(void *)TestsaveresultFree); + Tcl_SetResult(interp, (char *)"dynamic result", TestsaveresultFree); break; case RESULT_OBJECT: objPtr = Tcl_NewStringObj("object result", -1); @@ -5454,7 +5458,7 @@ TestsaveresultCmd( switch ((enum options) index) { case RESULT_DYNAMIC: { - int present = iPtr->freeProc == (Tcl_FreeProc *)(void *)TestsaveresultFree; + int present = iPtr->freeProc == TestsaveresultFree; int called = freeCount; Tcl_AppendElement(interp, called ? "called" : "notCalled"); @@ -5489,7 +5493,11 @@ TestsaveresultCmd( static void TestsaveresultFree( +#if TCL_MAJOR_VERSION > 8 void *blockPtr) +#else + char *blockPtr) +#endif { freeCount++; } -- cgit v0.12