2024-08-22
| ||
19:02 | Merge [a19b5c1f833aed47]: Fix [8ab8a138c9]: Functions passed to Tcl_EventuallyFree() must be declare... check-in: 64c1352555 user: pooryorick tags: unchained, INCOMPATIBLE_LICENSE | |
2024-04-05
| ||
21:21 | • Closed ticket [df85199878]: Tcl_SetResult compiler warnings plus 7 other changes artifact: 2b70d72f82 user: jan.nijtmans | |
2024-02-16
| ||
11:28 | • Ticket [8ab8a138c9] Functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl_FreeProc status still Pending with 3 other changes artifact: 3b0513364e user: jan.nijtmans | |
11:06 | • Ticket [8ab8a138c9]: 3 changes artifact: 65cf874dc4 user: chrstphrchvz | |
2023-10-26
| ||
20:08 | Final fix for [8ab8a138c9]: functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl... check-in: 91e8692bdf user: jan.nijtmans tags: core-8-branch | |
2023-10-22
| ||
23:18 | • Ticket [8ab8a138c9] Functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl_FreeProc status still Pending with 3 other changes artifact: f4c18b2b5a user: chrstphrchvz | |
2023-10-13
| ||
14:23 | • Ticket [8ab8a138c9]: 3 changes artifact: 7cd7441c2f user: jan.nijtmans | |
13:58 | • Ticket [8ab8a138c9]: 3 changes artifact: 30a8da4632 user: chrstphrchvz | |
06:56 | • Ticket [8ab8a138c9]: 3 changes artifact: 133a3ce12e user: chrstphrchvz | |
2023-10-11
| ||
12:27 | • Ticket [8ab8a138c9]: 3 changes artifact: 1d76a072fe user: chrstphrchvz | |
12:20 | • Ticket [8ab8a138c9]: 3 changes artifact: 92940d9e5f user: chrstphrchvz | |
11:18 | • Pending ticket [8ab8a138c9]. artifact: 339b90b07c user: jan.nijtmans | |
09:45 | Fix [8ab8a138c9]: Functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl_FreeProc check-in: df7a3fd9e1 user: jan.nijtmans tags: core-8-6-branch | |
07:50 | • Ticket [8ab8a138c9] Functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl_FreeProc status still Open with 4 other changes artifact: 0231766c80 user: jan.nijtmans | |
07:32 | • Ticket [8ab8a138c9]: 4 changes artifact: 6860e38024 user: chrstphrchvz | |
07:23 | • Ticket [8ab8a138c9]: 3 changes artifact: 42f31524a5 user: chrstphrchvz | |
2023-10-10
| ||
11:35 | Proposed fix for [8ab8a138c9]: Do not pass incompatible function pointers to Tcl_EventuallyFree(). ... check-in: 281df17f0d user: jan.nijtmans tags: bug-8ab8a138c9 | |
10:07 | • Ticket [8ab8a138c9] Do not pass incompatible function pointers to Tcl_EventuallyFree() status still Open with 3 other changes artifact: c7b80349df user: chrstphrchvz | |
2023-10-07
| ||
13:13 | • Ticket [8ab8a138c9]: 3 changes artifact: 473fc1ecbe user: chrstphrchvz | |
13:06 | • Ticket [8ab8a138c9]: 3 changes artifact: beec9be887 user: chrstphrchvz | |
12:33 | • Add attachment 8ab8a138c915.diff to ticket [8ab8a138c9] artifact: 4dfdb7098a user: chrstphrchvz | |
12:30 | • New ticket [8ab8a138c9] Do not pass incompatible function pointers to Tcl_EventuallyFree(). artifact: cb73bae87f user: chrstphrchvz | |
Ticket UUID: | 8ab8a138c9156e5a5a4a386310c6fd11608b8805 | |||
Title: | Functions passed to Tcl_EventuallyFree() must be declared/defined as Tcl_FreeProc | |||
Type: | Patch | Version: | 8.6.13 | |
Submitter: | chrstphrchvz | Created on: | 2023-10-07 12:30:45 | |
Subsystem: | 42. Memory Preservation | Assigned To: | jan.nijtmans | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Pending | Last Modified: | 2024-02-16 11:28:09 | |
Resolution: | Fixed | Closed By: | nobody | |
Closed on: | ||||
Description: |
LLVM Clang 17 makes -fsanitize=function available for C (previously it was just for C++). It is implied by -fsanitize=undefined. It complains about calls to freeProc(clientData) from Tcl_EventuallyFree() and Tcl_Release(). Unlike warnings from e.g. -Wincompatible-function-pointer-types, this UBSan error is not suppressed by casts to (Tcl_FreeProc *). Example when exiting tclsh:
tcl/generic/tclPreserve.c:229:3: runtime error: call to function DeleteInterpProc through pointer to incorrect function type 'void (*)(char *)'
tclBasic.c:1422: note: DeleteInterpProc defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior tcl/generic/tclPreserve.c:229:3 in
There are only a few instances of this in core Tcl; to patch these, I remove casts to (Tcl_FreeProc *), then use the Tcl_FreeProc typedef for function declarations, and then fix function definitions. There are several more instances in core Tk which I am looking into patching. Any extensions passing incompatible function pointers to Tcl_EventuallyFree() will also trigger this UBSan error.
| |||
User Comments: |
jan.nijtmans added on 2024-02-16 11:28:09:
> ... LTO which I am not aware how well Tcl supports Tcl and Tk support LTO, except for the stub libraries (for which LTO actually doesn't make much sense). chrstphrchvz added on 2024-02-16 11:06:31: I have since learned that eliminating -fsanitize=function complaints is also useful for security hardening, because some control flow integrity schemes require calling functions using the correct pointer type (although some schemes also rely on LTO which I am not aware how well Tcl supports). See https://maskray.me/blog/2022-12-18-control-flow-integrity#fsanitizefunction chrstphrchvz added on 2023-10-22 23:18:44:
There's a lot of code out there (e.g. Tk, Itcl) which uses this feature, UBSan just reports false-positives for them. One can use -fsanitize=undefined -fno-sanitize=function, but I doubt UBSan’s reports of undefined behavior are false positives*, despite things behaving as expected under typical calling conventions. Or have I misunderstood what you meant by “false positives”? *(The only potential false positives I am aware of are those due to this feature’s reliance on name mangling, which is more strict than standard C type compatibility; see https://reviews.llvm.org/D148827.) That being said, I do not know how immediate any danger posed by optimizing compilers is for exploiting this type of undefined behavior. Instances within a single translation unit, or with LTO enabled, speculatively seem more concerning. jan.nijtmans added on 2023-10-13 14:23:23: > …Currently, I believe it would be better to not suppress those compile-time complaints, particular Would it be possible to disable those when doing your UBSan tests? There's a lot of code out there (e.g. Tk, Itcl) which uses this feature, UBSan just reports false-positives for them. As it is now, they can use whatever pointer-type without warning. In Tcl 9.0, the pointer type changes to "void *", there we want the full UBSan warnings, but for 8.x it really doesn't matter much to chase this. Thanks for all your efforts! I see the point! chrstphrchvz added on 2023-10-13 13:58:28:
-Wcast-function-type also works.…but not when there is an intermediate (void *) cast. The casts in tclDecls.h cause Tcl_EventuallyFree() and Tcl_SetResult() to be called from function pointers of incorrect type, and so now UBSan complains even more. A couple of examples:
tk/generic/tkMenuDraw.c:796:2: runtime error: call to function Tcl_EventuallyFree through pointer to incorrect function type 'void (*)(void *, void *)'
tclPreserve.c:265: note: Tcl_EventuallyFree defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior tk/generic/tkMenuDraw.c:796:2 in
tcl/generic/tclTest.c:1117:2: runtime error: call to function Tcl_SetResult through pointer to incorrect function type 'void (*)(struct Tcl_Interp *, char *, void *)'
tclResult.c:419: note: Tcl_SetResult defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior tcl/generic/tclTest.c:1117:2 in
chrstphrchvz added on 2023-10-13 06:56:24:
…Currently, I believe it would be better to not suppress those compile-time complaints, particularly since they help identify and fix would-be -fsanitize=function errors… -Wcast-function-type also works. chrstphrchvz added on 2023-10-11 12:27:36:
How are the changes to tclDecls.h beneficial?What I mean is, aside from the effect of suppressing compiler warnings/errors, is there some benefit I am not aware of? chrstphrchvz added on 2023-10-11 12:20:45: How are the changes to tclDecls.h beneficial? They ensure the suppression of compiler warnings (or errors as of LLVM Clang 16, by default) regarding passing of incompatible function pointers. Currently, I believe it would be better to not suppress those compile-time complaints, particularly since they help identify and fix would-be -fsanitize=function errors, at least for the iterative workflow I used (remove any existing casts to (Tcl_FreeProc *) by Tcl_EventuallyFree() users, then fix declarations in response to compiler complaints of passing incompatible function pointers, then fix definitions in response to compiler complaints of declaration/definition mismatch). jan.nijtmans added on 2023-10-11 07:50:12: Thanks for your feedback! I was aware that the extra (void *) cast would not foll ubsan, but I thought it was worth to give it a try. I'll fix it as you suggest chrstphrchvz added on 2023-10-11 07:32:44: Ticket title revised. chrstphrchvz added on 2023-10-11 07:23:35: Jan, I am sorry if the title I gave this ticket was misleading, but unfortunately the work so far on the bug-8ab8a138c9 branch ultimately does not solve the problem. What matters is the type of actual function declarations/definitions, and not the type of function pointers passed to Tcl_EventuallyFree(). At runtime, when freeProc() is called from Tcl_EventuallyFree() or Tcl_Release(), UBSan -fsanitize=function checks whether the function pointed to by freeProc was actually declared/defined with a signature matching the type of freeProc, which is Tcl_FreeProc. It does not matter to this UBSan check whether the function pointer in freeProc was originally passed to Tcl_EventuallyFree() through any casts, so I do not see what is accomplished by additional intermediate casting through void *. I still believe the correct fix for this problem is to declare/define functions correctly, which is what I meant in the title: only pointers to functions whose actual declarations/definitions match Tcl_FreeProc should be passed to Tcl_EventuallyFree() (which can be done without casts), so that UBSan does not complain when the function is later called from Tcl_EventuallyFree() or Tcl_Release(). chrstphrchvz added on 2023-10-10 10:07:33: Proposed patch for Tk 8.6: https://core.tcl-lang.org/tk/info/d96974d99d72 chrstphrchvz added on 2023-10-07 13:06:18: I now notice that in Tcl 9, Tcl_FreeProc expects a void *. If reverting to char * is undesirable, then should a macro or typedef be introduced for use by Tk 8.7 and anything else intending to build against both Tcl 8 and 9? |
Attachments:
- 8ab8a138c915.diff [download] added by chrstphrchvz on 2023-10-07 12:33:36. [details]