Skip to content

Commit bc78378

Browse files
committed
Fix copying of zero length resources
Fix #14685 by handling zero length resources
1 parent 74763ad commit bc78378

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/internal/ByteChannelContentSource.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ public Content.Chunk read()
155155
try (AutoLock ignored = lock.lock())
156156
{
157157
lockedEnsureOpenOrTerminal();
158+
159+
if (_length == 0)
160+
{
161+
lockedSetTerminal(Content.Chunk.EOF);
162+
return Content.Chunk.EOF;
163+
}
164+
158165
if (_terminal != null)
159166
return _terminal;
160167

@@ -172,7 +179,7 @@ else if (_buffer.isRetained())
172179
{
173180
ByteBuffer byteBuffer = _buffer.getByteBuffer();
174181
BufferUtil.clearToFill(byteBuffer);
175-
if (_length >= 0)
182+
if (_length > 0)
176183
byteBuffer.limit((int)Math.min(_buffer.capacity(), _length - _totalRead));
177184
int read = _byteChannel.read(byteBuffer);
178185
BufferUtil.flipToFlush(byteBuffer, 0);

jetty-core/jetty-io/src/test/java/org/eclipse/jetty/io/IOResourcesTest.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,13 @@ public Content.Source newContentSource(ByteBufferPool.Sized bufferPool, long off
142142
public static Stream<Resource> all() throws Exception
143143
{
144144
Path testResourcePath = MavenTestingUtils.getTestResourcePath("keystore.p12");
145+
145146
URI resourceUri = testResourcePath.toUri();
146147
return Stream.of(
147148
ResourceFactory.root().newResource(resourceUri),
148149
ResourceFactory.root().newMemoryResource(resourceUri.toURL()),
150+
ResourceFactory.root().newResource(MavenTestingUtils.getTestResourcePath("zero")),
151+
ResourceFactory.root().newResource(MavenTestingUtils.getTestResourcePath("one")),
149152
new URLResourceFactory().newResource(resourceUri),
150153
new TestContentSourceFactoryResource(resourceUri, Files.readAllBytes(testResourcePath))
151154
);
@@ -181,12 +184,13 @@ public void testAsContentSourceWithFirst(Resource resource) throws Exception
181184
{
182185
TestSink sink = new TestSink();
183186
Callback.Completable callback = new Callback.Completable();
187+
184188
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 100, -1);
185189
Content.copy(contentSource, sink, callback);
186190
callback.get();
187191
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
188192
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
189-
assertThat(sum, is(resource.length() - 100L));
193+
assertThat(sum, is(Math.max(0L, resource.length() - 100L)));
190194
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
191195
}
192196

@@ -201,7 +205,7 @@ public void testAsContentSourceWithLength(Resource resource) throws Exception
201205
callback.get();
202206
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
203207
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
204-
assertThat(sum, is(500L));
208+
assertThat(sum, is(Math.min(resource.length(), 500L)));
205209
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
206210
}
207211

@@ -211,12 +215,15 @@ public void testAsContentSourceWithFirstAndLength(Resource resource) throws Exce
211215
{
212216
TestSink sink = new TestSink();
213217
Callback.Completable callback = new Callback.Completable();
214-
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 100, 500);
218+
219+
long offset = Math.min(resource.length(), 100);
220+
long length = Math.min(resource.length() - offset, 500);
221+
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, offset, length);
215222
Content.copy(contentSource, sink, callback);
216223
callback.get();
217224
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
218225
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
219-
assertThat(sum, is(500L));
226+
assertThat(sum, is(length));
220227
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
221228
}
222229

@@ -240,11 +247,12 @@ public void testCopyWithFirst(Resource resource) throws Exception
240247
{
241248
TestSink sink = new TestSink();
242249
Callback.Completable callback = new Callback.Completable();
243-
IOResources.copy(resource, sink, bufferPool, 100, -1, callback);
250+
long offset = Math.min(resource.length(), 100);
251+
IOResources.copy(resource, sink, bufferPool, offset, -1, callback);
244252
callback.get();
245253
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
246254
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
247-
assertThat(sum, is(resource.length() - 100L));
255+
assertThat(sum, is(Math.max(0L, resource.length() - 100L)));
248256
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
249257
}
250258

@@ -254,11 +262,12 @@ public void testCopyWithLength(Resource resource) throws Exception
254262
{
255263
TestSink sink = new TestSink();
256264
Callback.Completable callback = new Callback.Completable();
257-
IOResources.copy(resource, sink, bufferPool, 0, 500, callback);
265+
long length = resource.length() >= 0 ? Math.min(resource.length(), 500) : 500;
266+
IOResources.copy(resource, sink, bufferPool, 0, length, callback);
258267
callback.get();
259268
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
260269
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
261-
assertThat(sum, is(500L));
270+
assertThat(sum, is(length));
262271
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
263272
}
264273

@@ -268,11 +277,13 @@ public void testCopyWithFirstAndLength(Resource resource) throws Exception
268277
{
269278
TestSink sink = new TestSink();
270279
Callback.Completable callback = new Callback.Completable();
271-
IOResources.copy(resource, sink, bufferPool, 100, 500, callback);
280+
long offset = Math.min(resource.length(), 100);
281+
long length = Math.min(resource.length() - offset, 500);
282+
IOResources.copy(resource, sink, bufferPool, offset, length, callback);
272283
callback.get();
273284
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
274285
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
275-
assertThat(sum, is(500L));
286+
assertThat(sum, is(length));
276287
assertThat(chunks.get(chunks.size() - 1).isLast(), is(true));
277288
}
278289

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

jetty-core/jetty-io/src/test/resources/zero

Whitespace-only changes.

0 commit comments

Comments
 (0)