Skip to content

Commit 133196b

Browse files
committed
urlencode keys to protect against malformed keys
1 parent 92129e6 commit 133196b

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/com/danga/MemCached/MemCachedClient.java

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.*;
3434
import java.util.zip.*;
3535
import java.io.*;
36+
import java.net.URLEncoder;
3637

3738
import org.apache.log4j.Logger;
3839

@@ -346,6 +347,14 @@ public boolean delete( String key, Integer hashCode, Date expiry ) {
346347
return false;
347348
}
348349

350+
try {
351+
key = sanitizeKey( key );
352+
}
353+
catch ( UnsupportedEncodingException e ) {
354+
log.error( "failed to sanitize your key!", e );
355+
return false;
356+
}
357+
349358
// get SockIO obj from hash or from key
350359
SockIOPool.SockIO sock = SockIOPool.getInstance( poolName ).getSock( key, hashCode );
351360

@@ -574,6 +583,14 @@ private boolean set( String cmdname, String key, Object value, Date expiry, Inte
574583
return false;
575584
}
576585

586+
try {
587+
key = sanitizeKey( key );
588+
}
589+
catch ( UnsupportedEncodingException e ) {
590+
log.error( "failed to sanitize your key!", e );
591+
return false;
592+
}
593+
577594
if ( value == null ) {
578595
log.error( "trying to store a null value to cache" );
579596
return false;
@@ -604,7 +621,7 @@ private boolean set( String cmdname, String key, Object value, Date expiry, Inte
604621
val = value.toString().getBytes( defaultEncoding );
605622
}
606623
catch ( UnsupportedEncodingException ue ) {
607-
log.error( "invalid encoding type used: " + defaultEncoding );
624+
log.error( "invalid encoding type used: " + defaultEncoding, ue );
608625
sock.close();
609626
sock = null;
610627
return false;
@@ -776,6 +793,14 @@ public long getCounter( String key, Integer hashCode ) {
776793
return -1;
777794
}
778795

796+
try {
797+
key = sanitizeKey( key );
798+
}
799+
catch ( UnsupportedEncodingException e ) {
800+
log.error( "failed to sanitize your key!", e );
801+
return -1;
802+
}
803+
779804
long counter = -1;
780805
try {
781806
counter = Long.parseLong( (String)get( key, hashCode, true ) );
@@ -871,6 +896,19 @@ public long decr( String key, long inc, Integer hashCode ) {
871896
*/
872897
private long incrdecr( String cmdname, String key, long inc, Integer hashCode ) {
873898

899+
if ( key == null ) {
900+
log.error( "null key for incrdecr()" );
901+
return -1;
902+
}
903+
904+
try {
905+
key = sanitizeKey( key );
906+
}
907+
catch ( UnsupportedEncodingException e ) {
908+
log.error( "failed to sanitize your key!", e );
909+
return -1;
910+
}
911+
874912
// get SockIO obj for given cache key
875913
SockIOPool.SockIO sock = SockIOPool.getInstance( poolName ).getSock(key, hashCode);
876914

@@ -980,6 +1018,14 @@ public Object get( String key, Integer hashCode, boolean asString ) {
9801018
return null;
9811019
}
9821020

1021+
try {
1022+
key = sanitizeKey( key );
1023+
}
1024+
catch ( UnsupportedEncodingException e ) {
1025+
log.error( "failed to sanitize your key!", e );
1026+
return false;
1027+
}
1028+
9831029
// get SockIO obj using cache key
9841030
SockIOPool.SockIO sock = SockIOPool.getInstance( poolName ).getSock( key, hashCode );
9851031

@@ -1140,8 +1186,23 @@ public Map<String,Object> getMulti( String[] keys, Integer[] hashCodes, boolean
11401186
if ( hashCodes != null && hashCodes.length > i )
11411187
hash = hashCodes[ i ];
11421188

1189+
String key = keys[i];
1190+
1191+
if ( key == null ) {
1192+
log.error( "null key, so skipping" );
1193+
continue;
1194+
}
1195+
1196+
try {
1197+
key = sanitizeKey( key );
1198+
}
1199+
catch ( UnsupportedEncodingException e ) {
1200+
log.error( "failed to sanitize your key!", e );
1201+
continue;
1202+
}
1203+
11431204
// get SockIO obj from cache key
1144-
SockIOPool.SockIO sock = SockIOPool.getInstance( poolName ).getSock( keys[i], hash );
1205+
SockIOPool.SockIO sock = SockIOPool.getInstance( poolName ).getSock( key, hash );
11451206

11461207
if ( sock == null )
11471208
continue;
@@ -1150,7 +1211,7 @@ public Map<String,Object> getMulti( String[] keys, Integer[] hashCodes, boolean
11501211
if ( !sockKeys.containsKey( sock.getHost() ) )
11511212
sockKeys.put( sock.getHost(), new StringBuilder() );
11521213

1153-
sockKeys.get( sock.getHost() ).append( " " + keys[i] );
1214+
sockKeys.get( sock.getHost() ).append( " " + key );
11541215

11551216
// return to pool
11561217
sock.close();
@@ -1303,6 +1364,10 @@ else if ( END.equals( line ) ) {
13031364
}
13041365
}
13051366

1367+
private String sanitizeKey( String key ) throws UnsupportedEncodingException {
1368+
return URLEncoder.encode( key, "UTF-8" );
1369+
}
1370+
13061371
/**
13071372
* Invalidates the entire cache.
13081373
*

src/com/danga/MemCached/test/UnitTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ public static void test16() {
153153
assert !mc.set( "foo", null );
154154
}
155155

156+
public static void test17() {
157+
mc.set( "foo bar", Boolean.TRUE );
158+
Boolean b = (Boolean)mc.get( "foo bar" );
159+
assert b.booleanValue();
160+
}
161+
156162
/**
157163
* This runs through some simple tests of the MemCacheClient.
158164
*
@@ -199,5 +205,7 @@ public static void main(String[] args) {
199205
test13();
200206
test14();
201207
test15();
208+
test16();
209+
test17();
202210
}
203211
}

0 commit comments

Comments
 (0)