Tk Source Code

View Ticket
20:22 Closed ticket [eedd795d]: sizeof(enum) != sizeof(int) plus 7 other changes artifact: 1d02e7f2 user: jan.nijtmans
Missing TK_OPTION_ENUM_VAR usage. See [eedd795d98] check-in: 28b4d791 user: jan.nijtmans tags: revised_text, tip-466
Fix [eedd795d98]: sizeof(enum) != sizeof(int) check-in: 1280fcc3 user: jan.nijtmans tags: core-8-6-branch
13:56 Ticket [eedd795d] sizeof(enum) != sizeof(int) status still Open with 3 other changes artifact: a8ab25fc user: jan.nijtmans
Proposed fix for [eedd795d98]: sizeof(enum) != sizeof(int) check-in: 9bcac876 user: jan.nijtmans tags: bug-eedd795d98
13:28 New ticket [eedd795d] sizeof(enum) != sizeof(int). artifact: 43dea77b user: jan.nijtmans

Ticket UUID: eedd795d987bd576164c247548395fe50396ddfe
Title: sizeof(enum) != sizeof(int)
Type: Bug Version: 8.6
Submitter: jan.nijtmans Created on: 2022-05-05 13:28:36
Subsystem: 23. Option Parsing Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2022-05-08 20:22:39
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2022-05-08 20:22:39

When sizeof(enum) != sizeof(int), unaligned pointer access can happen when using TK_OPTION_STRING_TABLE. This is non-portable. The default behaviour of gcc/clang is to use 'int' as implementation for enum, but the -fshort-enum compiler option can be used to make enum storage more efficient. This cannot be used for Tk, currently.

Problem description: In tkPlace.c, lines 70-72:

    Tk_Anchor anchor;	... (Tk_Anchor is an enum)
    BorderMode borderMode; ... (BorderMode is an enum too)
If both Tk_Anchor and BorderMode are implemented as shorts, they fit together in an integer and borderMode will not be aligned on a 4-byte border.

Further below:

    {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", -1,
	 Tk_Offset(Content, anchor), ...
    {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", -1,
	 Tk_Offset(Content, borderMode), ...
The `TK_OPTION_STRING_TABLE` option expects a `Tk_Offset` which is 4-byte aligned, as the variable (`borderMode` in this case) should be an integer. It isn't: it's an enum. As soon as the `-bordermode` option is used in the `place`, this will result in non-aligned access: crash!

In total, I found 17 places where this is done wrong. Most of them have an int or a pointer following or preceding the offending variable, so no unaligned access will happen: some padding bytes will be written unintentionally, but that's all. the `-bordermode` is the only example found which really can go wrong.

Proposed solution: Use a new flag TK_OPTION_ENUM_VAR, and check for this flag in TK_OPTION_STRING_TABLE parsing.

User Comments: jan.nijtmans added on 2022-05-08 20:22:39:

The 'revised_text' branch had some additional places where `TK_OPTION_ENUM_VAR` was lacking. Added those now.


jan.nijtmans added on 2022-05-05 13:56:36:

Proposed fix here