This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: Patch: serialization fixes


Hi list,


I just commited the attached patch to fix serialization issues by 
Guilhem Lavaux.


Michael


2004-02-28  Guilhem Lavaux <guilhem@kaffe.org>

	* java/io/ObjectInputStream.java
	(readClassDescriptor): Keep elements of the mapping non null.
	(checkTypeConsistency): New method.
	(readFields): Fixed main loop and base logic. Small reindentation.
	* java/io/ObjectStreamField.java
	(lookupField): New method to update the field reference.
	(checkFieldType): New method.
	* java/io/ObjectStreamClass.java
	(setClass, setFields): Call lookupField when building the field
	database. Check the real field type.

Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.28
diff -u -b -B -r1.28 ObjectInputStream.java
--- java/io/ObjectInputStream.java	15 Feb 2004 11:53:45 -0000	1.28
+++ java/io/ObjectInputStream.java	28 Feb 2004 21:28:16 -0000
@@ -1,6 +1,5 @@
 /* ObjectInputStream.java -- Class used to read serialized objects
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -413,6 +412,64 @@
   }
 
   /**
+   * This method makes a partial check of types for the fields
+   * contained given in arguments. It checks primitive types of
+   * fields1 against non primitive types of fields2. This method 
+   * assumes the two lists has already been sorted according to 
+   * the Java specification.
+   *
+   * @param name Name of the class owning the given fields.
+   * @param fields1 First list to check.
+   * @param fields2 Second list to check.
+   * @throws InvalidClassException if a field in fields1, which has a primitive type, is a present
+   * in the non primitive part in fields2.
+   */
+  private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
+    throws InvalidClassException
+    int nonPrimitive = 0;
+    
+    for (nonPrimitive = 0; 
+	 nonPrimitive < fields1.length
+	   && fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
+      {
+      }
+
+    if (nonPrimitive == fields1.length)
+      return;
+    
+    int i = 0;
+    ObjectStreamField f1;
+    ObjectStreamField f2;
+    
+    while (i < fields2.length
+	   && nonPrimitive < fields1.length)
+      {
+	f1 = fields1[nonPrimitive];
+	f2 = fields2[i];
+	
+	if (!f2.isPrimitive())
+	  break;
+
+	int compVal = f1.getName().compareTo (f2.getName());
+
+	if (compVal < 0)
+	  {
+	    nonPrimitive++;
+	  }
+	else if (compVal > 0)
+	  {
+	    i++;
+	  }
+	else
+	  {
+	    throw new InvalidClassException
+	      ("invalid field type for " + f2.getName() +
+	       " in class " + name);
+	  }
+      }
+  }
+
+  /**
    * This method reads a class descriptor from the real input stream
    * and use these data to create a new instance of ObjectStreamClass.
    * Fields are sorted and ordered for the real read which occurs for
@@ -497,6 +554,15 @@
     int real_idx = 0;
     int map_idx = 0;
 
+    /*
+     * Check that there is no type inconsistencies between the lists.
+     * A special checking must be done for the two groups: primitive types and
+     * not primitive types. 
+     */
+    checkTypeConsistency(name, real_fields, stream_fields);
+    checkTypeConsistency(name, stream_fields, real_fields);
+
+    
     while (stream_idx < stream_fields.length
 	   || real_idx < real_fields.length)
       {
@@ -528,21 +594,13 @@
 	      {
 		stream_field = stream_fields[stream_idx++];
 		real_field = real_fields[real_idx++];
-		if(stream_field.getType() != real_field.getType())
+		if (stream_field.getType() != real_field.getType())
 		    throw new InvalidClassException
 			("invalid field type for " + real_field.getName() +
 			" in class " + name);
 	      }
 	  }
-	if (stream_field != null)
-	  {
-	    if (stream_field.getOffset() < 0)
-		stream_field = null;
-	    else if (!stream_field.isToSet())
-		real_field = null;
-	  }
-	if (real_field != null && !real_field.isToSet())
-	    real_field = null;
+
 	/* If some of stream_fields does not correspond to any of real_fields,
 	 * or the opposite, then fieldmapping will go short.
 	 */
@@ -1577,12 +1635,11 @@
       {
 	ObjectStreamField stream_field = fields[i];
 	ObjectStreamField real_field = fields[i + 1];
-	if(stream_field != null || real_field != null)
-	  {
-	    boolean read_value = stream_field != null;
-	    boolean set_value = real_field != null;
+	boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
+	boolean set_value = (real_field != null && real_field.isToSet());
 	    String field_name;
 	    char type;
+
 	    if (stream_field != null)
 	      {
 		field_name = stream_field.getName();
@@ -1690,7 +1747,6 @@
 	      }
 	  }
       }
