diff --git a/Lagrange.Core/Message/Entities/MultiMsgEntity.cs b/Lagrange.Core/Message/Entities/MultiMsgEntity.cs index 44be011c..d7aca564 100644 --- a/Lagrange.Core/Message/Entities/MultiMsgEntity.cs +++ b/Lagrange.Core/Message/Entities/MultiMsgEntity.cs @@ -26,9 +26,34 @@ public async Task Preprocess(BotContext context, BotMessage message) { if (string.IsNullOrEmpty(ResId)) { + // Recursively preprocess internal messages + Console.WriteLine($"[MultiMsgEntity] Preprocessing {Messages.Count} messages for forward chain..."); + + foreach (var innerMsg in Messages) + { + foreach (var entity in innerMsg.Entities) + { + try + { + await entity.Preprocess(context, message); + + if (entity is ImageEntity img) + { + if (img.MsgInfo != null) + Console.WriteLine($"[MultiMsgEntity] Image uploaded successfully. Size: {img.ImageSize}"); + else + Console.WriteLine("[MultiMsgEntity] WARNING: Image MsgInfo is NULL after preprocess!"); + } + } + catch (Exception ex) + { + Console.WriteLine($"[MultiMsgEntity] Error preprocessing entity: {ex.Message}"); + } + } + } + var result = await context.EventContext.SendEvent(new LongMsgSendEventReq(message.Receiver, Messages)); ResId = result.ResId; - } } diff --git a/Lagrange.Proto.Test/CrashTest.cs b/Lagrange.Proto.Test/CrashTest.cs new file mode 100644 index 00000000..6b4c37f8 --- /dev/null +++ b/Lagrange.Proto.Test/CrashTest.cs @@ -0,0 +1,45 @@ +using NUnit.Framework; +using Lagrange.Proto.Utility; + +namespace Lagrange.Proto.Test +{ + [TestFixture] + public class CrashTest + { + [Test] + public void TestNegativeInt32VarIntLength() + { + // This test is used to reproduce the IndexOutOfRangeException Bug + int value = -1; + + int length = ProtoHelper.GetVarIntLength(value); + + // Verify: For a 32-bit all-ones number (0xFFFF), VarInt encoding should be 5 bytes + Assert.That(length, Is.EqualTo(5)); + } + + [Test] + public void TestNegativeInt64VarIntLength() + { + long value = -1; + + // For 64-bit numbers with all 1s, VarInt encoding should be 10 bytes + int length = ProtoHelper.GetVarIntLength(value); + + Assert.That(length, Is.EqualTo(10)); + } + + [Test] + public void TestOtherNegativeValues() + { + // Test other negative values to ensure stability + int val1 = -100; + int len1 = ProtoHelper.GetVarIntLength(val1); + Assert.That(len1, Is.GreaterThan(0)); + + long val2 = long.MinValue; // 0x8000000000000000 + int len2 = ProtoHelper.GetVarIntLength(val2); + Assert.That(len2, Is.EqualTo(10)); + } + } +} \ No newline at end of file diff --git a/Lagrange.Proto/Primitives/ProtoWriter.cs b/Lagrange.Proto/Primitives/ProtoWriter.cs index 55b5da29..a59946b2 100644 --- a/Lagrange.Proto/Primitives/ProtoWriter.cs +++ b/Lagrange.Proto/Primitives/ProtoWriter.cs @@ -96,7 +96,8 @@ public void EncodeVarInt(T value) where T : unmanaged, INumber { if (_memory.Length - BytesPending >= 10) { - if (value < T.CreateTruncating(0x80)) + // For-1 (int), converting to ulong is 0xFF... FF, much greater than 0x80, will not mistakenly enter this branch. + if (ulong.CreateTruncating(value) < 0x80) { Unsafe.Add(ref MemoryMarshal.GetReference(_memory.Span), BytesPending++) = byte.CreateTruncating(value); return; diff --git a/Lagrange.Proto/Utility/ProtoHelper.cs b/Lagrange.Proto/Utility/ProtoHelper.cs index 01517c05..399db314 100644 --- a/Lagrange.Proto/Utility/ProtoHelper.cs +++ b/Lagrange.Proto/Utility/ProtoHelper.cs @@ -36,12 +36,12 @@ public static unsafe int GetVarIntLength(T value) where T : unmanaged, INumbe if (sizeof(T) <= 4) { - int leadingZeros = BitOperations.LeadingZeroCount(uint.CreateSaturating(value)); + int leadingZeros = BitOperations.LeadingZeroCount(uint.CreateTruncating(value)); return VarIntLengths32[leadingZeros]; } else { - int leadingZeros = BitOperations.LeadingZeroCount(ulong.CreateSaturating(value)); + int leadingZeros = BitOperations.LeadingZeroCount(ulong.CreateTruncating(value)); return VarIntLengths64[leadingZeros]; } } @@ -98,4 +98,4 @@ public static int CountBytes(ReadOnlySpan str) { return GetVarIntLength(str.Length) + str.Length; } -} \ No newline at end of file +}