shithub: scc

Download patch

ref: 2ef958d9809092755fd5fb1f154c8ab97cb8604e
parent: 94f23734015424515144b54f0a9f9d6c9d2f34c2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue May 17 09:01:11 EDT 2022

libc: Return 0 when truncation in strftime()

When the buffer is not big enough to hold the generated string strftime()
must returns 0. Strftime() was genereting a marker value '?' in that
case, but it made impossible to control the actual space that would be
required to store the value. For that reason, the code is modified
to store as much characters as it can, enabling it to detect the
truncation case.

--- a/src/libc/time/strftime.c
+++ b/src/libc/time/strftime.c
@@ -96,20 +96,21 @@
 	char *str;
 	size_t len;
 
-	if (idx < 0 && idx >= max)
-		goto wrong;
+	if (siz == 0)
+		return 0;
 
+	if (idx < 0 && idx >= max) {
+		*s = '?';
+		return 1;
+	}
+
 	str = strs[idx];
 	len = (!abrev) ? strlen(str) : 3;
 	if (len > siz)
-		goto wrong;
+		len = siz;
 
 	memcpy(s, str, len);
 	return len;
-
-wrong:
-	*s = '?';
-	return 1;
 }
 
 static size_t
@@ -119,7 +120,13 @@
 	int n;
 	static char digits[] = "0123456789";
 
-	if (prec > siz || val < 0) {
+	if (siz == 0)
+		return 0;
+
+	if (prec > siz)
+		prec = siz;
+
+	if (val < 0) {
 		*s = '?';
 		return 1;
 	}
@@ -137,15 +144,11 @@
 }
 
 static size_t
-timezone(char *s, size_t prec, const struct tm * restrict tm)
+timezone(char *s, size_t siz, const struct tm * restrict tm)
 {
+	size_t n;
 	long off = tm->tm_gmtoff;
 
-        if (prec < 5) {
-                *s = '?';
-                return 1;
-        }
-
 	if (off >= 0) {
 		*s++ = '+';
 	} else {
@@ -153,10 +156,11 @@
 		off = -off;
 	}
 
-	dval(s, 2, 2, '0', off / 3600);
-	dval(s + 2, 2, 2, '0', (off % 3600) / 60);
+	n = 1;
+	n += dval(s, siz-n, 2, '0', off / 3600);
+	n += dval(s + n, siz-n, 2, '0', (off % 3600) / 60);
 
-	return 5;
+	return n;
 }
 
 size_t
@@ -294,12 +298,9 @@
 			break;
 		case 'Z':
 			inc = strlen(timeptr->tm_zone);
-			if (inc > n) {
-				*s = '?';
-				inc = 1;
-			} else {
-				memcpy(s, timeptr->tm_zone, inc);
-			}
+			if (inc > n)
+				inc = n;
+			memcpy(s, timeptr->tm_zone, inc);
 			break;
 		case '\0':
 			inc = 0;