Commit 646e3290 by Guilhem Lavaux Committed by Michael Koch

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.

From-SVN: r78627
parent ca67f278
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.
2004-02-28 Michael Koch <konqueror@gmx.de> 2004-02-28 Michael Koch <konqueror@gmx.de>
* java/nio/ByteOrder.java * java/nio/ByteOrder.java
......
/* ObjectInputStream.java -- Class used to read serialized objects /* ObjectInputStream.java -- Class used to read serialized objects
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
...@@ -413,6 +412,64 @@ public class ObjectInputStream extends InputStream ...@@ -413,6 +412,64 @@ public class ObjectInputStream extends InputStream
} }
/** /**
* 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 * This method reads a class descriptor from the real input stream
* and use these data to create a new instance of ObjectStreamClass. * and use these data to create a new instance of ObjectStreamClass.
* Fields are sorted and ordered for the real read which occurs for * Fields are sorted and ordered for the real read which occurs for
...@@ -497,6 +554,15 @@ public class ObjectInputStream extends InputStream ...@@ -497,6 +554,15 @@ public class ObjectInputStream extends InputStream
int real_idx = 0; int real_idx = 0;
int map_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 while (stream_idx < stream_fields.length
|| real_idx < real_fields.length) || real_idx < real_fields.length)
{ {
...@@ -514,7 +580,7 @@ public class ObjectInputStream extends InputStream ...@@ -514,7 +580,7 @@ public class ObjectInputStream extends InputStream
else else
{ {
int comp_val = int comp_val =
real_fields[real_idx].compareTo (stream_fields[stream_idx]); real_fields[real_idx].compareTo (stream_fields[stream_idx]);
if (comp_val < 0) if (comp_val < 0)
{ {
...@@ -528,21 +594,13 @@ public class ObjectInputStream extends InputStream ...@@ -528,21 +594,13 @@ public class ObjectInputStream extends InputStream
{ {
stream_field = stream_fields[stream_idx++]; stream_field = stream_fields[stream_idx++];
real_field = real_fields[real_idx++]; real_field = real_fields[real_idx++];
if(stream_field.getType() != real_field.getType()) if (stream_field.getType() != real_field.getType())
throw new InvalidClassException throw new InvalidClassException
("invalid field type for " + real_field.getName() + ("invalid field type for " + real_field.getName() +
" in class " + name); " 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, /* If some of stream_fields does not correspond to any of real_fields,
* or the opposite, then fieldmapping will go short. * or the opposite, then fieldmapping will go short.
*/ */
...@@ -551,7 +609,7 @@ public class ObjectInputStream extends InputStream ...@@ -551,7 +609,7 @@ public class ObjectInputStream extends InputStream
ObjectStreamField[] newfieldmapping = ObjectStreamField[] newfieldmapping =
new ObjectStreamField[fieldmapping.length + 2]; new ObjectStreamField[fieldmapping.length + 2];
System.arraycopy(fieldmapping, 0, System.arraycopy(fieldmapping, 0,
newfieldmapping, 0, fieldmapping.length); newfieldmapping, 0, fieldmapping.length);
fieldmapping = newfieldmapping; fieldmapping = newfieldmapping;
} }
fieldmapping[map_idx++] = stream_field; fieldmapping[map_idx++] = stream_field;
...@@ -1577,121 +1635,119 @@ public class ObjectInputStream extends InputStream ...@@ -1577,121 +1635,119 @@ public class ObjectInputStream extends InputStream
{ {
ObjectStreamField stream_field = fields[i]; ObjectStreamField stream_field = fields[i];
ObjectStreamField real_field = fields[i + 1]; ObjectStreamField real_field = fields[i + 1];
if(stream_field != null || 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());
boolean read_value = stream_field != null; String field_name;
boolean set_value = real_field != null; char type;
String field_name;
char type;
if (stream_field != null)
{
field_name = stream_field.getName();
type = stream_field.getTypeCode();
}
else
{
field_name = real_field.getName();
type = real_field.getTypeCode();
}
switch(type) if (stream_field != null)
{ {
case 'Z': field_name = stream_field.getName();
{ type = stream_field.getTypeCode();
boolean value = }
read_value ? this.realInputStream.readBoolean() : false; else
if (dump && read_value && set_value) {
dumpElementln(" " + field_name + ": " + value); field_name = real_field.getName();
if (set_value) type = real_field.getTypeCode();
real_field.setBooleanField(obj, value); }
break;
} switch(type)
case 'B': {
{ case 'Z':
byte value = {
read_value ? this.realInputStream.readByte() : 0; boolean value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readBoolean() : false;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setByteField(obj, value); if (set_value)
break; real_field.setBooleanField(obj, value);
} break;
case 'C': }
{ case 'B':
char value = {
read_value ? this.realInputStream.readChar(): 0; byte value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readByte() : 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setCharField(obj, value); if (set_value)
break; real_field.setByteField(obj, value);
} break;
case 'D': }
{ case 'C':
double value = {
read_value ? this.realInputStream.readDouble() : 0; char value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readChar(): 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setDoubleField(obj, value); if (set_value)
break; real_field.setCharField(obj, value);
} break;
case 'F': }
{ case 'D':
float value = {
read_value ? this.realInputStream.readFloat() : 0; double value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readDouble() : 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setFloatField(obj, value); if (set_value)
break; real_field.setDoubleField(obj, value);
} break;
case 'I': }
{ case 'F':
int value = {
read_value ? this.realInputStream.readInt() : 0; float value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readFloat() : 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setIntField(obj, value); if (set_value)
break; real_field.setFloatField(obj, value);
} break;
case 'J': }
{ case 'I':
long value = {
read_value ? this.realInputStream.readLong() : 0; int value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readInt() : 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setLongField(obj, value); if (set_value)
break; real_field.setIntField(obj, value);
} break;
case 'S': }
{ case 'J':
short value = {
read_value ? this.realInputStream.readShort() : 0; long value =
if (dump && read_value && set_value) read_value ? this.realInputStream.readLong() : 0;
dumpElementln(" " + field_name + ": " + value); if (dump && read_value && set_value)
if (set_value) dumpElementln(" " + field_name + ": " + value);
real_field.setShortField(obj, value); if (set_value)
break; real_field.setLongField(obj, value);
} break;
case 'L': }
case '[': case 'S':
{ {
Object value = short value =
read_value ? readObject() : null; read_value ? this.realInputStream.readShort() : 0;
if (set_value) if (dump && read_value && set_value)
real_field.setObjectField(obj, value); dumpElementln(" " + field_name + ": " + value);
break; if (set_value)
} real_field.setShortField(obj, value);
default: break;
throw new InternalError("Invalid type code: " + type); }
} case 'L':
case '[':
{
Object value =
read_value ? readObject() : null;
if (set_value)
real_field.setObjectField(obj, value);
break;
}
default:
throw new InternalError("Invalid type code: " + type);
} }
} }
} }
// Toggles writing primitive data to block-data buffer. // Toggles writing primitive data to block-data buffer.
private boolean setBlockDataMode (boolean on) private boolean setBlockDataMode (boolean on)
{ {
......
...@@ -327,7 +327,7 @@ public class ObjectStreamClass implements Serializable ...@@ -327,7 +327,7 @@ public class ObjectStreamClass implements Serializable
i = 0; j = 0; k = 0; i = 0; j = 0; k = 0;
while (i < fields.length && j < exportedFields.length) 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) if (comp < 0)
{ {
...@@ -344,10 +344,27 @@ public class ObjectStreamClass implements Serializable ...@@ -344,10 +344,27 @@ public class ObjectStreamClass implements Serializable
newFieldList[k] = exportedFields[j]; newFieldList[k] = exportedFields[j];
newFieldList[k].setPersistent(true); newFieldList[k].setPersistent(true);
newFieldList[k].setToSet(false); newFieldList[k].setToSet(false);
try
{
newFieldList[k].lookupField(clazz);
newFieldList[k].checkFieldType();
}
catch (NoSuchFieldException _)
{
}
j++; j++;
} }
else else
{ {
try
{
exportedFields[j].lookupField(clazz);
exportedFields[j].checkFieldType();
}
catch (NoSuchFieldException _)
{
}
if (!fields[i].getType().equals(exportedFields[j].getType())) if (!fields[i].getType().equals(exportedFields[j].getType()))
throw new InvalidClassException throw new InvalidClassException
("serialPersistentFields must be compatible with" + ("serialPersistentFields must be compatible with" +
...@@ -554,6 +571,19 @@ outer: ...@@ -554,6 +571,19 @@ outer:
if (fields != null) if (fields != null)
{ {
Arrays.sort (fields); 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(); calculateOffsets();
return; return;
} }
...@@ -798,7 +828,7 @@ outer: ...@@ -798,7 +828,7 @@ outer:
fieldsArray = new ObjectStreamField[ o.length ]; fieldsArray = new ObjectStreamField[ o.length ];
System.arraycopy(o, 0, fieldsArray, 0, o.length); System.arraycopy(o, 0, fieldsArray, 0, o.length);
return fieldsArray; return fieldsArray;
} }
......
...@@ -41,6 +41,8 @@ package java.io; ...@@ -41,6 +41,8 @@ package java.io;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import gnu.java.lang.reflect.TypeSignature; 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 * This class intends to describe the field of a class for the serialization
...@@ -99,7 +101,7 @@ public class ObjectStreamField implements Comparable ...@@ -99,7 +101,7 @@ public class ObjectStreamField implements Comparable
/** /**
* There are many cases you can not get java.lang.Class from typename * 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. * construct the field.
* *
* @param name Name of the field to export. * @param name Name of the field to export.
...@@ -292,7 +294,7 @@ public class ObjectStreamField implements Comparable ...@@ -292,7 +294,7 @@ public class ObjectStreamField implements Comparable
} }
/** /**
* 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. * set.
* *
* @return True if it is to be set, false in the other cases. * @return True if it is to be set, false in the other cases.
...@@ -303,6 +305,49 @@ public class ObjectStreamField implements Comparable ...@@ -303,6 +305,49 @@ public class ObjectStreamField implements Comparable
return toset; 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 () public String toString ()
{ {
return "ObjectStreamField< " + type + " " + name + " >"; return "ObjectStreamField< " + type + " " + name + " >";
...@@ -310,102 +355,102 @@ public class ObjectStreamField implements Comparable ...@@ -310,102 +355,102 @@ public class ObjectStreamField implements Comparable
final void setBooleanField(Object obj, boolean val) final void setBooleanField(Object obj, boolean val)
{ {
try try
{ {
field.setBoolean(obj, val); field.setBoolean(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setByteField(Object obj, byte val) final void setByteField(Object obj, byte val)
{ {
try try
{ {
field.setByte(obj, val); field.setByte(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setCharField(Object obj, char val) final void setCharField(Object obj, char val)
{ {
try try
{ {
field.setChar(obj, val); field.setChar(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setShortField(Object obj, short val) final void setShortField(Object obj, short val)
{ {
try try
{ {
field.setShort(obj, val); field.setShort(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setIntField(Object obj, int val) final void setIntField(Object obj, int val)
{ {
try try
{ {
field.setInt(obj, val); field.setInt(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setLongField(Object obj, long val) final void setLongField(Object obj, long val)
{ {
try try
{ {
field.setLong(obj, val); field.setLong(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setFloatField(Object obj, float val) final void setFloatField(Object obj, float val)
{ {
try try
{ {
field.setFloat(obj, val); field.setFloat(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setDoubleField(Object obj, double val) final void setDoubleField(Object obj, double val)
{ {
try try
{ {
field.setDouble(obj, val); field.setDouble(obj, val);
} }
catch(IllegalAccessException x) catch(IllegalAccessException x)
{ {
throw new InternalError(x.getMessage()); throw new InternalError(x.getMessage());
} }
} }
final void setObjectField(Object obj, Object val) final void setObjectField(Object obj, Object val)
{ {
try try
{ {
field.set(obj, val); field.set(obj, val);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment