128 lines
4.6 KiB
Plaintext
128 lines
4.6 KiB
Plaintext
This rule raises an issue on a non-transient and non-serializable field within a serializable class, if said class does not have `writeObject` and `readObject` methods defined.
|
|
|
|
== Why is this an issue?
|
|
|
|
By contract, fields in a `Serializable` class must themselves be either `Serializable` or `transient`.
|
|
Even if the class is never explicitly serialized or deserialized, it is not safe to assume that this cannot happen.
|
|
For instance, under load, most J2EE application frameworks flush objects to disk.
|
|
|
|
An object that implements `Serializable` but contains non-transient, non-serializable data members (and thus violates the contract) could cause application crashes and open the door to attackers.
|
|
In general, a `Serializable` class is expected to fulfil its contract and not exhibit unexpected behaviour when an instance is serialized.
|
|
|
|
This rule raises an issue on:
|
|
|
|
* non-`Serializable` fields,
|
|
* collection fields when they are not `private` (because they could be assigned non-`Serializable` values externally),
|
|
* when a field is assigned a non-`Serializable` type within the class.
|
|
|
|
== How to fix it
|
|
|
|
Consider the following scenario.
|
|
|
|
[source,java,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
public class Address {
|
|
...
|
|
}
|
|
|
|
public class Person implements Serializable {
|
|
private static final long serialVersionUID = 1905122041950251207L;
|
|
|
|
private String name;
|
|
private Address address; // Noncompliant, Address is not serializable
|
|
}
|
|
----
|
|
|
|
How to fix this issue depends on the application's needs. If the field's value should be preserved during serialization and deserialization, you may want to make the field's value serializable.
|
|
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
public class Address implements Serializable {
|
|
private static final long serialVersionUID = 2405172041950251807L;
|
|
|
|
...
|
|
}
|
|
|
|
public class Person implements Serializable {
|
|
private static final long serialVersionUID = 1905122041950251207L;
|
|
|
|
private String name;
|
|
private Address address; // Compliant, Address is serializable
|
|
}
|
|
----
|
|
|
|
If the field's value does not need to be preserved during serialization and deserialization, mark it as `transient`. The field will be ignored when the object is serialized. After deserialization, the field will be set to the default value corresponding to its type (e.g., `null` for object references).
|
|
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
public class Address {
|
|
...
|
|
}
|
|
|
|
public class Person implements Serializable {
|
|
private static final long serialVersionUID = 1905122041950251207L;
|
|
|
|
private String name;
|
|
private transient Address address; // Compliant, the field is transient
|
|
}
|
|
----
|
|
|
|
The alternative to making all members serializable or `transient` is to implement special methods which take on the responsibility of properly serializing and de-serializing the object `writeObject` and `readObject`. These methods can be used to properly (de-)serialize an object, even though it contains fields that are not transient or serializable. Hence, this rule does not raise issues on fields of classes which implement these methods.
|
|
|
|
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
public class Address {
|
|
...
|
|
}
|
|
|
|
public class Person implements Serializable {
|
|
private static final long serialVersionUID = 1905122041950251207L;
|
|
|
|
private String name;
|
|
private Address address; // Compliant, writeObject and readObject handle this field
|
|
|
|
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
|
// Appropriate serialization logic here
|
|
}
|
|
|
|
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
|
// Appropriate deserialization logic here
|
|
}
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
* https://cwe.mitre.org/data/definitions/594[Saving Unserializable Objects to Disk - MITRE, CWE-594]
|
|
* https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html[Interface Serializable - Java SE 11 API Documentation]
|
|
* https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html[Interface Serializable - Java SE 17 API Documentation]
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Make "xxx" transient or serializable.
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== is duplicated by: S2058
|
|
|
|
=== on 21 Dec 2016, 14:16:57 Tibor Blenessy wrote:
|
|
There is a limitation to the rule discussed in
|
|
|
|
https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/sonarqube/ofykNf_8tso/mvwWvM6JBAAJ
|
|
|
|
|
|
The pattern of throwing NotSerializableException is described here \http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
|
|
|
|
endif::env-github,rspecator-view[]
|