Re: Patch for possible PSQLException bug - Mailing list pgsql-jdbc
From | Barry Lind |
---|---|
Subject | Re: Patch for possible PSQLException bug |
Date | |
Msg-id | 3E690347.3070108@xythos.com Whole thread Raw |
In response to | Patch for possible PSQLException bug (Tarjei Skorgenes <tarjei.skorgenes@himolde.no>) |
List | pgsql-jdbc |
Tarjei, Thanks for finding and fixing. This one has been bugging me for a while, but I haven't ever had the patience to track down what was the cause. I will apply your patch later today. thanks, --Barry Tarjei Skorgenes wrote: > After trying the new SSL functionality in the driver I stumbled upon the > following bug in PSQLException: > > The no-parameter constructor of SQLException is called at the beginning of every > constructor in PSQLException. This can lead to a NullPointerException > if the user has set the loglevel to something > 0. When loglevel is > greater than 0 Driver.java calls DriverManager.setLogWriter(System.out). > All messages are printed to this logwriter. The no-parameter > constructor for SQLException prints the stacktrace of the current > exception to this logwriter whenever it is instantiated. Since > PSQLException inherits from SQLException the toString method of > PSQLException will return null since the translate method won't have > been called yet. > > As a consequence an attempt will be made to print the return value from > toString() to the logwriter and this will result in a > NullPointerException being thrown. This might be categorized as a bug in > PrintWriter but any user trying to use the jdbc driver with loglevel > 0 > might stumble upon it. > > I've cooked up a JUnit testcase that checks for the error and I've made a > simple one-liner patch to get toString() to return "" if message hasn't been > initialized yet. > > -- > Tarjei Skorgenes > tarjei.skorgenes@himolde.no > > > ------------------------------------------------------------------------ > > diff -uNr jdbc/org/postgresql/util/PSQLException.java jdbc-new/org/postgresql/util/PSQLException.java > --- jdbc/org/postgresql/util/PSQLException.java 2003-02-27 06:45:44.000000000 +0100 > +++ jdbc-new/org/postgresql/util/PSQLException.java 2003-02-27 15:19:41.000000000 +0100 > @@ -111,6 +111,6 @@ > */ > public String toString() > { > - return message; > + return message != null ? message : ""; > } > } > > > ------------------------------------------------------------------------ > > diff -uNr jdbc/build.xml jdbc-new/build.xml > --- jdbc/build.xml 2003-02-27 06:45:43.000000000 +0100 > +++ jdbc-new/build.xml 2003-02-27 15:24:06.000000000 +0100 > @@ -50,6 +50,9 @@ > <available property="datasource" classname="javax.sql.DataSource"/> > <available property="ssl" classname="javax.net.ssl.SSLSocketFactory"/> > <available property="junit" classname="junit.framework.Test" /> > + <condition property="utiltests"> > + <isset property="junit"/> > + </condition> > <condition property="jdbc2tests"> > <and> > <isset property="jdbc2"/> > @@ -278,8 +281,21 @@ > <property name="junit.ui" value="textui" /> > > > - <target name="test" depends="testjdbc2,testjdbc2optional,testjdbc3"> > - </target> > + <target name="test" depends="testutil,testjdbc2,testjdbc2optional,testjdbc3"> > + </target> > + > + <target name="testutil" depends="jar" if="utiltests"> > + <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}"> > + <include name="${package}/test/util/*" /> > + </javac> > + <java fork="yes" classname="junit.${junit.ui}.TestRunner" taskname="junit" failonerror="true"> > + <arg value="org.postgresql.test.util.UtilTestSuite" /> > + <classpath> > + <pathelement location="${builddir}" /> > + <pathelement path="${java.class.path}" /> > + </classpath> > + </java> > + </target> > > <target name="testjdbc2" depends="jar" if="jdbc2tests"> > <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}"> > diff -uNr jdbc/org/postgresql/test/util/TestPSQLException.java jdbc-new/org/postgresql/test/util/TestPSQLException.java > --- jdbc/org/postgresql/test/util/TestPSQLException.java 1970-01-01 01:00:00.000000000 +0100 > +++ jdbc-new/org/postgresql/test/util/TestPSQLException.java 2003-02-27 15:24:07.000000000 +0100 > @@ -0,0 +1,84 @@ > +package org.postgresql.test.util; > + > +import java.io.*; > +import java.sql.*; > +import junit.framework.TestCase; > +import org.postgresql.util.PSQLException; > + > +public class TestPSQLException extends TestCase { > + private PrintWriter oldWriter; > + private MockWriter mockWriter; > + > + private static class MockWriter extends PrintWriter { > + static class BogusWriter extends Writer { > + public void flush() {} > + public void close() {} > + public void write(char[] cbuf, int off, int len) {} > + } > + > + public MockWriter() { > + super(new BogusWriter()); > + out = this; > + } > + > + private boolean isNull = false; > + private int methodCallNr = 1; > + > + // This method gets called from SQLExceptions constructor > + // with the value of PSQLException.toString() as a parameter. > + // We're only interested in the first call since that is > + // the one containing the toString value > + public void write(String val) { > + if ((methodCallNr == 1) && (val == null)) { > + isNull = true; > + } > + > + methodCallNr++; > + } > + > + public boolean isNull() { > + return this.isNull; > + } > + } > + > + private void setLogWriter(PrintWriter pw) { > + DriverManager.setLogWriter(pw); > + } > + > + public TestPSQLException(String name) { > + super(name); > + } > + > + public void setUp() { > + // Take a backup of the old logWriter > + oldWriter = DriverManager.getLogWriter(); > + > + // Set a new logwriter > + mockWriter = new MockWriter(); > + setLogWriter(mockWriter); > + } > + > + public void tearDown() { > + // Restore the old logwriter > + setLogWriter(oldWriter); > + > + oldWriter = null; > + mockWriter = null; > + } > + > + /** > + * Checks if PSQLException.toString() returns null if it gets called from one > + * of the constructors. This is checked by testing if an attempt was made to > + * write a null value to the MockWriter > + */ > + public void testToStringNotNullInConstructor() { > + PSQLException ex = new PSQLException("Bogus exception", new Exception()); > + > + // Did toString return null? > + boolean isNull = mockWriter.isNull(); > + > + boolean expected = false; > + boolean actual = isNull; > + assertEquals("toString should not return null if called from the constructor", expected, actual); > + } > +} > diff -uNr jdbc/org/postgresql/test/util/UtilTestSuite.java jdbc-new/org/postgresql/test/util/UtilTestSuite.java > --- jdbc/org/postgresql/test/util/UtilTestSuite.java 1970-01-01 01:00:00.000000000 +0100 > +++ jdbc-new/org/postgresql/test/util/UtilTestSuite.java 2003-02-27 15:24:27.000000000 +0100 > @@ -0,0 +1,24 @@ > +package org.postgresql.test.util; > + > +import junit.framework.TestSuite; > +import junit.framework.TestCase; > +import junit.framework.Test; > + > +/* > + * Executes all known tests for classes in org.postgresql.util > + */ > +public class UtilTestSuite extends TestSuite > +{ > + /* > + * The main entry point for JUnit > + */ > + public static TestSuite suite() > + { > + TestSuite suite = new TestSuite(); > + > + // PSQLException tests > + suite.addTestSuite(TestPSQLException.class); > + > + return suite; > + } > +} > > > ------------------------------------------------------------------------ > > > ---------------------------(end of broadcast)--------------------------- > TIP 5: Have you checked our extensive FAQ? > > http://www.postgresql.org/users-lounge/docs/faq.html
pgsql-jdbc by date: