Tcl Source Code

Artifact [81a06e537e]
Login

Artifact 81a06e537e61c2142ab2986e501c3d7fef76869187aec9946747684232d6ee59:

Attachment "clock-format-z-overflow.patch" to ticket [e713c36677] added by bef 2026-11-05 16:17:29. (unpublished)
--- 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