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;