Findbugs™ Warnings By Example - Database & Security


Facebook Twitter More...

By Markus Sprunck; Revision: 1.3; Status: final; Last Content Change: Apr 25, 2013;  


This article describes selected warnings of Findbugs with Java sample code. Here some database and security related warnings of FindBugs™ are in the center of attention. The following 5 warnings are covered in this article:

- DMI_CONSTANT_DB_PASSWORD (Security)
- DMI_EMPTY_DB_PASSWORD (Security)
- SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE (Security)
- OBL_UNSATISFIED_OBLIGATION (Experimental)
- OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE (Experimental)

Motivation for the 'Findbugs™ Warnings By Example' Series












Source: Wikipedia;  
GNU Lesser General 
Public License
The FindBugs™ bug descriptions of the online documentation are concise and well written. 

Unfortunately, some parts of the descriptions are not easy to understand (even for experienced Java developers). It can be difficult to understand the exact root cause for a warning and/or to find the correct way of fixing. 

To be honest - at least I had problems with some warnings in the last years. Quite often, I found no helping sample code in the web. The main weakness of the bug descriptions is, that it uses seldom sample code to demonstrate the wrong and correct situation. 

Example Code

Findbugs™ (Version 2.0.1-rc2) will show all warnings with the activated settings 'Security' and 'Experimental' of the Findbugs™ Eclipse Plugin (Version 2.0.1.20120511). See the following figure:


The code has been compiled with JDK 1.6.0_24 and with derby.jar (Version 10.9.1.0) in the build path.

package com.sw_engineering_candies;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class FindbugsWarningsByExample2 {

public static void main(final String[] args) {

// Prepare database
Statement createStatement = null;
Connection connection = null;
try {
System.out.println("Findbugs Sample prepare small in memory database");
connection = getConnection_dmiConstantDbPasswordCORRECT();
createStatement = connection.createStatement();
createStatement.execute("create table T_ADVICE (answer varchar(255), " + "owner varchar(255))");
createStatement.execute("insert into T_ADVICE ( answer, owner ) values "
+ "('Don''t Panic', 'Joe')");
createStatement.execute("insert into T_ADVICE ( answer, owner ) values "
+ "('Keep Smiling', 'John')");

System.out.println("\nFindbugs Sample for DMI_CONSTANT_DB_PASSWORD");
// WRONG
FindbugsWarningsByExample2.getConnection_dmiConstantDbPasswordWRONG();
// CORRECT
FindbugsWarningsByExample2.getConnection_dmiConstantDbPasswordCORRECT();

System.out.println("\nFindbugs Sample for DMI_EMPTY_DB_PASSWORD");
// WRONG
FindbugsWarningsByExample2.getConnection_dmiEmptyDbPasswordWRONG();
// CORRECT
FindbugsWarningsByExample2.getConnection_dmiConstantDbPasswordCORRECT();

System.out.println("\nFindbugs Sample for SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE");
// WRONG
FindbugsWarningsByExample2.sqlNonconstantStringPassedToExecuteWRONG("Joe");
// CORRECT
FindbugsWarningsByExample2.sqlNonconstantStringPassedToExecuteCORRECT("Joe");

System.out.println("\nFindbugs Sample for OBL_UNSATISFIED_OBLIGATION");
// WRONG
FindbugsWarningsByExample2.oblUnsatisfiedObligationWRONG("Joe");
// CORRECT
FindbugsWarningsByExample2.oblUnsatisfiedObligationCORRECT("Joe");

System.out.println("\nFindbugs Sample for OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE");
// WRONG
FindbugsWarningsByExample2.oblUnsatisfiedObligationExceptionEdgeWRONG("Joe");
// CORRECT
FindbugsWarningsByExample2.oblUnsatisfiedObligationExceptionEdgeCORRECT("Joe");

} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != createStatement) {
try {
createStatement.close();
} catch (final SQLException e) {
}
}
if (null != connection) {
try {
connection.close();
} catch (final SQLException e) {
}
}

}

}

private static Connection getConnection_dmiConstantDbPasswordWRONG() throws SQLException {

Connection connection = null;
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
} catch (final ClassNotFoundException e) {
System.out.println(" - ERROR:" + e.getMessage());
}
connection = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "APP",
"my-secret-password");
System.out.println(" - DriverManager.getConnection(\"jdbc:derby:database;"
+ "create=true\", \"test\", \"admin\"))");

return connection;
}

private static Connection getConnection_dmiEmptyDbPasswordWRONG() throws SQLException {

Connection connection = null;
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
} catch (final ClassNotFoundException e) {
System.out.println(" - ERROR:" + e.getMessage());
}
connection = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "APP", "");
System.out.println(" - DriverManager.getConnection(\"jdbc:derby:database;create=true\","
+ " \"test\", \"\"))");
return connection;
}

