[8] RFR of 8066985: Java Webstart downloading packed files can result in Timezone set to UTC

Peter Levart peter.levart at gmail.com
Thu Mar 19 16:29:29 UTC 2015


On 03/19/2015 04:46 PM, Peter Levart wrote:
> On 03/19/2015 02:53 PM, Kumar Srinivasan wrote:
>> Mikhail,
>>
>> You can move the common utilitieschangeDefaultTimeZoneToUtc and
>> restoreDefaultTimeZoneto Utils.java.
>>
>> Also I am not sure how effective the test is ?  does it catch the 
>> issue ?
>> if you don't have the fix in PackerImpl and UnpackerImpl ?
>>
>> Otherwise it looks good, and I can sponsor this patch for you.
>>
>> Kumar
>
> Hi Mikhail,
>
> Is this code part of some utility so that it is executed exclusively 
> in it's own JVM, or can it also be executed by some public API or 
> internal JVM thread? It appears to be the later (used by 
> java.util.jar.Pack200 public API), but haven't checked.
>
> In case of the later, I think it is very strange that the code changes 
> global JVM timezone, albeit just temporarily. This could affect other 
> code that needs default TZ and executes concurrently.
>
> Even in case of the former, if the PackerImpl.pack can be executed by 
> multiple concurrent threads and if UnpackerImpl.unpack can be executed 
> by multiple concurrent threads, what guarantees that some 
> PackerImpl.pack thread is not executed concurrently with some 
> UnpackerImpl.unpack thread? You only track each method separately.
>
>
> Regards, Peter

I guess this default TZ manipulation is needed because 
JarOutputStream/JarInputStream don't provide constructors that would 
take a TZ object, but always use default TZ, right?

The cleanest way would be to add such constructors, but if this is too 
much for 8u, then perhaps some internal ThreadLocal<TZ> could be exposed 
to both PackerImpl/UnpackerImpl and Jar[Zip]Input[Output] stream 
internals. It think the use of default TZ in Jar/Zip/Streams is very 
localized. It is needed to convert local time (specified as DOS time) to 
and from epoch-based time exposed in ZipEntry. The code is located in 
package-private class java.util.zip.ZipUtils in methods dosToJavaTime 
/javaToDosTime (or equivalent extendedDosToJavaTime / 
javaToExtendedDosTime in JDK9).

Another way would be to provide a general thread-local default TZ 
override in TimeZone itself. Something like the following:

===================================================================
--- jdk/src/share/classes/java/util/TimeZone.java
+++ jdk/src/share/classes/java/util/TimeZone.java
@@ -630,8 +630,11 @@
       * method doesn't create a clone.
       */
      static TimeZone getDefaultRef() {
-        TimeZone defaultZone = defaultTimeZone;
+        TimeZone defaultZone = threadLocalTimeZone.get();
          if (defaultZone == null) {
+            defaultZone = defaultTimeZone;
+        }
+        if (defaultZone == null) {
              // Need to initialize the default time zone.
              defaultZone = setDefaultZone();
              assert defaultZone != null;
@@ -713,6 +716,20 @@
          defaultTimeZone = zone;
      }

+    public void withThreadDefaultDo(Runnable runnable) {
+        TimeZone prevZone = threadLocalTimeZone.get();
+        threadLocalTimeZone.set(this);
+        try {
+            runnable.run();
+        } finally {
+            if (prevZone == null) {
+                threadLocalTimeZone.remove();
+            } else {
+                threadLocalTimeZone.set(prevZone);
+            }
+        }
+    }
+
      /**
       * Returns true if this zone has the same rule and offset as 
another zone.
       * That is, if this zone differs only in ID, if at all.  Returns false
@@ -760,6 +777,8 @@
       */
      private String           ID;
      private static volatile TimeZone defaultTimeZone;
+    private static final ThreadLocal<TimeZone> threadLocalTimeZone =
+        new ThreadLocal<>();

      static final String         GMT_ID        = "GMT";
      private static final int    GMT_ID_LENGTH = 3;


Regards, Peter

>
>>
>>
>> On 3/18/2015 3:07 PM, Kumar Srinivasan wrote:
>>>
>>> Hello Mikhail,
>>>
>>>> Hi all,
>>>>
>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8066985
>>>>
>>>> The problem is that packer/unpacker changes global state( default 
>>>> time zone ) without proper synchronization:
>>>> http://hg.openjdk.java.net/jdk9/client/jdk/file/a159e5358e25/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java#l85 
>>>>
>>>>
>>>> however javadoc says that it's save to use it in concurrent way if 
>>>> each thread has it's own packer/unpacker instance:
>>>> http://hg.openjdk.java.net/jdk9/client/jdk/file/a159e5358e25/src/java.base/share/classes/java/util/jar/Pack200.java#l149 
>>>>
>>>>
>>>> The fix is:
>>>> 1. first packer/unpacker saves default time zone
>>>> 2. the last set it back.
>>>>
>>>> Webrev:
>>>> http://cr.openjdk.java.net/~mcherkas/8066985/webrev.00/
>>>
>>> The above link is wrong!, it takes me to webrev for 8073187,
>>> which has only the PackerImpl changes.
>>>
>>> I am guessing the link should be:
>>> http://cr.openjdk.java.net/~mcherkas/8066985/webrev.00/
>>>
>>> Kumar
>>>
>>>>
>>>> Thanks,
>>>> Mikhail.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>
>




More information about the core-libs-dev mailing list