Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8279444

File.setLastModifiedTime(long) suffers from Year 2038 problem on 32-bit platforms

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 8, 11, 17, 18, 19
    • core-libs
    • None

      Originally spotted as tools/jar/ReproducibleJar.java failure on x86_32, see JDK-8279453.

      Reproduced with standalone jdk/bin/jar installation all the way back to 8u, using attached JAR.

      $ rm -rf outer; ./build/linux-x86-server-fastdebug/images/jdk/bin/jar xvf 8279444.jar; stat outer
        created: META-INF/
       inflated: META-INF/MANIFEST.MF
        created: outer/
        created: outer/inner/
       inflated: outer/inner/foo.txt
        File: outer
        Size: 4096 Blocks: 8 IO Block: 4096 directory
      Device: fd00h/64768d Inode: 88233545 Links: 3
      Access: (0775/drwxrwxr-x) Uid: ( 1000/ shade) Gid: ( 1000/ shade)
      Access: 2022-01-04 16:43:13.936388000 +0100
      Modify: 1963-11-25 17:31:42.000000000 +0100
      Change: 2022-01-04 16:43:13.936388034 +0100
       Birth: -

      $ rm -rf outer; ./build/linux-x86_64-server-fastdebug/images/jdk/bin/jar xvf 8279444.jar; stat outer
        created: META-INF/
       inflated: META-INF/MANIFEST.MF
        created: outer/
        created: outer/inner/
       inflated: outer/inner/foo.txt
        File: outer
        Size: 4096 Blocks: 8 IO Block: 4096 directory
      Device: fd00h/64768d Inode: 88233545 Links: 3
      Access: (0775/drwxrwxr-x) Uid: ( 1000/ shade) Gid: ( 1000/ shade)
      Access: 2022-01-04 16:43:17.740488000 +0100
      Modify: 2099-12-31 23:59:58.000000000 +0100
      Change: 2022-01-04 16:43:17.740488841 +0100
       Birth: -

      Note bad "Modify" date in x86_32 case, and good time in x86_64 case.

      I believe this is 2038 problem due to overflow during preparation for utimes call. This assert fails on x86_32, but passes on x86_64:

      diff --git a/src/java.base/unix/native/libjava/UnixFileSystem_md.c b/src/java.base/unix/native/libjava/UnixFileSystem_md.c
      index 7c23aaa567c..7b4fa9b198e 100644
      --- a/src/java.base/unix/native/libjava/UnixFileSystem_md.c
      +++ b/src/java.base/unix/native/libjava/UnixFileSystem_md.c
      @@ -427,7 +427,9 @@ Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
                   tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
       #endif
                   /* Change last-modified time */
      - tv[1].tv_sec = time / 1000;
      + jlong t = time / 1000;
      + tv[1].tv_sec = t;
      + assert(tv[1].tv_sec == t);
                   tv[1].tv_usec = (time % 1000) * 1000;
       
                   if (utimes(path, tv) == 0)

      I see that glibc started year2038 workaround work with extending tv_sec to time64_t, first batch available in glibc 2.34 (which is rather recent):
        https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#struct_timespec
        https://sourceware.org/git/?p=glibc.git;a=commit;h=bdc4782744df73a8c0559985c54b5b6b9c7a4a74
        https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html

      "* Add support for 64-bit time_t on configurations like x86 where time_t
        is traditionally 32-bit. Although time_t still defaults to 32-bit on
        these configurations, this default may change in future versions.
        This is enabled with the _TIME_BITS preprocessor macro set to 64 and is
        only supported when LFS (_FILE_OFFSET_BITS=64) is also enabled. It is
        only enabled for Linux and the full support requires a minimum kernel
        version of 5.1."

      But it does not look like a complete support is there yet, so this issue looks unsolvable at this time.

            bpb Brian Burkhalter
            shade Aleksey Shipilev
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: