Skip to content

Commit 79ccbfa

Browse files
paulirwinclaude
andcommitted
Throw on invalid offset 0 in LZ4 decompression, #1276
Backports upstream Lucene fix apache/lucene#15570 (Lucene 10.4.0): replaces the matchDec > 0 assert in LZ4.Decompress with an IOException so malformed input is rejected in all build modes rather than producing stale buffer contents. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 774bd81 commit 79ccbfa

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using Lucene.Net.Attributes;
2+
using Lucene.Net.Store;
3+
using Lucene.Net.Util;
4+
using NUnit.Framework;
5+
using System.IO;
6+
using Assert = Lucene.Net.TestFramework.Assert;
7+
8+
namespace Lucene.Net.Codecs.Compressing
9+
{
10+
/*
11+
* Licensed to the Apache Software Foundation (ASF) under one or more
12+
* contributor license agreements. See the NOTICE file distributed with
13+
* this work for additional information regarding copyright ownership.
14+
* The ASF licenses this file to You under the Apache License, Version 2.0
15+
* (the "License"); you may not use this file except in compliance with
16+
* the License. You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing, software
21+
* distributed under the License is distributed on an "AS IS" BASIS,
22+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
* See the License for the specific language governing permissions and
24+
* limitations under the License.
25+
*/
26+
27+
[TestFixture]
28+
public class TestDecompressLZ4 : LuceneTestCase
29+
{
30+
// LUCENENET specific: backported from upstream Lucene 10.4.0 (apache/lucene#15570)
31+
[Test]
32+
public void TestDecompressOffset0()
33+
{
34+
byte[] input = new byte[]
35+
{
36+
// token
37+
0xE,
38+
// offset 0 (invalid)
39+
0,
40+
0,
41+
// last literal
42+
// token
43+
7 << 4,
44+
// literal
45+
0,
46+
0,
47+
0,
48+
0,
49+
0,
50+
0,
51+
0
52+
};
53+
54+
byte[] output = new byte[18];
55+
56+
var e = Assert.Throws<IOException>(
57+
() => LZ4.Decompress(new ByteArrayDataInput(input), output.Length, output, 0));
58+
Assert.AreEqual("offset 0 is invalid", e.Message);
59+
}
60+
61+
// LUCENENET specific - confirm the same fail-fast behavior surfaces through the
62+
// CompressionMode.FAST.NewDecompressor() integration path that callers actually use.
63+
[Test, LuceneNetSpecific]
64+
public void TestDecompressOffset0ThroughCompressionMode()
65+
{
66+
byte[] input = new byte[]
67+
{
68+
0xE,
69+
0,
70+
0,
71+
7 << 4,
72+
0,
73+
0,
74+
0,
75+
0,
76+
0,
77+
0,
78+
0
79+
};
80+
81+
Decompressor decompressor = CompressionMode.FAST.NewDecompressor();
82+
BytesRef bytes = new BytesRef();
83+
84+
var e = Assert.Throws<IOException>(
85+
() => decompressor.Decompress(new ByteArrayDataInput(input), 18, 0, 18, bytes));
86+
Assert.AreEqual("offset 0 is invalid", e.Message);
87+
}
88+
}
89+
}

src/Lucene.Net/Codecs/Compressing/LZ4.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Lucene.Net.Diagnostics;
33
using Lucene.Net.Support;
44
using System;
5+
using System.IO;
56
using System.Runtime.CompilerServices;
67

78
namespace Lucene.Net.Codecs.Compressing
@@ -137,7 +138,11 @@ public static int Decompress(DataInput compressed, int decompressedLen, byte[] d
137138
var byte1 = compressed.ReadByte();
138139
var byte2 = compressed.ReadByte();
139140
int matchDec = (byte1 & 0xFF) | ((byte2 & 0xFF) << 8);
140-
if (Debugging.AssertsEnabled) Debugging.Assert(matchDec > 0);
141+
// LUCENENET specific: backported from upstream Lucene 10.4.0 (apache/lucene#15570) - matchDec == 0 is invalid per the LZ4 block format
142+
if (matchDec == 0)
143+
{
144+
throw new IOException("offset 0 is invalid");
145+
}
141146

142147
int matchLen = token & 0x0F;
143148
if (matchLen == 0x0F)

0 commit comments

Comments
 (0)