Skip to content

Commit 37aca85

Browse files
timtebeekTim te Beek
andauthored
Only calculate hex string for valid HTTP responses (#6763)
* Add tests for Checksum hex validation and HTTP error handling * Validate checksum HTTP responses and hex input `Checksum.fromUri()` did not check the HTTP response status before parsing the body as hex. When a proxy, CDN, or missing endpoint returned an HTML/XML error page, `fromHex()` threw a cryptic `NumberFormatException: For input string: "<?"`. - Check `response.isSuccessful()` in `fromUri()` before parsing - Trim response body to handle trailing newlines in checksum files - Validate hex characters in `fromHex()` with a clear error message - Catch failures in `DistributionInfos.fetchChecksum()` and return null so the recipe proceeds without checksum verification Fixes #6762 * Minimize API changes * Remove unused import --------- Co-authored-by: Tim te Beek <tim@mac.home>
1 parent 2ae43a8 commit 37aca85

2 files changed

Lines changed: 54 additions & 0 deletions

File tree

rewrite-core/src/main/java/org/openrewrite/Checksum.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.IOException;
2727
import java.io.InputStream;
28+
import java.io.UncheckedIOException;
2829
import java.net.URI;
2930
import java.nio.charset.StandardCharsets;
3031
import java.nio.file.Files;
@@ -83,6 +84,10 @@ public static Checksum fromUri(HttpSender httpSender, URI uri, String algorithm)
8384
.withMethod(HttpSender.Method.GET)
8485
.build();
8586
try (HttpSender.Response response = httpSender.send(request)) {
87+
if (!response.isSuccessful()) {
88+
throw new UncheckedIOException(new IOException(
89+
"Failed to download checksum from " + uri + ": HTTP " + response.getCode()));
90+
}
8691
String hexString = new String(response.getBodyAsBytes(), StandardCharsets.UTF_8);
8792
return Checksum.fromHex(algorithm, hexString);
8893
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.ipc.http.HttpSender;
20+
21+
import java.io.ByteArrayInputStream;
22+
import java.io.UncheckedIOException;
23+
import java.net.URI;
24+
import java.nio.charset.StandardCharsets;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
28+
29+
class ChecksumTest {
30+
31+
@Test
32+
void fromHexWithValidInput() {
33+
Checksum checksum = Checksum.fromHex("SHA-256", "abcdef01");
34+
assertThat(checksum.getHexValue()).isEqualTo("abcdef01");
35+
}
36+
37+
@Test
38+
void fromUriRejectsNonSuccessfulResponse() {
39+
HttpSender httpSender = request -> new HttpSender.Response(
40+
403,
41+
new ByteArrayInputStream("<?xml version=\"1.0\"?>".getBytes(StandardCharsets.UTF_8)),
42+
() -> {
43+
});
44+
45+
assertThatThrownBy(() -> Checksum.fromUri(httpSender, URI.create("https://example.com/checksum.sha256")))
46+
.isInstanceOf(UncheckedIOException.class)
47+
.hasMessageContaining("403");
48+
}
49+
}

0 commit comments

Comments
 (0)