From: Nadav Har'El <n...@scylladb.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

libc: fix build error (and potential bug) in __year_to_secs

Musl's __year_to_secs() has this strange code:

    int *is_leap;
    ...
    if (!is_leap) is_leap = &(int){0};

The motivation is to set the pointer, if unset, to point to our own integer.
But nothing in the C standard guarantees that this temporary integer will
actually live as long as the "is_leap" variable lives... Since C++03
there is such a guarantee for *const* *reference*, but this is not C++,
not const, and not a reference :-)

Gcc 12.1.1 started to complain about this, calling it a "dangling pointer
to an unnamed temporary". Unfortunately to fix it we need to make a copy
of this musl source file and change it:

    15,19c15
    <   int our_is_leap;
    <   if (!is_leap) {
    <           our_is_leap = 0;
    <           is_leap = &our_is_leap;
    <     }
    ---
    >   if (!is_leap) is_leap = &(int){0};

Signed-off-by: Nadav Har'El <n...@scylladb.com>

---
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -1812,7 +1812,7 @@ musl += time/__secs_to_tm.o
 musl += time/__tm_to_secs.o
 libc += time/__tz.o
 $(out)/libc/time/__tz.o: pre-include-api = -isystem 
include/api/internal_musl_headers -isystem musl/src/include
-musl += time/__year_to_secs.o
+libc += time/__year_to_secs.o
 musl += time/asctime.o
 musl += time/asctime_r.o
 musl += time/ctime.o
diff --git a/libc/time/__year_to_secs.c b/libc/time/__year_to_secs.c
--- a/libc/time/__year_to_secs.c
+++ b/libc/time/__year_to_secs.c
@@ -0,0 +1,51 @@
+long long __year_to_secs(long long year, int *is_leap)
+{
+       if (year-2ULL <= 136) {
+               int y = year;
+               int leaps = (y-68)>>2;
+               if (!((y-68)&3)) {
+                       leaps--;
+                       if (is_leap) *is_leap = 1;
+               } else if (is_leap) *is_leap = 0;
+               return 31536000*(y-70) + 86400*leaps;
+       }
+
+       int cycles, centuries, leaps, rem;
+
+       int our_is_leap;
+       if (!is_leap) {
+               our_is_leap = 0;
+               is_leap = &our_is_leap;
+    }
+       cycles = (year-100) / 400;
+       rem = (year-100) % 400;
+       if (rem < 0) {
+               cycles--;
+               rem += 400;
+       }
+       if (!rem) {
+               *is_leap = 1;
+               centuries = 0;
+               leaps = 0;
+       } else {
+               if (rem >= 200) {
+                       if (rem >= 300) centuries = 3, rem -= 300;
+                       else centuries = 2, rem -= 200;
+               } else {
+                       if (rem >= 100) centuries = 1, rem -= 100;
+                       else centuries = 0;
+               }
+               if (!rem) {
+                       *is_leap = 0;
+                       leaps = 0;
+               } else {
+                       leaps = rem / 4U;
+                       rem %= 4U;
+                       *is_leap = !rem;
+               }
+       }
+
+       leaps += 97*cycles + 24*centuries - *is_leap;
+
+       return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
+}

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000d8c39005e25626a7%40google.com.

Reply via email to