Skip to content

Commit 223dfaf

Browse files
committed
Fix for Bug#114989 (Bug#36612566), Setting null value in setClientInfo throws an NPE.
Change-Id: Ie1a2be98cc2079ecb7572e9c1bb3548583ce9444
1 parent 39206fb commit 223dfaf

File tree

5 files changed

+125
-43
lines changed

5 files changed

+125
-43
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 9.0.0
55

6+
- Fix for Bug#114989 (Bug#36612566), Setting null value in setClientInfo throws an NPE.
7+
68
- WL#16376, Set 'caching_sha2_password' as default fallback authentication plugin.
79

810
- WL#16342, Update MySQL error codes mapping.

src/main/user-api/java/com/mysql/cj/jdbc/ClientInfoProvider.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
package com.mysql.cj.jdbc;
2222

23+
import java.sql.Connection;
2324
import java.sql.SQLClientInfoException;
2425
import java.sql.SQLException;
2526
import java.util.Properties;
@@ -43,7 +44,7 @@ public interface ClientInfoProvider {
4344
* @throws SQLException
4445
* if initialization fails.
4546
*/
46-
void initialize(java.sql.Connection conn, Properties configurationProps) throws SQLException;
47+
void initialize(Connection conn, Properties configurationProps) throws SQLException;
4748

4849
/**
4950
* Called once by the driver when the connection this provider instance
@@ -74,7 +75,7 @@ public interface ClientInfoProvider {
7475
* @return client info as Properties
7576
* @see java.sql.Connection#getClientInfo()
7677
*/
77-
Properties getClientInfo(java.sql.Connection conn) throws SQLException;
78+
Properties getClientInfo(Connection conn) throws SQLException;
7879

7980
/**
8081
* Returns the client info for the connection that this provider
@@ -95,7 +96,7 @@ public interface ClientInfoProvider {
9596
* @return the client info by given property name
9697
* @see java.sql.Connection#getClientInfo(java.lang.String)
9798
*/
98-
String getClientInfo(java.sql.Connection conn, String name) throws SQLException;
99+
String getClientInfo(Connection conn, String name) throws SQLException;
99100

100101
/**
101102
* Sets the client info for the connection that this provider
@@ -116,7 +117,7 @@ public interface ClientInfoProvider {
116117
*
117118
* @see java.sql.Connection#setClientInfo(java.util.Properties)
118119
*/
119-
void setClientInfo(java.sql.Connection conn, Properties properties) throws SQLClientInfoException;
120+
void setClientInfo(Connection conn, Properties properties) throws SQLClientInfoException;
120121

121122
/**
122123
* Sets the client info for the connection that this provider
@@ -139,6 +140,6 @@ public interface ClientInfoProvider {
139140
*
140141
* @see java.sql.Connection#setClientInfo(java.lang.String,java.lang.String)
141142
*/
142-
void setClientInfo(java.sql.Connection conn, String name, String value) throws SQLClientInfoException;
143+
void setClientInfo(Connection conn, String name, String value) throws SQLClientInfoException;
143144

144145
}

src/main/user-impl/java/com/mysql/cj/jdbc/ClientInfoProviderSP.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
package com.mysql.cj.jdbc;
2222

