Skip to content

Commit 5c299e2

Browse files
Client setinfo ignore all exception (#3449)
This PR contains the following changes: 1. Check the character legality of clientName in advance through `validateClientInfo`, so that character exceptions are ignored in `initializeFromClientConfig`. 2. Move the `select` command out of the fire-and-forget message (we care about its return value). 3. For the test of RedisCredentials, we gave it "invalidPass" for the first time to make it fail the verification instead of skipping the verification.
1 parent 70f7ea8 commit 5c299e2

File tree

3 files changed

+67
-33
lines changed

3 files changed

+67
-33
lines changed

src/main/java/redis/clients/jedis/Connection.java

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import redis.clients.jedis.exceptions.JedisConnectionException;
2121
import redis.clients.jedis.exceptions.JedisDataException;
2222
import redis.clients.jedis.exceptions.JedisException;
23+
import redis.clients.jedis.exceptions.JedisValidationException;
2324
import redis.clients.jedis.util.IOUtils;
2425
import redis.clients.jedis.util.JedisMetaInfo;
2526
import redis.clients.jedis.util.RedisInputStream;
@@ -370,6 +371,23 @@ public List<Object> getMany(final int count) {
370371
return responses;
371372
}
372373

374+
/**
375+
* Check if the client name libname, libver, characters are legal
376+
* @param info the name
377+
* @return Returns true if legal, false throws exception
378+
* @throws JedisException if characters illegal
379+
*/
380+
private static boolean validateClientInfo(String info) {
381+
for (int i = 0; i < info.length(); i++) {
382+
char c = info.charAt(i);
383+
if (c < '!' || c > '~') {
384+
throw new JedisValidationException("client info cannot contain spaces, "
385+
+ "newlines or special characters.");
386+
}
387+
}
388+
return true;
389+
}
390+
373391
private void initializeFromClientConfig(JedisClientConfig config) {
374392
try {
375393
connect();
@@ -387,9 +405,12 @@ private void initializeFromClientConfig(JedisClientConfig config) {
387405

388406
Supplier<RedisCredentials> credentialsProvider = config.getCredentialsProvider();
389407
if (credentialsProvider instanceof RedisCredentialsProvider) {
390-
((RedisCredentialsProvider) credentialsProvider).prepare();
391-
auth(credentialsProvider);
392-
((RedisCredentialsProvider) credentialsProvider).cleanUp();
408+
try {
409+
((RedisCredentialsProvider) credentialsProvider).prepare();
410+
auth(credentialsProvider);
411+
} finally {
412+
((RedisCredentialsProvider) credentialsProvider).cleanUp();
413+
}
393414
} else {
394415
auth(credentialsProvider);
395416
}
@@ -398,59 +419,37 @@ private void initializeFromClientConfig(JedisClientConfig config) {
398419
hello(protocol);
399420
}
400421
}
401-
/// HELLO and AUTH
402-
403-
List<CommandArguments> fireAndForgetMsg = new ArrayList<>();
404422

405423
int dbIndex = config.getDatabase();
406424
if (dbIndex > 0) {
407-
fireAndForgetMsg.add(new CommandArguments(Command.SELECT).add(Protocol.toByteArray(dbIndex)));
425+
select(dbIndex);
408426
}
409427

428+
List<CommandArguments> fireAndForgetMsg = new ArrayList<>();
429+
410430
String clientName = config.getClientName();
411-
if (doClientName && clientName != null) {
431+
if (doClientName && clientName != null && validateClientInfo(clientName)) {
412432
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETNAME).add(clientName));
413433
}
414434

415435
String libName = JedisMetaInfo.getArtifactId();
416-
if (libName != null) {
436+
if (libName != null && validateClientInfo(libName)) {
417437
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
418438
.add(ClientAttributeOption.LIB_NAME.getRaw()).add(libName));
419439
}
420440

421441
String libVersion = JedisMetaInfo.getVersion();
422-
if (libVersion != null) {
442+
if (libVersion != null && validateClientInfo(libVersion)) {
423443
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
424444
.add(ClientAttributeOption.LIB_VER.getRaw()).add(libVersion));
425445
}
426446

427447
for (CommandArguments arg : fireAndForgetMsg) {
428448
sendCommand(arg);
429449
}
430-
431-
List<Object> objects = getMany(fireAndForgetMsg.size());
432-
for (Object obj : objects) {
433-
if (obj instanceof JedisDataException) {
434-
JedisDataException e = (JedisDataException)obj;
435-
String errorMsg = e.getMessage().toUpperCase();
436-
/**
437-
* 1. Redis 4.0 and before, we need to ignore `Syntax error`.
438-
* 2. Redis 5.0 and later, we need to ignore `Unknown subcommand error`.
439-
* 3. Because Jedis allows Jedis jedis = new Jedis() in advance, and jedis.auth(password) later,
440-
* we need to ignore `NOAUTH errors`.
441-
*/
442-
if (errorMsg.contains("SYNTAX") ||
443-
errorMsg.contains("UNKNOWN") ||
444-
errorMsg.contains("NOAUTH")) { // TODO: not filter out NOAUTH
445-
// ignore
446-
} else {
447-
throw e;
448-
}
449-
}
450-
}
450+
getMany(fireAndForgetMsg.size());
451451
} catch (JedisException je) {
452452
try {
453-
setBroken();
454453
disconnect();
455454
} catch (Exception e) {
456455
// the first exception 'je' will be thrown
@@ -504,6 +503,11 @@ private void auth(final Supplier<RedisCredentials> credentialsProvider) {
504503
getStatusCodeReply(); // OK
505504
}
506505

506+
public String select(final int index) {
507+
sendCommand(Protocol.Command.SELECT, Protocol.toByteArray(index));
508+
return getStatusCodeReply();
509+
}
510+
507511
public boolean ping() {
508512
sendCommand(Protocol.Command.PING);
509513
String status = getStatusCodeReply();

src/test/java/redis/clients/jedis/JedisPoolTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.apache.commons.pool2.PooledObjectFactory;
1414
import org.apache.commons.pool2.impl.DefaultPooledObject;
1515
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
16+
import org.junit.Assert;
1617
import org.junit.Test;
1718

1819
import redis.clients.jedis.exceptions.InvalidURIException;
@@ -219,6 +220,17 @@ public void customClientName() {
219220
}
220221
}
221222

223+
@Test
224+
public void invalidClientName() {
225+
try (JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,
226+
"foobared", 0, "invalid client name"); Jedis jedis = pool.getResource()) {
227+
} catch (Exception e) {
228+
if (!e.getMessage().startsWith("client info cannot contain space")) {
229+
Assert.fail("invalid client name test fail");
230+
}
231+
}
232+
}
233+
222234
@Test
223235
public void returnResourceDestroysResourceOnException() {
224236

src/test/java/redis/clients/jedis/JedisPooledTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.concurrent.atomic.AtomicBoolean;
1414
import java.util.concurrent.atomic.AtomicInteger;
1515
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
16+
import org.junit.Assert;
1617
import org.junit.Test;
1718

1819
import redis.clients.jedis.exceptions.JedisConnectionException;
@@ -102,6 +103,18 @@ public void customClientName() {
102103
}
103104
}
104105

106+
@Test
107+
public void invalidClientName() {
108+
try (JedisPooled pool = new JedisPooled(hnp, DefaultJedisClientConfig.builder()
109+
.clientName("invalid client name").build());
110+
Connection jedis = pool.getPool().getResource()) {
111+
} catch (Exception e) {
112+
if (!e.getMessage().startsWith("client info cannot contain space")) {
113+
Assert.fail("invalid client name test fail");
114+
}
115+
}
116+
}
117+
105118
@Test
106119
public void getNumActiveWhenPoolIsClosed() {
107120
JedisPooled pool = new JedisPooled(hnp);
@@ -194,7 +207,12 @@ public void prepare() {
194207
@Override
195208
public RedisCredentials get() {
196209
if (!validPassword.get()) {
197-
return new RedisCredentials() { };
210+
return new RedisCredentials() {
211+
@Override
212+
public char[] getPassword() {
213+
return "invalidPass".toCharArray();
214+
}
215+
};
198216
}
199217

200218
return new RedisCredentials() {

0 commit comments

Comments
 (0)