- Rami Jaamour, Software Development Manager
Recently I wrote some SOAtest code which relates to Parasoft SOAtest's Stub Server functionality. One of the private fields in the class I wrote was a "provider" field, which can be used to manufacture WebSphere, TIBCO or other vendor specific connections. That "provider" field was never initialized, so the code would take the route of using a generic connection.
public class JMSReporter {
...
private JMSProvider provider = null;
private Connection connection;
public JMSReporter(ReportingConfiguration reportingConfig) {
init();
}
public init() {
...
if (provider == null) {
connectionFactory = getGenericConnectionFactory(...);
} else {
// this code never executes
connectionFactory = provider.getConnectionFactory(...);
}
connection = connectionFactory.createConnection(...);
...
}
}
Functionally speaking, everything seems fine when you test it. However, in reality this code has not been using the right connection type, which is a defect that could manifest itself in certain heterogeneous contexts that are different from our test environments. I cannot test my functionality under all possible environmental configurations, so this problem could have gone unnoticed, but luckily a static analysis rule came to the rescue and helped me expose the bug in my code.
The Parasoft Jtest rule "Avoid using 'private' fields which are never given a meaningful value" is just awesome! This rule detects "private" fields which are used but which are never set to a meaningful value. For example, the code might have null checks whenever the field is used but the field is never set to a none null value, or if the code has a collection object (array, vector, etc.) that is instantiated but items are never added to it. In my case the rule helped me fix my code by initializing my provider field in the constructor and prevent a bug from creeping into the release:
public class JMSReporter {
...
private JMSProvider provider = null;
private Connection connection;
public JMSReporter(ReportingConfiguration reportingConfig) {
provider = reportingConfig.getProvider
init();
}
public init() {
...
if (provider == null) {
connectionFactory = getGenericConnectionFactory(...);
} else {
// this code never executes
connectionFactory = provider.getConnectionFactory(...);
}
connection = connectionFactory.createConnection(...);
...
}
}
Learn how Parasoft helps developers do static analysis, and more.
Wednesday, May 26, 2010
Monday, May 3, 2010
Static code analysis prevents entire classes of errors
- Nathan Jakubiak, Software Development Manager
Recently we found a bug in our software that resulted in a null variable being dereferenced and throwing an exception. We have static analysis rules enabled, so we wondered why they did not catch the problem.
We discovered that there was a rule in Jtest that could have found the problem - "Avoid using "private" fields which are never given a meaningful value" - and flag if those variables ever got dereferenced. So we turned the rule on. This rule was in a Jtest category called Possible Bugs, so we combed through that category looking for other Serverity 1 rules that we possibly should have turned on.
We found and enabled the high severity rule "Do not call 'equals()' methods that always return false", which turned up a number of bugs!
In our code we have calls that look like Logger.getlogger().error("some error message"). In some cases a developer had accidentally used the equals() method insead of the error() method. The resulting code compiled fine, but did not do the logging that was intended. Jtest found this problem since the equals() method was passing a String to the equals() method of a Logger object - and this would always return false.
In this process we also turned on the rule "Avoid calling 'equals()' with same object", which also found us a bug! This bug was in the equals() method of an object called XMLAssertionTool, and could cause the method to consider two instances of XMLAssertionTool equal even if their message field had a different value, as shown below:
public boolean equals(Object obj) {
if (!(obj instanceof XMLAssertionTool)) {
return false;
}
XMLAssertionTool other = (XMLAssertionTool)obj;
return assertions.equals(other.assertions) &&
message.equals(message) && toolEquals(obj);
// The problem is: "message.equals(message)"
}
Learn how Parasoft helps developers do static analysis, and more.
Recently we found a bug in our software that resulted in a null variable being dereferenced and throwing an exception. We have static analysis rules enabled, so we wondered why they did not catch the problem.
We discovered that there was a rule in Jtest that could have found the problem - "Avoid using "private" fields which are never given a meaningful value" - and flag if those variables ever got dereferenced. So we turned the rule on. This rule was in a Jtest category called Possible Bugs, so we combed through that category looking for other Serverity 1 rules that we possibly should have turned on.
We found and enabled the high severity rule "Do not call 'equals()' methods that always return false", which turned up a number of bugs!
In our code we have calls that look like Logger.getlogger().error("some error message"). In some cases a developer had accidentally used the equals() method insead of the error() method. The resulting code compiled fine, but did not do the logging that was intended. Jtest found this problem since the equals() method was passing a String to the equals() method of a Logger object - and this would always return false.
In this process we also turned on the rule "Avoid calling 'equals()' with same object", which also found us a bug! This bug was in the equals() method of an object called XMLAssertionTool, and could cause the method to consider two instances of XMLAssertionTool equal even if their message field had a different value, as shown below:
public boolean equals(Object obj) {
if (!(obj instanceof XMLAssertionTool)) {
return false;
}
XMLAssertionTool other = (XMLAssertionTool)obj;
return assertions.equals(other.assertions) &&
message.equals(message) && toolEquals(obj);
// The problem is: "message.equals(message)"
}
Learn how Parasoft helps developers do static analysis, and more.
Friday, April 30, 2010
Static analysis reveals functional error
- Matt Love, Software Development Manager
I'd like to share an interesting discovery that Parasoft's own Jtest development team made recently: a static analysis rule for optimization actually alerted us to a serious defect
We wanted to optimize our code base before the next release, so we extended our usual static analysis configuration to include several optimization rules. One rule (OPT.LIOL) recommended moving aResults[0] outside and above the loop as an optimization for the following Java code:
for (int i = 0; I < aResults.length; i++) {
ICodingStandardsCoverageInfo coverageInfo =
(ICodingStandardsCoverageInfo)aResults[0];
updateStatistics(coverageInfo);
}
Blindly following the rule would indeed optimize this code. But a closer look at this code revealed that using array index 0 for every loop iteration was a mistake and a functional error.
The same defect pattern also exists in other languages with loop constructs, and it may be detected with rules in Parasoft C++test (for C and C++) and Parasoft .TEST (for .NET code - including C#, VB.NET, ASP.NET and Managed C++).
I'd like to share an interesting discovery that Parasoft's own Jtest development team made recently: a static analysis rule for optimization actually alerted us to a serious defect
We wanted to optimize our code base before the next release, so we extended our usual static analysis configuration to include several optimization rules. One rule (OPT.LIOL) recommended moving aResults[0] outside and above the loop as an optimization for the following Java code:
for (int i = 0; I < aResults.length; i++) {
ICodingStandardsCoverageInfo coverageInfo =
(ICodingStandardsCoverageInfo)aResults[0];
updateStatistics(coverageInfo);
}
Blindly following the rule would indeed optimize this code. But a closer look at this code revealed that using array index 0 for every loop iteration was a mistake and a functional error.
The same defect pattern also exists in other languages with loop constructs, and it may be detected with rules in Parasoft C++test (for C and C++) and Parasoft .TEST (for .NET code - including C#, VB.NET, ASP.NET and Managed C++).
Subscribe to:
Comments (Atom)
