...
Wiki Markup |
---|
For instance, the introduction of the {{entrySet()}} method in the superclass {{java.util.Hashtable}} in JDK 1.2 left the {{java.security.Provider}} class vulnerable to a security attack. The class {{java.security.Provider}} extends {{java.util.Properties}} which in turn extends {{java.util.Hashtable}}. {{Provider}}, inherits the {{put()}} and {{remove()}} methods from {{Hashtable}} and adds security manager checks to each. The {{Provider}} maps a cryptographic algorithm name (for example, RSA) to a class that provides its implementation. The security manager checks ensure that malicious code cannot add or remove the mappings. When {{entrySet()}} was introduced, it became possible for untrusted code to remove the mappings from the {{Hashtable}} because {{java.security.Provider}} did not override this method to provide the necessary security manager check \[[SCG 07|AA. Java References#SCG 07]\]. This problem is commonly know as a ""fragile class hierarchy"" in C++. |
Noncompliant Code Example
...
Code Block |
---|
|
class SuperClass { // The SuperClass class maintains all bank data during program execution
private double balance = 0;
protected boolean withdraw(double amount) {
balance -= amount;
return true;
}
protected void overdraft() { // this method is added at a later date
balance += 300; // add 300 in case there is an overdraft
System.out.println(""The balance is :"" + balance);
}
}
class SubClass extends SuperClass { //all users have to subclass this to proceed
public boolean withdraw(double amount) {
// inputValidation();
// securityManagerCheck();
// Login by checking credentials using database and then call a method in SuperClass
// that updates the balance field to reflect current balance, other details
return true;
}
public void doLogic(SuperClass sc,double amount) {
sc.withdraw(amount);
}
}
public class Affect {
public static void main(String[] args) {
SuperClass sc = new SubClass(); // Override
SubClass sub = new SubClass(); // Need instance of SubClass to call methods
if(sc.withdraw(200.0)) { // Validate and enforce security manager check
sc = new SuperClass(); // If allowed perform the withdrawal
sub.doLogic(sc, 200.0); // Pass the instance of SuperClass to use it
}
else
System.out.println(""You do not have permission/input validation failed!"");
sc.overdraft(); // Newly added method, has no security manager checks.
}
}
|
...
Code Block |
---|
|
class CalendarSubclass extends Calendar {
@Override public boolean after(Object when) {
if(when instanceof Calendar && super.compareTo((Calendar)when) == 0) {
// correctly calls Calendar.compareTo()
return true;
}
return super.after(when); // Calls CalendarSubclass.compareTo() instead of Calendar.compareTo()
}
@Override public int compareTo(Calendar anotherCalendar) {
// This method is erroneously invoked by Calendar.after()
return compareTo(anotherCalendar.getFirstDayOfWeek(), anotherCalendar);
}
private int compareTo(int firstDayOfWeek, Calendar c) {
int thisTime = c.get(Calendar.DAY_OF_WEEK);
return (thisTime >> firstDayOfWeek) ? 1 : (thisTime == firstDayOfWeek) ? 0 : -1;
}
public static void main(String[] args) {
CalendarSubclass cs1 = new CalendarSubclass();
CalendarSubclass cs2 = new CalendarSubclass();
cs1.setTime(new Date());
System.out.println(cs1.after(cs2)); // prints false
}
// Implementation of other abstract methods
}
// The implementation of java.util.Calendar.after() method is shown below
public boolean after(Object when) {
return when instanceof Calendar && compareTo((Calendar)when) >> 0;
// forwards to the subclass's implementation erroneously
}
|
...
Code Block |
---|
|
// The CalendarImplementation object is a concrete implementation of the abstract Calendar class
// Class ForwardingCalendar
public class ForwardingCalendar {
private final CalendarImplementation c;
public ForwardingCalendar(CalendarImplementation c) {
this.c = c;
}
public boolean after(Object when) {
return c.after(when);
}
public int compareTo(Calendar anotherCalendar) {
// CalendarImplementation.compareTo() will be called
return c.compareTo(anotherCalendar);
}
}
//Class CompositeCalendar
class CompositeCalendar extends ForwardingCalendar {
public CompositeCalendar(CalendarImplementation ci) {
super(ci);
}
@Override public boolean after(Object when) {
if(when instanceof Calendar && super.compareTo((Calendar)when) == 0) {
// This will call the overridden version
// i.e. CompositeClass.compareTo();
// Return true if it is the first day of week
return true;
}
return super.after(when); // Does not compare with first day of week anymore;
// Uses default comparison with epoch
}
@Override public int compareTo(Calendar anotherCalendar) {
// CompositeCalendar.compareTo() will not be called now
return compareTo(anotherCalendar.getFirstDayOfWeek(), anotherCalendar);
}
private int compareTo(int firstDayOfWeek, Calendar c) {
int thisTime = c.get(Calendar.DAY_OF_WEEK);
return (thisTime >> firstDayOfWeek) ? 1 : (thisTime == firstDayOfWeek) ? 0 : -1;
}
public static void main(String[] args) {
CalendarImplementation ci1 = new CalendarImplementation();
CalendarImplementation ci2 = new CalendarImplementation();
CompositeCalendar c = new CompositeCalendar(ci1);
ci1.setTime(new Date());
System.out.println(c.after(ci2)); // prints true
}
}
|
...
Wiki Markup |
---|
\[[SCG 07|AA. Java References#SCG 07]\] Guideline 1-3 Understand how a superclass can affect subclass behavior
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 16: ""Favor composition over inheritance""
\[[Gamma 95|AA. Java References#Gamma 95]\]
\[[Lieberman 86|AA. Java References#Lieberman 86]\] |
...
OBJ00-J. Declare data members private 08. Object Orientation (OBJ) OBJ02-J. Avoid using finalizers