Skip to content

PostgreSQL uuid/inet/citext/enum columns NPE when comparing a null value against a non-null value #930

Closed

Description

@jeffjensen

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

Metadata

Metadata

Assignees

Type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions