Re: [cp-patches] FYI: java.util.Locale - fix broken serialization and equals()

2006-08-12 Thread Mark Wielaard
On Sun, 2006-08-13 at 02:21 +0200, Sven de Marothy wrote:
> 2006-08-13  Sven de Marothy  <[EMAIL PROTECTED]>
> 
>   * java/util/Locale.java
>   (hashcode): Is a serialized field, not transient.
>   (equals): Should NOT compare strings by reference.
>   (readObject/writeObject): Use the default methods and handle the hash
>   seperately.
> [...]
> +int temp = hashcode;
> +hashcode = -1;
> +s.defaultWriteObject();
> +hashcode = temp;

This is not thread-safe. If one thread serializes the Locale and another
uses its hashCode() method.

> [...]
> -language = ((String) s.readObject()).intern();
> -country = ((String) s.readObject()).intern();
> -variant = ((String) s.readObject()).intern();
> +s.defaultReadObject();

There are a couple of places in this class that depend on these three
fields to be interned. Please see the comments in the class that say so.

Cheers,

Mark


signature.asc
Description: This is a digitally signed message part


[cp-patches] FYI: java.util.Locale - fix broken serialization and equals()

2006-08-12 Thread Sven de Marothy
This is a major embarassment. 

2006-08-13  Sven de Marothy  <[EMAIL PROTECTED]>

* java/util/Locale.java
(hashcode): Is a serialized field, not transient.
(equals): Should NOT compare strings by reference.
(readObject/writeObject): Use the default methods and handle the hash
seperately.


Index: java/util/Locale.java
===
RCS file: /sources/classpath/classpath/java/util/Locale.java,v
retrieving revision 1.33
diff -U3 -r1.33 Locale.java
--- java/util/Locale.java	20 Apr 2006 09:29:27 -	1.33
+++ java/util/Locale.java	13 Aug 2006 00:17:42 -
@@ -192,7 +192,7 @@
*
* @serial should be -1 in serial streams
*/
-  private transient int hashcode;
+  private int hashcode;
 
   /**
* Array storing all available locales.
@@ -917,9 +917,9 @@
   return false;
 Locale l = (Locale) obj;
 
-return (language == l.language
-&& country == l.country
-&& variant == l.variant);
+return (language.equals( l.language )
+&& country.equals( l.country )
+&& variant.equals( l.variant ) );
   }
 
   /**
@@ -935,11 +935,11 @@
   private void writeObject(ObjectOutputStream s)
 throws IOException
   {
-s.writeObject(language);
-s.writeObject(country);
-s.writeObject(variant);
 // Hashcode field is always written as -1.
-s.writeInt(-1);
+int temp = hashcode;
+hashcode = -1;
+s.defaultWriteObject();
+hashcode = temp;
   }
 
   /**
@@ -953,9 +953,7 @@
   private void readObject(ObjectInputStream s)
 throws IOException, ClassNotFoundException
   {
-language = ((String) s.readObject()).intern();
-country = ((String) s.readObject()).intern();
-variant = ((String) s.readObject()).intern();
+s.defaultReadObject();
 // Recompute hashcode.
 hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
   }