Skip to content

Commit bd91c4c

Browse files
authored
Prepare for release (#2580)
* Revert "fix: replace syncronization in Connection.close with compareAndSet" * Revert "feat: synchronize statement executions (e.g. avoid deadlock when Connection.isValid is executed from concurrent threads)" * Revert "set a timeout to get the return from requesting SSL upgrade. (#2572)" * Revert "add alias to the generated query for clarity (#2553)"
1 parent 739e599 commit bd91c4c

13 files changed

Lines changed: 197 additions & 260 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,29 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
55

66
## [Unreleased]
77
### Changed
8-
chore: skip publishing pgjdbc-osgi-test to Central
9-
chore: bump Gradle to 7.5
10-
test: update JUnit to 5.8.2
118

129
### Added
13-
chore: added Gradle Wrapper Validation for verifying gradle-wrapper.jar
14-
chore: added "permissions: contents: read" for GitHub Actions to avoid unintentional modifications by the CI
15-
chore: support building pgjdbc with Java 17
16-
feat: synchronize statement executions (e.g. avoid deadlock when Connection.isValid is executed from concurrent threads)
10+
11+
### Fixed
12+
13+
[42.4.1] (2022-08-01 16:24:20 -0400)
14+
### Security
15+
- fix: CVE-2022-31197 Fixes SQL generated in PgResultSet.refresh() to escape column identifiers so as to prevent SQL injection.
16+
- Previously, the column names for both key and data columns in the table were copied as-is into the generated
17+
SQL. This allowed a malicious table with column names that include statement terminator to be parsed and
18+
executed as multiple separate commands.
19+
- Also adds a new test class ResultSetRefreshTest to verify this change.
20+
- Reported by [Sho Kato](https://github.com/kato-sho)
21+
22+
### Changed
23+
- chore: skip publishing pgjdbc-osgi-test to Central
24+
- chore: bump Gradle to 7.5
25+
- test: update JUnit to 5.8.2
26+
27+
### Added
28+
- chore: added Gradle Wrapper Validation for verifying gradle-wrapper.jar
29+
- chore: added "permissions: contents: read" for GitHub Actions to avoid unintentional modifications by the CI
30+
- chore: support building pgjdbc with Java 17
1731

1832
### Fixed
1933

@@ -709,4 +723,5 @@ thrown to caller to be dealt with so no need to log at this verbosity by pgjdbc
709723
[42.3.4]: https://github.com/pgjdbc/pgjdbc/compare/REL42.3.4...REL42.3.5
710724
[42.3.5]: https://github.com/pgjdbc/pgjdbc/compare/REL42.3.5...REL42.3.6
711725
[42.3.6]: https://github.com/pgjdbc/pgjdbc/compare/REL42.3.6...REL42.4.0
712-
[Unreleased]: https://github.com/pgjdbc/pgjdbc/compare/REL42.4.0...HEAD
726+
[42.4.0]: https://github.com/pgjdbc/pgjdbc/compare/REL42.4.0...REL42.4.1
727+
[Unreleased]: https://github.com/pgjdbc/pgjdbc/compare/REL42.4.1...HEAD

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ In addition to the standard connection parameters the driver supports a number o
118118
| loginTimeout | Integer | 0 | Specify how long to wait for establishment of a database connection.|
119119
| connectTimeout | Integer | 10 | The timeout value used for socket connect operations. |
120120
| socketTimeout | Integer | 0 | The timeout value used for socket read operations. |
121-
| sslResponseTimeout | Integer | 5000 | Socket timeout waiting for a response from a request for SSL upgrade from the server. |
122121
| tcpKeepAlive | Boolean | false | Enable or disable TCP keep-alive. |
123122
| tcpNoDelay | Boolean | true | Enable or disable TCP no delay. |
124123
| ApplicationName | String | PostgreSQL JDBC Driver | The application name (require server version >= 9.0). If assumeMinServerVersion is set to >= 9.0 this will be sent in the startup packets, otherwise after the connection is made |
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: PostgreSQL JDBC Driver 42.4.1 Released
3+
date: 2022-08-03 08:09:07 -0400
4+
categories:
5+
- new_release
6+
version: 42.4.1
7+
---
8+
**Notable changes**
9+
10+
### Security
11+
- fix: CVE-2022-31197 Fixes SQL generated in PgResultSet.refresh() to escape column identifiers so as to prevent SQL injection.
12+
- Previously, the column names for both key and data columns in the table were copied as-is into the generated
13+
SQL. This allowed a malicious table with column names that include statement terminator to be parsed and
14+
executed as multiple separate commands.
15+
- Also adds a new test class ResultSetRefreshTest to verify this change.
16+
- Reported by [Sho Kato](https://github.com/kato-sho)
17+
18+
### Changed
19+
- chore: skip publishing pgjdbc-osgi-test to Central
20+
- chore: bump Gradle to 7.5
21+
- test: update JUnit to 5.8.2
22+
23+
### Added
24+
- chore: added Gradle Wrapper Validation for verifying gradle-wrapper.jar
25+
- chore: added "permissions: contents: read" for GitHub Actions to avoid unintentional modifications by the CI
26+
- chore: support building pgjdbc with Java 17
27+
28+
<!--more-->
29+
30+
**Commits by author**
31+
32+
Dave Cramer (9):
33+
bump gradle to version 3 to fix compile errors with jdk17 [PR 2550](https://github.com/pgjdbc/pgjdbc/pull/2550)
34+
update the website content [PR 2578](https://github.com/pgjdbc/pgjdbc/pull/2578)
35+
36+
Sehrope Sarkuni (1):
37+
Fix SQL generated in PgResultSet.refresh() to escape column identifiers so as to prevent SQL injection.
38+
39+
Vladimir Sitnikov (34):
40+
bump system-stubs-jupiter to 2.0.1 to support Java 16+
41+
update JUnit to 5.8.2
42+
migrate DriverTest to JUnit5
43+
bump Gradle to 7.5
44+

docs/documentation/head/connect.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,6 @@ Connection conn = DriverManager.getConnection(url);
327327
detecting network problems. The timeout is specified in seconds and a
328328
value of zero means that it is disabled.
329329

330-
* **sslResponseTimeout** = int
331-
The timeout value in milliseconds that we wait for a response from the server
332-
after requesting the connection be upgraded to SSL.
333-
334330
* **cancelSignalTimeout** = int
335331

336332
Cancel command is sent out of band over its own connection, so cancel message can itself get

pgjdbc/src/main/java/org/postgresql/PGProperty.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -672,15 +672,6 @@ public enum PGProperty {
672672
null,
673673
"A class, implementing javax.security.auth.callback.CallbackHandler that can handle PassworCallback for the ssl password."),
674674

675-
/**
676-
* <p>After requesting an upgrade to SSL from the server there are reports of the server not responding due to a failover
677-
* without a timeout here, the client can wait forever. This timeout will be set before the request and reset after </p>
678-
*/
679-
SSL_RESPONSE_TIMEOUT(
680-
"sslResponseTimeout",
681-
"5000",
682-
"Time in milliseconds we wait for a response from the server after requesting SSL upgrade"),
683-
684675
/**
685676
* File containing the root certificate when validating server ({@code sslmode} = {@code
686677
* verify-ca} or {@code verify-full}). Default will be the file {@code root.crt} in {@code

pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -532,17 +532,6 @@ private PGStream enableSSL(PGStream pgStream, SslMode sslMode, Properties info,
532532

533533
LOGGER.log(Level.FINEST, " FE=> SSLRequest");
534534

535-
int sslTimeout = PGProperty.SSL_RESPONSE_TIMEOUT.getInt(info);
536-
int currentTimeout = pgStream.getSocket().getSoTimeout();
537-
538-
// if the current timeout is less than sslTimeout then
539-
// use the smaller timeout. We could do something tricky
540-
// here to not set it in that case but this is pretty readable
541-
if (currentTimeout > 0 && currentTimeout < sslTimeout) {
542-
sslTimeout = currentTimeout;
543-
}
544-
545-
pgStream.getSocket().setSoTimeout(sslTimeout);
546535
// Send SSL request packet
547536
pgStream.sendInteger4(8);
548537
pgStream.sendInteger2(1234);
@@ -551,8 +540,6 @@ private PGStream enableSSL(PGStream pgStream, SslMode sslMode, Properties info,
551540

552541
// Now get the response from the backend, one of N, E, S.
553542
int beresp = pgStream.receiveChar();
554-
pgStream.getSocket().setSoTimeout(currentTimeout);
555-
556543
switch (beresp) {
557544
case 'E':
558545
LOGGER.log(Level.FINEST, " <=BE SSLError");

pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -354,24 +354,6 @@ public void setConnectTimeout(int connectTimeout) {
354354
PGProperty.CONNECT_TIMEOUT.set(properties, connectTimeout);
355355
}
356356

357-
/**
358-
*
359-
* @return SSL ResponseTimeout
360-
* @see PGProperty#SSL_RESPONSE_TIMEOUT
361-
*/
362-
public int getSslResponseTimeout() {
363-
return PGProperty.SSL_RESPONSE_TIMEOUT.getIntNoCheck(properties);
364-
}
365-
366-
/**
367-
*
368-
* @param sslResponseTimeout ssl response timeout
369-
* @see PGProperty#SSL_RESPONSE_TIMEOUT
370-
*/
371-
public void setSslResponseTimeout(int sslResponseTimeout) {
372-
PGProperty.SSL_RESPONSE_TIMEOUT.set(properties,sslResponseTimeout);
373-
}
374-
375357
/**
376358
* @return protocol version
377359
* @see PGProperty#PROTOCOL_VERSION

pgjdbc/src/main/java/org/postgresql/jdbc/PgCallableStatement.java

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -80,79 +80,79 @@ public int executeUpdate() throws SQLException {
8080

8181
@Override
8282
public boolean executeWithFlags(int flags) throws SQLException {
83-
synchronized (this) {
84-
boolean hasResultSet = super.executeWithFlags(flags);
85-
int[] functionReturnType = this.functionReturnType;
86-
if (!isFunction || !returnTypeSet || functionReturnType == null) {
87-
return hasResultSet;
88-
}
83+
boolean hasResultSet = super.executeWithFlags(flags);
84+
int[] functionReturnType = this.functionReturnType;
85+
if (!isFunction || !returnTypeSet || functionReturnType == null) {
86+
return hasResultSet;
87+
}
8988

90-
// If we are executing and there are out parameters
91-
// callable statement function set the return data
92-
if (!hasResultSet) {
93-
throw new PSQLException(GT.tr("A CallableStatement was executed with nothing returned."),
94-
PSQLState.NO_DATA);
95-
}
89+
// If we are executing and there are out parameters
90+
// callable statement function set the return data
91+
if (!hasResultSet) {
92+
throw new PSQLException(GT.tr("A CallableStatement was executed with nothing returned."),
93+
PSQLState.NO_DATA);
94+
}
9695

97-
ResultSet rs = castNonNull(getResultSet());
98-
if (!rs.next()) {
99-
throw new PSQLException(GT.tr("A CallableStatement was executed with nothing returned."),
100-
PSQLState.NO_DATA);
101-
}
96+
ResultSet rs = castNonNull(getResultSet());
97+
if (!rs.next()) {
98+
throw new PSQLException(GT.tr("A CallableStatement was executed with nothing returned."),
99+
PSQLState.NO_DATA);
100+
}
102101

103-
// figure out how many columns
104-
int cols = rs.getMetaData().getColumnCount();
102+
// figure out how many columns
103+
int cols = rs.getMetaData().getColumnCount();
105104

106-
int outParameterCount = preparedParameters.getOutParameterCount();
105+
int outParameterCount = preparedParameters.getOutParameterCount();
107106

108-
if (cols != outParameterCount) {
109-
throw new PSQLException(
110-
GT.tr("A CallableStatement was executed with an invalid number of parameters"),
111-
PSQLState.SYNTAX_ERROR);
107+
if (cols != outParameterCount) {
108+
throw new PSQLException(
109+
GT.tr("A CallableStatement was executed with an invalid number of parameters"),
110+
PSQLState.SYNTAX_ERROR);
111+
}
112+
113+
// reset last result fetched (for wasNull)
114+
lastIndex = 0;
115+
116+
// allocate enough space for all possible parameters without regard to in/out
117+
@Nullable Object[] callResult = new Object[preparedParameters.getParameterCount() + 1];
118+
this.callResult = callResult;
119+
120+
// move them into the result set
121+
for (int i = 0, j = 0; i < cols; i++, j++) {
122+
// find the next out parameter, the assumption is that the functionReturnType
123+
// array will be initialized with 0 and only out parameters will have values
124+
// other than 0. 0 is the value for java.sql.Types.NULL, which should not
125+
// conflict
126+
while (j < functionReturnType.length && functionReturnType[j] == 0) {
127+
j++;
112128
}
113129

114-
// reset last result fetched (for wasNull)
115-
lastIndex = 0;
116-
117-
// allocate enough space for all possible parameters without regard to in/out
118-
@Nullable Object[] callResult = new Object[preparedParameters.getParameterCount() + 1];
119-
this.callResult = callResult;
120-
121-
// move them into the result set
122-
for (int i = 0, j = 0; i < cols; i++, j++) {
123-
// find the next out parameter, the assumption is that the functionReturnType
124-
// array will be initialized with 0 and only out parameters will have values
125-
// other than 0. 0 is the value for java.sql.Types.NULL, which should not
126-
// conflict
127-
while (j < functionReturnType.length && functionReturnType[j] == 0) {
128-
j++;
129-
}
130+
callResult[j] = rs.getObject(i + 1);
131+
int columnType = rs.getMetaData().getColumnType(i + 1);
130132

131-
callResult[j] = rs.getObject(i + 1);
132-
int columnType = rs.getMetaData().getColumnType(i + 1);
133-
134-
if (columnType != functionReturnType[j]) {
135-
// this is here for the sole purpose of passing the cts
136-
if (columnType == Types.DOUBLE && functionReturnType[j] == Types.REAL) {
137-
// return it as a float
138-
Object result = callResult[j];
139-
if (result != null) {
140-
callResult[j] = ((Double) result).floatValue();
141-
}
142-
} else if (columnType == Types.REF_CURSOR && functionReturnType[j] == Types.OTHER) {
143-
// For backwards compatibility reasons we support that ref cursors can be
144-
// registered with both Types.OTHER and Types.REF_CURSOR so we allow
145-
// this specific mismatch
146-
} else {
147-
throw new PSQLException(GT.tr(
148-
"A CallableStatement function was executed and the out parameter {0} was of type {1} however type {2} was registered.",
149-
i + 1, "java.sql.Types=" + columnType, "java.sql.Types=" + functionReturnType[j]),
150-
PSQLState.DATA_TYPE_MISMATCH);
133+
if (columnType != functionReturnType[j]) {
134+
// this is here for the sole purpose of passing the cts
135+
if (columnType == Types.DOUBLE && functionReturnType[j] == Types.REAL) {
136+
// return it as a float
137+
Object result = callResult[j];
138+
if (result != null) {
139+
callResult[j] = ((Double) result).floatValue();
151140
}
141+
} else if (columnType == Types.REF_CURSOR && functionReturnType[j] == Types.OTHER) {
142+
// For backwards compatibility reasons we support that ref cursors can be
143+
// registered with both Types.OTHER and Types.REF_CURSOR so we allow
144+
// this specific mismatch
145+
} else {
146+
throw new PSQLException(GT.tr(
147+
"A CallableStatement function was executed and the out parameter {0} was of type {1} however type {2} was registered.",
148+
i + 1, "java.sql.Types=" + columnType, "java.sql.Types=" + functionReturnType[j]),
149+
PSQLState.DATA_TYPE_MISMATCH);
152150
}
153-
154151
}
155-
rs.close();
152+
153+
}
154+
rs.close();
155+
synchronized (this) {
156156
result = null;
157157
}
158158
return false;

pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,13 +1454,8 @@ public boolean isValid(int timeout) throws SQLException {
14541454
statement.execute("IDENTIFY_SYSTEM");
14551455
statement.close();
14561456
} else {
1457-
PreparedStatement checkConnectionQuery;
1458-
synchronized (this) {
1459-
checkConnectionQuery = this.checkConnectionQuery;
1460-
if (checkConnectionQuery == null) {
1461-
checkConnectionQuery = prepareStatement("");
1462-
this.checkConnectionQuery = checkConnectionQuery;
1463-
}
1457+
if (checkConnectionQuery == null) {
1458+
checkConnectionQuery = prepareStatement("");
14641459
}
14651460
checkConnectionQuery.executeUpdate();
14661461
}

pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,11 +2696,11 @@ public ResultSet getUDTs(@Nullable String catalog, @Nullable String schemaPatter
26962696
long longTypOid = typeInfo.intOidToLong(typOid);
26972697
int sqlType = typeInfo.getSQLType(typOid);
26982698

2699-
sqlwhen.append(" when base_type.oid = ").append(longTypOid).append(" then ").append(sqlType);
2699+
sqlwhen.append(" when oid = ").append(longTypOid).append(" then ").append(sqlType);
27002700
}
27012701
sql += sqlwhen.toString();
27022702

2703-
sql += " else " + java.sql.Types.OTHER + " end from pg_type base_type where base_type.oid=t.typbasetype) "
2703+
sql += " else " + java.sql.Types.OTHER + " end from pg_type where oid=t.typbasetype) "
27042704
+ "else null end as base_type "
27052705
+ "from pg_catalog.pg_type t, pg_catalog.pg_namespace n where t.typnamespace = n.oid and n.nspname != 'pg_catalog' and n.nspname != 'pg_toast'";
27062706

0 commit comments

Comments
 (0)