Tcl Source Code

View Ticket
Login
Ticket UUID: 0e8fd6c6d5fd2f29f90c6e101197796951e399d6
Title: (unsigned)STRING_SIZE(STRING_MAXCHARS) is 0
Type: Patch Version: core-8-6-branch
Submitter: chrstphrchvz Created on: 2022-03-22 02:02:17
Subsystem: 10. Objects Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2022-03-24 01:01:51
Resolution: Fixed Closed By: chrstphrchvz
    Closed on: 2022-03-24 01:01:51
Description:

…causing stringAlloc(STRING_MAXCHARS) or similar to eventually lead to a crash or noticeable memory corruption. Example:

set a [string repeat a 1073741820]
# crash when attempting to create string with longest possible unicode rep and no string rep
set aa [string replace $a 0 0 $a ]

After TCLFLEXARRAY ([29540d10c4]) was introduced, STRING_MAXCHARS was updated ([3a6a0399ad]), but the …- 1… seems to be misplaced (it currently makes no difference in the numerator of the expression): see attached patch. STRING_MAXCHARS apparently should return 1 less than what it currently does (i.e. 2147483638 rather than 2147483639, for 32-bit int and 16-bit Tcl_UniChar).

To my knowledge there are no similar issues for other structures using TCLFLEXARRAY.

User Comments: chrstphrchvz added on 2022-03-24 01:01:51:

ASan issue reported: https://github.com/google/sanitizers/issues/1502


jan.nijtmans added on 2022-03-22 20:09:07:

Good catch! Should be fixed now.

Thanks for the report and the patch!


chrstphrchvz added on 2022-03-22 18:41:41:

The ASan flag allocator_frees_and_returns_null_on_realloc_zero is enabled by default, so this Tcl issue effectively triggers a double free. The problem seems to be that ASan is not detecting/reporting double frees for at least some large allocations.


chrstphrchvz added on 2022-03-22 02:10:14:

Just an observation: when built using Clang 13.0.1 AddressSanitizer (-fsanitize=address) on macOS, running this example triggers an invalid write in realloc(ptr, 0); the address is just before ptr, i.e. likely in the ASAN chunk header, so I wonder if this is an ASAN bug.

realloc(ptr, 0) (where ptr != NULL) is expected to become undefined behavior in C23, however. Should Tcl try preventing this from happening in e.g. Tcl_Realloc(), ckrealloc(), etc.?


Attachments: