| Ticket UUID: | 813699148d19177469c94023f3dc739cbd2d9f8d | ||
| Title: | Heap out-of-bounds read and NULL dereference in `clock` on malformed `TZData` | ||
| Type: | Bug | Created on: | 2026-11-05 14:33:49 |
| Submitter: | bef | Assigned to: | jan.nijtmans |
| Subsystem: | 16. Commands A-H | Severity: | Severe |
| Priority: | 5 Medium | Last modified: | 2026-11-06 11:30:53 |
| Status: | Closed | Closed by: | jan.nijtmans |
| Resolution: | Fixed | Closed on: | 2026-11-06 11:30:53 |
| Version: | 8.6.18, 9.0.4, 9.1.0, 9.1.1 trunk | ||
| Description: | ||||
|
Security issue: memory corruption that a script in a safe interpreter can trigger on trunk and in every release, and that any trusted script can trigger everywhere. The C clock code takes the rows of All three PoCs below run in a plain
The stray pointer in 1 and 2 is more than a read: it gets a reference count increment, is stored in the conversion cache and in the result, and is read as a string, so whatever object or data it points to is written to and may later be freed. With the normal allocator the slot past a small list usually lies inside the same allocator block and holds leftover data from an earlier use. In one run on an optimised trunk build it held string bytes ( Exploitability. Items 1 and 2 are assessed as plausibly exploitable for code execution, given an address leak or heap predictability. No exploit has been written. Item 3 is a denial of service only. In a safe interpreter
This gives the same report as 1 on trunk, 9.1.0 and 9.0.4 (on 8.6 the helpers take the rows themselves instead of a name, with the same result). The helpers should not be visible there at all. The reads go back to the C clock code of 8.5.0 (2005), except the Fix suggestion. In | ||||
| User Comments: | ||||
jan.nijtmans added on 2026-11-05 16:54:07:
Thanks for this elaborate report with testcases! Now put together in a [01cd1ca85c|branch]. Can you verify it's OK? Someone else who wants to review? If there is no objection/remarks, I'll merge this to trunk in a few days. serhiy.storchaka added on 2026-11-05 19:07:06:
Reviewed [01cd1ca85c]. With ASan and UBSan, the three PoCs and the safe-interp one now give "malformed time zone data", and clock.test passes. One case is still open: the :GMT shortcut in TclConvertUTCToLocal() reads the first row without checking rowc, and does not check that element 3 exists. After "set ::tcl::clock::TZData(:GMT) {}" the next "clock format 0 -gmt 1" crashes in Tcl_ListObjIndex(); with a 3-element row the name is NULL and %Z crashes on it. Only trusted scripts can reach it. Minor: the changes.md link has a stray opening bracket (fixed in [e8180fc66e]), and clock-72.0..72.2 leave TZData(:bad) behind. 9.0 and 8.6 need the checks too. This does not cover the other half of the report: on trunk the ::tcl::clock::* helpers, including getenv, are still visible in safe interps. jan.nijtmans added on 2026-11-06 08:29:56:
Fixed in [999ff2b72f|trunk] and core-9-0-branch Many thanks! Can be backported to 8.6 as well. jan.nijtmans added on 2026-11-06 11:30:53:
Now also backported to core-8-6-branch | ||||