private static Connection getConnection_dmiConstantDbPasswordCORRECT() throws SQLException {

Connection connection = null;
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
} catch (final ClassNotFoundException e) {
System.out.println(" - ERROR:" + e.getMessage());
}
connection = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "APP",
getSecurePassword());
System.out.println(" - DriverManager.getConnection(\"jdbc:derby:database;"
+ "create=true\", \"test\", pwdDecoder()))");
return connection;
}

static String getSecurePassword() {
// Here we should fetch and decode the password from a secured resource
return "my-sec" + "ret-password";
}

private static void sqlNonconstantStringPassedToExecuteWRONG(final String owner) {

Statement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner= '" + owner + "'";
statement = getConnection_dmiConstantDbPasswordCORRECT().createStatement();
resultSet = statement.executeQuery(query);
while (resultSet.next()) {
System.out.println(" - Result (Statement):" + resultSet.getString("ANSWER"));
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {

if (null != resultSet) {
try {
resultSet.close();
} catch (final SQLException e) {
}
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
}
}

private static void sqlNonconstantStringPassedToExecuteCORRECT(final String owner) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner = ?";
statement = getConnection_dmiConstantDbPasswordCORRECT().prepareStatement(query);
statement.setString(1, owner);
resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(" - Result (PreparedStatement):" + resultSet.getString("ANSWER"));
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != resultSet) {
try {
resultSet.close();
} catch (final SQLException e) {
}
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
}
}

private static void oblUnsatisfiedObligationWRONG(final String owner) {

PreparedStatement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner = ?";
statement = getConnection_dmiConstantDbPasswordCORRECT().prepareStatement(query);
statement.setString(1, owner);
resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(" - Result (PreparedStatement):" + resultSet.getString("ANSWER"));
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
}
}

private static void oblUnsatisfiedObligationCORRECT(final String owner) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner = ?";
statement = getConnection_dmiConstantDbPasswordCORRECT().prepareStatement(query);
statement.setString(1, owner);
resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(" - Result (PreparedStatement):" + resultSet.getString("ANSWER"));
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != resultSet) {
try {
resultSet.close();
} catch (final SQLException e) {
}
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
}
}

private static void oblUnsatisfiedObligationExceptionEdgeWRONG(final String owner) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner = ?";
statement = getConnection_dmiConstantDbPasswordCORRECT().prepareStatement(query);
statement.setString(1, owner);
resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(" - Result (PreparedStatement):" + resultSet.getString("ANSWER"));
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != resultSet) {
try {
resultSet.close();
} catch (final SQLException e) {
}
}
}
}

private static void oblUnsatisfiedObligationExceptionEdgeCORRECT(final String owner) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
final String query = "SELECT answer FROM T_ADVICE WHERE owner = ?";
statement = getConnection_dmiConstantDbPasswordCORRECT().prepareStatement(query);
statement.setString(1, owner);
resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(" - Result (PreparedStatement):" + resultSet.getString("ANSWER"));
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
} catch (final SQLException e) {
System.out.println(" - ERROR:" + e.getMessage());
} finally {
if (null != resultSet) {
try {
resultSet.close();
} catch (final SQLException e) {
}
}
if (null != statement) {
try {
statement.close();
} catch (final SQLException e) {
}
}
}
}
}

The program should print the following to the standard output:


Findbugs Sample prepare small in memory database
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))

Findbugs Sample for DMI_CONSTANT_DB_PASSWORD
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", "admin"))
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))

Findbugs Sample for DMI_EMPTY_DB_PASSWORD
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", ""))
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))

Findbugs Sample for SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (Statement):Don't Panic
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (PreparedStatement):Don't Panic

Findbugs Sample for OBL_UNSATISFIED_OBLIGATION
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (PreparedStatement):Don't Panic
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (PreparedStatement):Don't Panic

Findbugs Sample for OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (PreparedStatement):Don't Panic
   - DriverManager.getConnection("jdbc:derby:database;create=true", "test", pwdDecoder()))
   - Result (PreparedStatement):Don't Panic

Please, do not hesitate to contact me if you have any ideas for improvement and/or you find a bug in the sample code. 

Change History

 Revision  Date  Author  Description
 1.0  Jul 25, 2012  Markus Sprunck   created
 1.1  Aug 19, 2012  Markus Sprunck  improved layout for tablets
 1.2   Jan 19, 2013  Markus Sprunck  smaller content improvements
 1.3  Apr 25, 2013  Markus Sprunck  source code now on GitHub

Google+ Comments

You may press the +1 button to share and/or comment