shithub: riscv

Download patch

ref: ac6d54e5c67ea62f0be7fa848e738069d4eaa44d
parent: 9e857f15163843e797e86d85deb560a8995978ef
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Apr 17 01:25:00 EDT 2025

libc: fix ALL tzload() bugs

It used snprint() return to check for Tzone.tzname truncation,
can never happen as our snprintf() will never return anything
>= the passed buffer size (it always nul-terminates).

Return path is wrong, forgetting to unlock.

Passing the tzname to snprint format! so if you tzload("%s")
it crashes.

Does the realloc() of the zones array in wrong order (before
load). In case tzload() fails, and returns. We never assign
newzones to zones, so zones points to potentially stale data.

--- a/sys/src/libc/port/date.c
+++ b/sys/src/libc/port/date.c
@@ -167,6 +167,11 @@
 	int i, f, r;
 
 	memset(tz, 0, sizeof(Tzone));
+	strncpy(tz->tzname, name, sizeof(tz->tzname));
+	if(tz->tzname[sizeof(tz->tzname)-1]){
+		werrstr("timezone name too long");
+		return -1;
+	}
 	if(strcmp(name, "local") == 0)
 		snprint(path, sizeof(path), "/env/timezone");
 	else
@@ -223,15 +228,11 @@
 	tz = malloc(sizeof(Tzone));
 	if(tz == nil)
 		goto error;
+	if(loadzone(tz, tzname) != 0)
+		goto error;
 	newzones = realloc(zones, (nzones + 1) * sizeof(Tzone*));
 	if(newzones == nil)
 		goto error;
-	if(loadzone(tz, tzname) != 0)
-		goto error;
-	if(snprint(tz->tzname, sizeof(tz->tzname), tzname) >= sizeof(tz->tzname)){
-		werrstr("timezone name too long");
-		return nil;
-	}
 	zones = newzones;
 	zones[nzones] = tz;
 	nzones++;
--