Fix CVE-2022-31197 Source of this commit and more information about it is here: https://github.com/pgjdbc/pgjdbc/commit/739e599d52ad80f8dcd6efedc6157859b1a9d637 diff --git a/src/main/java/org/postgresql/jdbc/PgResultSet.java b/src/main/java/org/postgresql/jdbc/PgResultSet.java index 42c6dda6..81a5ef1d 100644 --- a/src/main/java/org/postgresql/jdbc/PgResultSet.java +++ b/src/main/java/org/postgresql/jdbc/PgResultSet.java @@ -1323,7 +1323,7 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS if (i > 1) { selectSQL.append(", "); } - selectSQL.append(pgmd.getBaseColumnName(i)); + Utils.escapeIdentifier(selectSQL, pgmd.getBaseColumnName(i)); } selectSQL.append(" from ").append(onlyTable).append(tableName).append(" where "); @@ -1333,7 +1333,8 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS for (int i = 0; i < numKeys; i++) { PrimaryKey primaryKey = primaryKeys.get(i); - selectSQL.append(primaryKey.name).append("= ?"); + Utils.escapeIdentifier(selectSQL, primaryKey.name); + selectSQL.append(" = ?"); if (i < numKeys - 1) { selectSQL.append(" and "); diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetRefreshTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetRefreshTest.java new file mode 100644 index 00000000..3a4a7e51 --- /dev/null +++ b/src/test/java/org/postgresql/test/jdbc2/ResultSetRefreshTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, PostgreSQL Global Development Group + * See the LICENSE file in the project root for more information. + */ + +package org.postgresql.test.jdbc2; + +import static org.junit.Assert.assertTrue; + +import org.postgresql.test.TestUtil; + +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Connection; + +public class ResultSetRefreshTest extends BaseTest4 { + @Test + public void testWithDataColumnThatRequiresEscaping() throws Exception { + Connection conn = con; + TestUtil.dropTable(conn, "refresh_row_bad_ident"); + TestUtil.execute("CREATE TABLE refresh_row_bad_ident (id int PRIMARY KEY, \"1 FROM refresh_row_bad_ident; SELECT 2; SELECT *\" int)",conn); + TestUtil.execute("INSERT INTO refresh_row_bad_ident (id) VALUES (1), (2), (3)",conn); + + Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + ResultSet rs = stmt.executeQuery("SELECT * FROM refresh_row_bad_ident"); + assertTrue(rs.next()); + try { + rs.refreshRow(); + } catch (SQLException ex) { + throw new RuntimeException("ResultSet.refreshRow() did not handle escaping data column identifiers", ex); + } + rs.close(); + stmt.close(); + } + + @Test + public void testWithKeyColumnThatRequiresEscaping() throws Exception { + Connection conn = con; + TestUtil.dropTable(conn, "refresh_row_bad_ident"); + TestUtil.execute("CREATE TABLE refresh_row_bad_ident (\"my key\" int PRIMARY KEY)",conn); + TestUtil.execute("INSERT INTO refresh_row_bad_ident VALUES (1), (2), (3)",conn); + + Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + ResultSet rs = stmt.executeQuery("SELECT * FROM refresh_row_bad_ident"); + assertTrue(rs.next()); + try { + rs.refreshRow(); + } catch (SQLException ex) { + throw new RuntimeException("ResultSet.refreshRow() did not handle escaping key column identifiers", ex); + } + rs.close(); + stmt.close(); + } +}