-  }
 
   // Toggles writing primitive data to block-data buffer.
   private boolean setBlockDataMode (boolean on)
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.19
diff -u -b -B -r1.19 ObjectStreamClass.java
--- java/io/ObjectStreamClass.java	6 Feb 2004 13:27:36 -0000	1.19
+++ java/io/ObjectStreamClass.java	28 Feb 2004 21:28:16 -0000
@@ -327,7 +327,7 @@
 	i = 0; j = 0; k = 0;
 	while (i < fields.length && j < exportedFields.length)
 	  {
-	    int comp = fields[i].getName().compareTo(exportedFields[j].getName());
+	    int comp = fields[i].compareTo(exportedFields[j]);
 
 	    if (comp < 0)
 	      {
@@ -344,10 +344,27 @@
 		newFieldList[k] = exportedFields[j];
 		newFieldList[k].setPersistent(true);
 		newFieldList[k].setToSet(false);
+		try
+		  {
+		    newFieldList[k].lookupField(clazz);
+		    newFieldList[k].checkFieldType();
+		  }
+		catch (NoSuchFieldException _)
+		  {
+		  }
 		j++;
 	      }
 	    else
 	      {
+		try
+		  {
+		    exportedFields[j].lookupField(clazz);
+		    exportedFields[j].checkFieldType();
+		  }
+		catch (NoSuchFieldException _)
+		  {
+		  }
+
 		if (!fields[i].getType().equals(exportedFields[j].getType()))
 		  throw new InvalidClassException
 		    ("serialPersistentFields must be compatible with" +
@@ -554,6 +571,19 @@
 	    if (fields != null)
 	      {
 		Arrays.sort (fields);
+		// Retrieve field reference.
+		for (int i=0; i < fields.length; i++)
+		  {
+		    try
+		      {
+			fields[i].lookupField(cl);
+		      }
+		    catch (NoSuchFieldException _)
+		      {
+			fields[i].setToSet(false);
+		      }
+		  }
+		
 		calculateOffsets();
 		return;
 	      }
Index: java/io/ObjectStreamField.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamField.java,v
retrieving revision 1.8
diff -u -b -B -r1.8 ObjectStreamField.java
--- java/io/ObjectStreamField.java	6 Feb 2004 13:27:36 -0000	1.8
+++ java/io/ObjectStreamField.java	28 Feb 2004 21:28:16 -0000
@@ -41,6 +41,8 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import gnu.java.lang.reflect.TypeSignature;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
  * This class intends to describe the field of a class for the serialization
@@ -99,7 +101,7 @@
  
   /**
    * There are many cases you can not get java.lang.Class from typename 
-   * if your context class loader cann not load it, then use typename to
+   * if your context class loader cannot load it, then use typename to
    * construct the field.
    *
    * @param name Name of the field to export.
@@ -292,7 +294,7 @@
   }
 
   /**
-   * This methods returns true if the field is marked as to be
+   * This method returns true if the field is marked as to be
    * set.
    *
    * @return True if it is to be set, false in the other cases.
@@ -303,6 +305,49 @@
     return toset;
   }
 
+  /**
+   * This method searches for its field reference in the specified class
+   * object. It requests privileges. If an error occurs the internal field
+   * reference is not modified.
+   *
+   * @throws NoSuchFieldException if the field name does not exist in this class.
+   * @throws SecurityException if there was an error requesting the privileges.
+   */
+  void lookupField(Class clazz) throws NoSuchFieldException, SecurityException
+  {
+    final Field f = clazz.getDeclaredField(name);
+    
+    AccessController.doPrivileged(new PrivilegedAction()
+      {
+	public Object run()
+	{
+	  f.setAccessible(true);
+	  return null;
+	}
+      });
+    
+    this.field = f;
+  }
+
+  /**
+   * This method check whether the field described by this
+   * instance of ObjectStreamField is compatible with the
+   * actual implementation of this field.
+   *
+   * @throws NullPointerException if this field does not exist
+   * in the real class.
+   * @throws InvalidClassException if the types are incompatible.
+   */
+  void checkFieldType() throws InvalidClassException
+  {
+    Class ftype = field.getType();
+
+    if (!ftype.isAssignableFrom(type))
+      throw new InvalidClassException
+	("invalid field type for " + name +
+	 " in class " + field.getDeclaringClass());
+  }
+
   public String toString ()
   {
     return "ObjectStreamField< " + type + " " + name + " >";

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]