Attachment "clock-format-z-overflow.patch" to
ticket [e713c36677]
added by
bef
2026-11-05 16:17:29.
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -2921,23 +2921,27 @@
TCL_UNUSED(int *))
{
if (*tok->tokWord.start == 'z') {
- int z = dateFmt->date.tzOffset;
+ Tcl_WideInt z = dateFmt->date.tzOffset;
char sign = '+';
if (z < 0) {
z = -z;
sign = '-';
}
- if (FrmResultAllocate(dateFmt, 7) != TCL_OK) {
+ /*
+ * Sign, hours, minutes and seconds. The offset is a 32-bit value, so
+ * the hours take up to 6 digits: +hhhhhhmmss is at most 11 chars.
+ */
+ if (FrmResultAllocate(dateFmt, 11) != TCL_OK) {
return TCL_ERROR;
}
*dateFmt->output++ = sign;
- dateFmt->output = Clock_itoaw(dateFmt->output, z / 3600, '0', 2);
+ dateFmt->output = Clock_itoaw(dateFmt->output, (int)(z / 3600), '0', 2);
z %= 3600;
- dateFmt->output = Clock_itoaw(dateFmt->output, z / 60, '0', 2);
+ dateFmt->output = Clock_itoaw(dateFmt->output, (int)(z / 60), '0', 2);
z %= 60;
if (z != 0) {
- dateFmt->output = Clock_itoaw(dateFmt->output, z, '0', 2);
+ dateFmt->output = Clock_itoaw(dateFmt->output, (int)z, '0', 2);
}
} else {
Tcl_Obj * objPtr;
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -38902,6 +38902,32 @@
list [clock format 0 -gmt 1 -locale he -format %EE] \
[clock format -62200000000 -gmt 1 -locale he -format %EE]
} -result [list "\u05dc\u05e1\u05d4\"\u05e0" "\u05dc\u05e4\u05e1\u05d4\"\u05e0"]
+
+test clock-72.1 {%z with an offset of 100 hours or more at the end of the stack buffer} -body {
+ clock format 0 -timezone +99:99:99 -format "[string repeat a 72]%z"
+} -result "[string repeat a 72]+1004039"
+test clock-72.2 {%z with an offset of 100 hours or more at the end of a heap buffer} -body {
+ clock format 0 -timezone +99:99:99 \
+ -format "[string repeat a 100]%Y[string repeat b 148]%z"
+} -result "[string repeat a 100]1970[string repeat b 148]+1004039"
+test clock-72.3 {%z with the largest 32-bit offset} -setup {
+ clock format 0 -gmt 1
+ set ::tcl::clock::TZData(:clock-72.3) \
+ {{-9223372036854775808 2147483647 0 clock-72.3}}
+} -body {
+ clock format 0 -timezone :clock-72.3 -format "[string repeat a 72]%z"
+} -cleanup {
+ unset -nocomplain ::tcl::clock::TZData(:clock-72.3)
+} -result "[string repeat a 72]+5965231407"
+test clock-72.4 {%z with the smallest 32-bit offset} -setup {
+ clock format 0 -gmt 1
+ set ::tcl::clock::TZData(:clock-72.4) \
+ {{-9223372036854775808 -2147483648 0 clock-72.4}}
+} -body {
+ clock format 0 -timezone :clock-72.4 -format "[string repeat a 72]%z"
+} -cleanup {
+ unset -nocomplain ::tcl::clock::TZData(:clock-72.4)
+} -result "[string repeat a 72]-5965231408"
# cleanup