Fixed - ByteBuf leaks when one of multiple parameters can't be encoded. #4576

pull/4597/head
Nikita Koksharov 2 years ago
parent 801ad8510d
commit 5f76910cc7

@ -16,6 +16,7 @@
package org.redisson;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import org.redisson.api.LocalCachedMapOptions;
import org.redisson.api.LocalCachedMapOptions.ReconnectionStrategy;
import org.redisson.api.LocalCachedMapOptions.SyncStrategy;
@ -826,7 +827,14 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
try {
mapKeys.add(encodeMapKey(value.getKey()));
} catch (Exception e) {
mapKeys.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
result.add((V) value.getValue());
}
@ -869,7 +877,14 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
if (value == null) {
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
try {
mapKeys.add(encodeMapKey(value.getKey()));
} catch (Exception e) {
mapKeys.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
result.put((K) value.getKey(), (V) value.getValue());
}
@ -925,7 +940,14 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
try {
mapKeys.add(encodeMapKey(value.getKey()));
} catch (Exception e) {
mapKeys.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
result.add(new AbstractMap.SimpleEntry<K, V>((K) value.getKey(), (V) value.getValue()));
}

@ -16,6 +16,7 @@
package org.redisson;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import org.redisson.api.*;
import org.redisson.api.MapOptions.WriteMode;
import org.redisson.api.mapreduce.RMapReduce;
@ -768,13 +769,7 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
protected RFuture<Void> putAllOperationAsync(Map<? extends K, ? extends V> map) {
List<Object> params = new ArrayList<>(map.size()*2 + 1);
params.add(getRawName());
for (java.util.Map.Entry<? extends K, ? extends V> t : map.entrySet()) {
checkKey(t.getKey());
checkValue(t.getValue());
params.add(encodeMapKey(t.getKey()));
params.add(encodeMapValue(t.getValue()));
}
encodeMapKeys(params, map);
RFuture<Void> future = commandExecutor.writeAsync(getRawName(), codec, RedisCommands.HMSET, params.toArray());
return future;
@ -1043,6 +1038,23 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
}
}
protected void encodeMapKeys(Collection<Object> params, Map<?, ?> map) {
try {
for (java.util.Map.Entry<?, ?> t : map.entrySet()) {
checkKey(t.getKey());
checkValue(t.getValue());
params.add(encodeMapKey(t.getKey()));
params.add(encodeMapValue(t.getValue()));
}
} catch (Exception e) {
params.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
return get(replaceAsync(key, oldValue, newValue));
@ -1430,9 +1442,7 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
protected RFuture<List<Long>> fastRemoveOperationBatchAsync(K... keys) {
List<Object> args = new ArrayList<>(keys.length);
for (K key : keys) {
args.add(encodeMapKey(key));
}
encodeMapKeys(args, Arrays.asList(keys));
RFuture<List<Long>> future = commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LIST,
"local result = {}; " +
@ -1449,9 +1459,7 @@ public class RedissonMap<K, V> extends RedissonExpirable implements RMap<K, V> {
protected RFuture<Long> fastRemoveOperationAsync(K... keys) {
List<Object> args = new ArrayList<>(keys.length + 1);
args.add(getRawName());
for (K key : keys) {
args.add(encodeMapKey(key));
}
encodeMapKeys(args, Arrays.asList(keys));
return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.HDEL, args.toArray());
}

@ -227,14 +227,11 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
@Override
public RFuture<Map<K, V>> getAllOperationAsync(Set<K> keys) {
List<Object> args = new ArrayList<Object>(keys.size() + 1);
List<Object> plainKeys = new ArrayList<Object>(keys.size());
List<Object> args = new ArrayList<>(keys.size() + 1);
List<Object> plainKeys = new ArrayList<>(keys);
args.add(System.currentTimeMillis());
for (K key : keys) {
plainKeys.add(key);
args.add(encodeMapKey(key));
}
encodeMapKeys(args, keys);
return commandExecutor.evalWriteAsync(getRawName(), codec, new RedisCommand<Map<Object, Object>>("EVAL",
new MapValueDecoder(new MapGetAllDecoder(plainKeys, 0))),
@ -1441,10 +1438,8 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
@Override
protected RFuture<List<Long>> fastRemoveOperationBatchAsync(K... keys) {
List<Object> args = new ArrayList<Object>(keys.length);
for (K key : keys) {
args.add(encodeMapKey(key));
}
List<Object> args = new ArrayList<>(keys.length);
encodeMapKeys(args, Arrays.asList(keys));
RFuture<List<Long>> future = commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LIST,
"local maxSize = tonumber(redis.call('hget', KEYS[6], 'max-size')); "
@ -1475,10 +1470,8 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
@Override
protected RFuture<Long> fastRemoveOperationAsync(K... keys) {
List<Object> params = new ArrayList<Object>(keys.length);
for (K key : keys) {
params.add(encodeMapKey(key));
}
List<Object> params = new ArrayList<>(keys.length);
encodeMapKeys(params, Arrays.asList(keys));
return commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_LONG,
"local maxSize = tonumber(redis.call('hget', KEYS[6], 'max-size')); "
@ -2082,17 +2075,7 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
protected RFuture<Void> putAllOperationAsync(Map<? extends K, ? extends V> map) {
List<Object> params = new ArrayList<Object>(map.size()*2 + 1);
params.add(System.currentTimeMillis());
for (java.util.Map.Entry<? extends K, ? extends V> t : map.entrySet()) {
if (t.getKey() == null) {
throw new NullPointerException("map key can't be null");
}
if (t.getValue() == null) {
throw new NullPointerException("map value can't be null");
}
params.add(encodeMapKey(t.getKey()));
params.add(encodeMapValue(t.getValue()));
}
encodeMapKeys(params, map);
return commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_VOID,
"local currentTime = tonumber(table.remove(ARGV, 1)); " + // index is the first parameter
@ -2187,17 +2170,7 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
ttlTimeout = System.currentTimeMillis() + ttlUnit.toMillis(ttl);
}
params.add(ttlTimeout);
for (java.util.Map.Entry<? extends K, ? extends V> t : map.entrySet()) {
if (t.getKey() == null) {
throw new NullPointerException("map key can't be null");
}
if (t.getValue() == null) {
throw new NullPointerException("map value can't be null");
}
params.add(encodeMapKey(t.getKey()));
params.add(encodeMapValue(t.getValue()));
}
encodeMapKeys(params, map);
return commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_VOID,
"local currentTime = tonumber(table.remove(ARGV, 1)); " + // index is the first parameter

@ -16,6 +16,7 @@
package org.redisson;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import org.redisson.api.*;
import org.redisson.client.codec.ByteArrayCodec;
import org.redisson.client.codec.Codec;
@ -260,8 +261,15 @@ public abstract class RedissonObject implements RObject {
}
public void encode(Collection<Object> params, Collection<?> values) {
for (Object object : values) {
params.add(encode(object));
try {
for (Object object : values) {
params.add(encode(object));
}
} catch (Exception e) {
params.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
}
@ -282,16 +290,30 @@ public abstract class RedissonObject implements RObject {
keyState.release();
}
}
protected void encodeMapKeys(Collection<Object> params, Collection<?> values) {
for (Object object : values) {
params.add(encodeMapKey(object));
try {
for (Object object : values) {
params.add(encodeMapKey(object));
}
} catch (Exception e) {
params.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
}
protected void encodeMapValues(Collection<Object> params, Collection<?> values) {
for (Object object : values) {
params.add(encodeMapValue(object));
try {
for (Object object : values) {
params.add(encodeMapValue(object));
}
} catch (Exception e) {
params.forEach(v -> {
ReferenceCountUtil.safeRelease(v);
});
throw e;
}
}

@ -2093,9 +2093,7 @@ public class JCache<K, V> extends RedissonObject implements Cache<K, V>, CacheAs
params.add(System.currentTimeMillis());
params.add(syncId);
for (Object key : keys) {
params.add(encodeMapKey(key));
}
encodeMapKeys(params, keys);
String script = "local syncs = 0; "
+ "local values = {}; "

Loading…
Cancel
Save