Background
Found while implementing #574 (PostgresqlDataTypeFactory json/jsonb support). That issue's own history has a 2015 maintainer reply flagging the original patch attachment's setSqlValue() NPEing on a null value; tracing exactly why that class of bug is possible surfaced that four already-shipped org.dbunit.ext.postgresql classes have the same gap today, live on main.
Root cause
org.dbunit.dataset.datatype.AbstractDataType#compare(Object, Object) - used by Assertion/DbUnitAssert whenever comparing an expected value against an actual value - calls typeCast(o1)/typeCast(o2) directly whenever the two values aren't .equals(), including the case where exactly one of them is null:
if (areObjectsEqual(o1, o2)) { return 0; }
final Object value1 = typeCast(o1);
final Object value2 = typeCast(o2);
Four PostgreSQL Types.OTHER data types don't null-check before dereferencing in typeCast(Object arg0), returning arg0.toString() unconditionally:
UuidType
InetType
CitextType
GenericEnumType
Additionally, none of the four null-check inside the private PGobject-building helper (getUUID()/getInet()/getCitext()/getEnum()) that setSqlValue() calls, so a direct setSqlValue(null, ...) call would also NPE. This is normally masked on the write path because SimplePreparedStatement/PreparedBatchStatement#addValue() intercept a null value and call PreparedStatement#setNull(...) directly before ever reaching DataType#setSqlValue() - but AbstractDataType#compare() has no equivalent guard, so the assertion path is genuinely reachable.
Reproduction
Comparing an expected dataset row containing null for a uuid/inet/citext/enum column against an actual row containing a non-null value (or vice versa) via Assertion.assertEquals/DbUnitAssert throws NullPointerException instead of correctly reporting a value mismatch.
Suggested fix
Null-check in typeCast() (returning null for a null input) and in setSqlValue() (bind SQL NULL before ever entering the PGobject-building path) for all four classes. org.dbunit.ext.postgresql.JsonType, added in #574 (branch 574-postgresql-json-type, not yet merged), already implements both guards correctly and can be used as the reference pattern.
Affected classes
org.dbunit.ext.postgresql.UuidType
org.dbunit.ext.postgresql.InetType
org.dbunit.ext.postgresql.CitextType
org.dbunit.ext.postgresql.GenericEnumType
Background
Found while implementing #574 (PostgresqlDataTypeFactory
json/jsonbsupport). That issue's own history has a 2015 maintainer reply flagging the original patch attachment'ssetSqlValue()NPEing on a null value; tracing exactly why that class of bug is possible surfaced that four already-shippedorg.dbunit.ext.postgresqlclasses have the same gap today, live onmain.Root cause
org.dbunit.dataset.datatype.AbstractDataType#compare(Object, Object)- used byAssertion/DbUnitAssertwhenever comparing an expected value against an actual value - callstypeCast(o1)/typeCast(o2)directly whenever the two values aren't.equals(), including the case where exactly one of them is null:Four PostgreSQL
Types.OTHERdata types don't null-check before dereferencing intypeCast(Object arg0), returningarg0.toString()unconditionally:UuidTypeInetTypeCitextTypeGenericEnumTypeAdditionally, none of the four null-check inside the private PGobject-building helper (
getUUID()/getInet()/getCitext()/getEnum()) thatsetSqlValue()calls, so a directsetSqlValue(null, ...)call would also NPE. This is normally masked on the write path becauseSimplePreparedStatement/PreparedBatchStatement#addValue()intercept a null value and callPreparedStatement#setNull(...)directly before ever reachingDataType#setSqlValue()- butAbstractDataType#compare()has no equivalent guard, so the assertion path is genuinely reachable.Reproduction
Comparing an expected dataset row containing
nullfor auuid/inet/citext/enum column against an actual row containing a non-null value (or vice versa) viaAssertion.assertEquals/DbUnitAssertthrowsNullPointerExceptioninstead of correctly reporting a value mismatch.Suggested fix
Null-check in
typeCast()(returningnullfor anullinput) and insetSqlValue()(bind SQLNULLbefore ever entering the PGobject-building path) for all four classes.org.dbunit.ext.postgresql.JsonType, added in #574 (branch574-postgresql-json-type, not yet merged), already implements both guards correctly and can be used as the reference pattern.Affected classes
org.dbunit.ext.postgresql.UuidTypeorg.dbunit.ext.postgresql.InetTypeorg.dbunit.ext.postgresql.CitextTypeorg.dbunit.ext.postgresql.GenericEnumType