[fix] 修正解析超大Redis响应包时进行边界处理的缺陷,该问题导致一些超大操作量的指令返回有异常。fix: https://github.com/NewLifeX/NewLife.Redis/issues/157
This commit is contained in:
parent
e4fcca6d49
commit
13bb6e444e
|
@ -45,6 +45,8 @@ public ref struct BufferedReader
|
|||
public void Advance(Int32 count)
|
||||
{
|
||||
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));
|
||||
|
||||
EnsureSpace(count);
|
||||
if (_index + count > _span.Length) throw new ArgumentOutOfRangeException(nameof(count));
|
||||
|
||||
_index += count;
|
||||
|
|
|
@ -560,6 +560,10 @@ public class RedisClient : DisposeBase
|
|||
{
|
||||
arr[i] = ReadBlocks(ref reader, log);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RedisException($"Invalid [{header}] on blocks[{i}/{len}]");
|
||||
}
|
||||
}
|
||||
|
||||
return arr;
|
||||
|
@ -579,7 +583,8 @@ public class RedisClient : DisposeBase
|
|||
|
||||
// 读取数据包,并跳过换行符
|
||||
var pk = reader.ReadPacket(len);
|
||||
if (reader.FreeCapacity >= 2) reader.Advance(2);
|
||||
//if (reader.FreeCapacity >= 2)
|
||||
reader.Advance(2);
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
@ -587,11 +592,13 @@ public class RedisClient : DisposeBase
|
|||
private static String ReadLine(ref BufferedReader reader)
|
||||
{
|
||||
var sb = Pool.StringBuilder.Get();
|
||||
var count = reader.FreeCapacity;
|
||||
for (var i = 0; i < count; i++)
|
||||
// 可能刚好一帧结束,字符串至少需要2个字符
|
||||
//reader.EnsureSpace(2);
|
||||
//var count = reader.FreeCapacity;
|
||||
while (true)
|
||||
{
|
||||
var b = (Char)reader.ReadByte();
|
||||
if (b == '\r' && i + 1 < count)
|
||||
if (b == '\r')
|
||||
{
|
||||
var b2 = (Char)reader.ReadByte();
|
||||
if (b2 == '\n') break;
|
||||
|
@ -610,11 +617,15 @@ public class RedisClient : DisposeBase
|
|||
{
|
||||
Span<Char> span = stackalloc Char[32];
|
||||
var k = 0;
|
||||
var count = reader.FreeCapacity;
|
||||
for (var i = 0; i < count; i++)
|
||||
// 缓冲读取器的FreeCapacity不准确,它可以读取下一帧数据
|
||||
// 可能刚好一帧结束,字符串至少需要2个字符
|
||||
//reader.EnsureSpace(2);
|
||||
//var count = reader.FreeCapacity;
|
||||
//var count = 16;
|
||||
while (true)
|
||||
{
|
||||
var b = (Char)reader.ReadByte();
|
||||
if (b == '\r' && i + 1 < count)
|
||||
if (b == '\r')
|
||||
{
|
||||
var b2 = (Char)reader.ReadByte();
|
||||
if (b2 == '\n') break;
|
||||
|
|
|
@ -114,6 +114,7 @@ public class HashTest
|
|||
|
||||
rh["0"] = new EventInfo { EventId = "1234", EventName = "Stone" };
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "获取所有数据,丢失数据bug")]
|
||||
public void ValuesHashTest()
|
||||
{
|
||||
|
@ -121,8 +122,8 @@ public class HashTest
|
|||
//大批量数据获取,大概率会数据不完整,具体原有不明
|
||||
var key = $"NewLife:HashTestInfo:Test";
|
||||
{
|
||||
_redis.MaxMessageSize = int.MaxValue;
|
||||
var hash = _redis.GetDictionary<string>(key) as RedisHash<string, string>;
|
||||
_redis.MaxMessageSize = Int32.MaxValue;
|
||||
var hash = _redis.GetDictionary<String>(key) as RedisHash<String, String>;
|
||||
hash.Clear();
|
||||
for (var i = 0; i < 10000; i++)
|
||||
{
|
||||
|
@ -134,7 +135,11 @@ public class HashTest
|
|||
var list = hash.Values.ToList();
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
try { var item = list[i].ToJsonEntity<EventInfo>(); }
|
||||
Assert.NotEmpty(list[i]);
|
||||
try
|
||||
{
|
||||
var item = list[i].ToJsonEntity<EventInfo>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//某块连续的数据段可能会不完整
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace XUnitTest
|
|||
public class RedisCacheTests
|
||||
{
|
||||
public readonly ServiceProvider provider;
|
||||
private static readonly string prefix = "myPrefix:";
|
||||
private static readonly String prefix = "myPrefix:";
|
||||
public RedisCacheTests()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
|
|
@ -597,13 +597,13 @@ public class RedisTest
|
|||
var uservalue = rds.Get<User>("user");
|
||||
var user2value = rds.Get<User>("user2");
|
||||
|
||||
var keys = new[] { "user", "user2" };
|
||||
var keys = new[] { "user3", "user", "user2" };
|
||||
var values = rds.GetAll<User>(keys);
|
||||
|
||||
// 应该返回2个值,但是GetALl()这里只返回一个key的值
|
||||
Assert.True(values.Count >= 2);
|
||||
Assert.Equal(3, values.Count);
|
||||
Assert.NotNull(values["user"]);
|
||||
Assert.Null(values["user2"]);
|
||||
Assert.Equal(user.Name, values["user"].Name);
|
||||
Assert.Null(values["user3"]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue