61

I have the following code in my dto class.

public void setBillDate(Date billDate) {
    this.billDate = billDate;
}

And I get an error in sonar stated as such and I'm not sure what I'm doing wrong here.

Malicious code vulnerability - May expose internal representation by incorporating reference to mutable object   

The class is a dto and the method is automatically created setter method. What am I doing wrong here. if anyone could explain. it would be a great help.

3
  • 1
    You could trying using this.billDate = new Date(billDate.getTime()); instead... Commented Sep 23, 2013 at 8:35
  • Is dto; data transfer object? Undefined acronyms can only lead to confusion Commented Sep 23, 2013 at 8:36
  • Sorry it's not a dto.. it's an entity class. sorry! Commented Sep 23, 2013 at 9:13

8 Answers 8

126

Date is mutable

Using that setter, someone can modify the date instance from outside unintentionally

Consider this

class MyClass {

   private Date billDate;


   public void setBillDate(Date billDate) {
      this.billDate = billDate;
   }

}

now some one can set it

MyClass m = new MyClass();

Date dateToBeSet = new Date();
m.setBillDate(dateToBeSet); //The actual dateToBeSet is set to m

dateToBeSet.setYear(...); 
//^^^^^^^^ Un-intentional modification to dateToBeSet, will also modify the m's billDate 

To avoid this, you may want to Deep-copy before setting

public void setBillDate(Date billDate) {
    this.billDate = new Date(billDate.getTime());
}
6
  • how can this be achieved if my instance variable was an Array of Dates ? can i use Arrays.copyOf ?
    – yathirigan
    Commented Nov 16, 2015 at 16:44
  • 2
    @yathirigan yes. Basically you need to do deep copy, so that outside modification doesn't affect the object held within this instance
    – sanbhat
    Commented Nov 17, 2015 at 9:02
  • thank you.. am confused looking at few articles that state that Arrays.copyOf does not do a deep copy. am doing some reading around it.
    – yathirigan
    Commented Nov 17, 2015 at 9:15
  • also is clone useful, eg. billDate.clone()
    – nikli
    Commented Oct 18, 2016 at 6:23
  • What if we write this.billDate = billDate.clone(); ? It is also the same
    – prem30488
    Commented May 23, 2017 at 6:38
51

I wonder why none of the solutions takes null into consideration. A general, null-safe solution should look like this:

public void setBillDate(Date billDate) {
    this.billDate = billDate != null ? new Date(billDate.getTime()) : null;
}
8
  • 4
    maybe because you should avoid using null values as it is considered by many as antipattern
    – Zavael
    Commented Feb 4, 2016 at 14:26
  • 2
    @Zavael The whole point of this is "you don't know what people outside the class are going to do with the values". You can't expect everyone to never pass you a null value.
    – Demonblack
    Commented Mar 17, 2016 at 15:32
  • @Demonblack I agree you can't excpect everyone to never pass a null, but you can "punish" them with appropriate exception :) if the caller does not have a value to set, he shouldn't call the method at all
    – Zavael
    Commented Mar 17, 2016 at 16:06
  • 1
    @Zavael Or, we can accept the Date to be a null instead of just punish them. Just like this answer.
    – Nier
    Commented Mar 31, 2016 at 7:12
  • 1
    @Zavael Most of time throw exception is a good choice. But recently I'm dealing with JPA with a nullable Date field in get / set functions. I need to consider the null case because it's legal to set / get a null Date.
    – Nier
    Commented Mar 31, 2016 at 7:36
6

A counter argument can be, why one would one unintentionally modify the date? If client sets the value and then modifies it, then our code should reflect it, isn't it? If not then is it not confusing?

I prefer to just ignore this FindBugs warning.

In case if you want to do that, just add following Maven dependencies in your pom.xml:

<!-- Findbugs -->
        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>annotations</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>annotations</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>jsr305</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

and then these annotations at class or member field level in your POJO:

@SuppressFBWarnings(value = { "EI_EXPOSE_REP", "EI_EXPOSE_REP2" }, justification = "I prefer to suppress these FindBugs warnings")

Cheers

Akshay

3

Date is mutable

and you are not creating a copy of Date that came in to you are parameter. So if the client code will change the value of the Date object, it will affect your class too.

Solution is to create a copy of Date

public setBillDate(Date billDate){
   this.billDate = new Date(billDate.getTime());
}
0
3

Consider using a clone as well. Don't forget null check.

public void setBillDate(Date billDate) {
    this.billDate = billDate == null ? null : billDate.clone();
}
2
3

In addition to the existing answers, I propose a new version based on Optional class from Java 8.

public void setBillDate(Date billDate) {
    this.billDate = Optional
            .ofNullable(billDate)
            .map(Date::getTime)
            .map(Date::new)
            .orElse(null);
}
0
1

Date is not immutable, i.e. your billDate can be changed after it has been set on your DTO object. Or, in code:

Date billDate = new Date();
dto.setBillDate(billDate);
billDate.setYear(1990);
// now, dto.getBillDate().getYear() == 1990

You can make your setter more secure:

public void setBillDate(Date billDate) {
    this.billDate = (Date)billDate.clone();
}
2
  • The default clone() will create shallow copy, so it might not fix the problem
    – sanbhat
    Commented Sep 23, 2013 at 8:41
  • In Oracle's JDK 7 it's overwritten to create a deep copy. But you're right, the API doc only says: 'Return a copy of this object.' - that does not fully explain the type of copy it creates.
    – isnot2bad
    Commented Sep 23, 2013 at 8:51
1

Top answer number 37 is not the correct answer : nobody cares about NullPointerExceptions???

You should try this instead :

public void setBillDate(Date billDate) {
    this.billDate = billDate == null ? billDate : new Date(billDate.getTime());
}
1
  • Null is already mentioned in this answer.
    – cfi
    Commented Sep 21, 2015 at 11:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.