23+
import java.sql.Connection;
2324
import java.sql.PreparedStatement;
2425
import java.sql.ResultSet;
2526
import java.sql.SQLClientInfoException;
@@ -45,7 +46,7 @@ public class ClientInfoProviderSP implements ClientInfoProvider {
4546
private final Lock lock = new ReentrantLock();
4647

4748
@Override
48-
public void initialize(java.sql.Connection conn, Properties configurationProps) throws SQLException {
49+
public void initialize(Connection conn, Properties configurationProps) throws SQLException {
4950
this.lock.lock();
5051
try {
5152
String identifierQuote = ((JdbcConnection) conn).getSession().getIdentifierQuoteString();
@@ -93,7 +94,7 @@ public void destroy() throws SQLException {
9394
}
9495

9596
@Override
96-
public Properties getClientInfo(java.sql.Connection conn) throws SQLException {
97+
public Properties getClientInfo(Connection conn) throws SQLException {
9798
this.lock.lock();
9899
try {
99100
ResultSet rs = null;
@@ -121,7 +122,7 @@ public Properties getClientInfo(java.sql.Connection conn) throws SQLException {
121122
}
122123

123124
@Override
124-
public String getClientInfo(java.sql.Connection conn, String name) throws SQLException {
125+
public String getClientInfo(Connection conn, String name) throws SQLException {
125126
this.lock.lock();
126127
try {
127128
ResultSet rs = null;
@@ -150,7 +151,7 @@ public String getClientInfo(java.sql.Connection conn, String name) throws SQLExc
150151
}
151152

152153
@Override
153-
public void setClientInfo(java.sql.Connection conn, Properties properties) throws SQLClientInfoException {
154+
public void setClientInfo(Connection conn, Properties properties) throws SQLClientInfoException {
154155
this.lock.lock();
155156
try {
156157
Enumeration<?> propNames = properties.propertyNames();
@@ -172,7 +173,7 @@ public void setClientInfo(java.sql.Connection conn, Properties properties) throw
172173
}
173174

174175
@Override
175-
public void setClientInfo(java.sql.Connection conn, String name, String value) throws SQLClientInfoException {
176+
public void setClientInfo(Connection conn, String name, String value) throws SQLClientInfoException {
176177
this.lock.lock();
177178
try {
178179
this.setClientInfoSp.setString(1, name);

src/main/user-impl/java/com/mysql/cj/jdbc/CommentClientInfoProvider.java

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@
2020

2121
package com.mysql.cj.jdbc;
2222

23+
import java.sql.Connection;
2324
import java.sql.SQLClientInfoException;
2425
import java.sql.SQLException;
25-
import java.util.Enumeration;
2626
import java.util.Properties;
27+
import java.util.stream.Collectors;
2728

2829
/**
2930
* An implementation of ClientInfoProvider that exposes the client info as a comment prepended to all statements issued by the driver.
@@ -36,7 +37,7 @@ public class CommentClientInfoProvider implements ClientInfoProvider {
3637
private Properties clientInfo;
3738

3839
@Override
39-
public synchronized void initialize(java.sql.Connection conn, Properties configurationProps) throws SQLException {
40+
public synchronized void initialize(Connection conn, Properties configurationProps) throws SQLException {
4041
this.clientInfo = new Properties();
4142
}
4243

@@ -46,54 +47,44 @@ public synchronized void destroy() throws SQLException {
4647
}
4748

4849
@Override
49-
public synchronized Properties getClientInfo(java.sql.Connection conn) throws SQLException {
50-
return this.clientInfo;
50+
public synchronized Properties getClientInfo(Connection conn) throws SQLException {
51+
Properties clientInfoOut = new Properties();
52+
clientInfoOut.putAll(this.clientInfo);
53+
return clientInfoOut;
5154
}
5255

5356
@Override
54-
public synchronized String getClientInfo(java.sql.Connection conn, String name) throws SQLException {
57+
public synchronized String getClientInfo(Connection conn, String name) throws SQLException {
5558
return this.clientInfo.getProperty(name);
5659
}
5760

5861
@Override
59-
public synchronized void setClientInfo(java.sql.Connection conn, Properties properties) throws SQLClientInfoException {
62+
public synchronized void setClientInfo(Connection conn, Properties properties) throws SQLClientInfoException {
6063
this.clientInfo = new Properties();
61-
62-
Enumeration<?> propNames = properties.propertyNames();
63-
64-
while (propNames.hasMoreElements()) {
65-
String name = (String) propNames.nextElement();
66-
67-
this.clientInfo.put(name, properties.getProperty(name));
64+
if (properties != null) {
65+
this.clientInfo.putAll(properties);
6866
}
69-
7067
setComment(conn);
7168
}
7269

7370
@Override
74-
public synchronized void setClientInfo(java.sql.Connection conn, String name, String value) throws SQLClientInfoException {
75-
this.clientInfo.setProperty(name, value);
71+
public synchronized void setClientInfo(Connection conn, String name, String value) throws SQLClientInfoException {
72+
if (value == null) {
73+
this.clientInfo.remove(name);
74+
} else {
75+
this.clientInfo.setProperty(name, value);
76+
}
7677
setComment(conn);
7778
}
7879

79-
private synchronized void setComment(java.sql.Connection conn) {
80-
StringBuilder commentBuf = new StringBuilder();
81-
82-
Enumeration<?> propNames = this.clientInfo.propertyNames();
83-
84-
while (propNames.hasMoreElements()) {
85-
String name = (String) propNames.nextElement();
86-
87-
if (commentBuf.length() > 0) {
88-
commentBuf.append(", ");
89-
}
90-
91-
commentBuf.append("" + name);
92-
commentBuf.append("=");
93-
commentBuf.append("" + this.clientInfo.getProperty(name));
80+
private synchronized void setComment(Connection conn) throws SQLClientInfoException {
81+
String clientInfoComment = this.clientInfo.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", "));
82+
try {
83+
conn.unwrap(JdbcConnection.class).setStatementComment(clientInfoComment);
84+
} catch (SQLException e) {
85+
SQLClientInfoException clientInfoEx = new SQLClientInfoException();
86+
clientInfoEx.initCause(e);
9487
}
95-
96-
((com.mysql.cj.jdbc.JdbcConnection) conn).setStatementComment(commentBuf.toString());
9788
}
9889

9990
}

src/test/java/testsuite/regression/ConnectionRegressionTest.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.junit.jupiter.api.Assertions.assertFalse;
2525
import static org.junit.jupiter.api.Assertions.assertNotEquals;
2626
import static org.junit.jupiter.api.Assertions.assertNotNull;
27+
import static org.junit.jupiter.api.Assertions.assertNotSame;
2728
import static org.junit.jupiter.api.Assertions.assertNull;
2829
import static org.junit.jupiter.api.Assertions.assertTrue;
2930
import static org.junit.jupiter.api.Assertions.fail;
@@ -12090,4 +12091,90 @@ private void testBug23143279RunTest(String lbStrategy) throws Exception {
1209012091
testConn.close();
1209112092
}
1209212093

12094+
/**
12095+
* Test fix for Bug#114989 (36612566), Setting null value in setClientInfo throws an NPE.
12096+
*
12097+
* @throws Exception
12098+
*/
12099+
@Test
12100+
void testBug114989() throws Exception {
12101+
final String clientInfoKey1 = "testBug114989-key1";
12102+
final String clientInfoValue1 = "testBug114989-value1";
12103+
final String clientInfoKey2 = "testBug114989-key2";
12104+
final String clientInfoValue2 = "testBug114989-value2";
12105+
12106+
Properties props = new Properties();
12107+
props.setProperty(PropertyKey.clientInfoProvider.getKeyName(), CommentClientInfoProvider.class.getName());
12108+
try (Connection testConn = getConnectionWithProps(props)) {
12109+
// Start with empty client info.
12110+
Properties clientInfoOut = testConn.getClientInfo();
12111+
assertTrue(clientInfoOut.isEmpty());
12112+
12113+
// Add 2 properties via Properties.
12114+
Properties clientInfoIn = new Properties();
12115+
clientInfoIn.setProperty(clientInfoKey1, clientInfoValue1);
12116+
clientInfoIn.setProperty(clientInfoKey2, clientInfoValue2);
12117+
testConn.setClientInfo(clientInfoIn);
12118+
clientInfoOut = testConn.getClientInfo();
12119+
assertNotSame(clientInfoIn, clientInfoOut);
12120+
assertEquals(2, clientInfoOut.size());
12121+
assertTrue(clientInfoOut.containsKey(clientInfoKey1));
12122+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey1));
12123+
assertTrue(clientInfoOut.containsKey(clientInfoKey2));
12124+
assertEquals(clientInfoValue2, testConn.getClientInfo(clientInfoKey2));
12125+
12126+
// Clear the client info map.
12127+
testConn.setClientInfo(new Properties());
12128+
clientInfoOut = testConn.getClientInfo();
12129+
assertTrue(clientInfoOut.isEmpty());
12130+
12131+
// Add one client info name=value pair.
12132+
testConn.setClientInfo(clientInfoKey1, clientInfoValue1);
12133+
clientInfoOut = testConn.getClientInfo();
12134+
assertFalse(clientInfoOut.isEmpty());
12135+
assertEquals(1, clientInfoOut.size());
12136+
assertTrue(clientInfoOut.containsKey(clientInfoKey1));
12137+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey1));
12138+
12139+
// Add another client info name=value pair.
12140+
testConn.setClientInfo(clientInfoKey2, clientInfoValue2);
12141+
clientInfoOut = testConn.getClientInfo();
12142+
assertFalse(clientInfoOut.isEmpty());
12143+
assertEquals(2, clientInfoOut.size());
12144+
assertTrue(clientInfoOut.containsKey(clientInfoKey1));
12145+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey1));
12146+
assertTrue(clientInfoOut.containsKey(clientInfoKey2));
12147+
assertEquals(clientInfoValue2, testConn.getClientInfo(clientInfoKey2));
12148+
12149+
// Returned Properties is never the same.
12150+
assertNotSame(testConn.getClientInfo(), testConn.getClientInfo());
12151+
12152+
// Replace one of the client info properties value.
12153+
testConn.setClientInfo(clientInfoKey2, clientInfoValue1);
12154+
clientInfoOut = testConn.getClientInfo();
12155+
assertFalse(clientInfoOut.isEmpty());
12156+
assertEquals(2, clientInfoOut.size());
12157+
assertTrue(clientInfoOut.containsKey(clientInfoKey1));
12158+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey1));
12159+
assertTrue(clientInfoOut.containsKey(clientInfoKey2));
12160+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey2));
12161+
12162+
// Undefined client info property name returns null.
12163+
assertNull(testConn.getClientInfo("undefined"));
12164+
12165+
// Clear one of the client info properties.
12166+
testConn.setClientInfo(clientInfoKey2, null);
12167+
clientInfoOut = testConn.getClientInfo();
12168+
assertFalse(clientInfoOut.isEmpty());
12169+
assertEquals(1, clientInfoOut.size());
12170+
assertTrue(clientInfoOut.containsKey(clientInfoKey1));
12171+
assertEquals(clientInfoValue1, testConn.getClientInfo(clientInfoKey1));
12172+
12173+
// Clear the client info map.
12174+
testConn.setClientInfo(null);
12175+
clientInfoOut = testConn.getClientInfo();
12176+
assertTrue(clientInfoOut.isEmpty());
12177+
}
12178+
}
12179+
1209312180
}

0 commit comments

Comments
 (0)