diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/Checksum.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/Checksum.java index 0e3e9e005ed0b5..8e05adf0247585 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/Checksum.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/Checksum.java @@ -20,6 +20,13 @@ /** The content checksum for an HTTP download, which knows its own type. */ public class Checksum { + /** Exception thrown to indicate that a string is not a valid checksum for that key type. */ + public static final class InvalidChecksumException extends Exception { + private InvalidChecksumException(KeyType keyType, String hash) { + super("Invalid " + keyType + " checksum '" + hash + "'"); + } + } + private final KeyType keyType; private final HashCode hashCode; @@ -29,15 +36,16 @@ private Checksum(KeyType keyType, HashCode hashCode) { } /** Constructs a new Checksum for a given key type and hash, in hex format. */ - public static Checksum fromString(KeyType keyType, String hash) { + public static Checksum fromString(KeyType keyType, String hash) throws InvalidChecksumException { if (!keyType.isValid(hash)) { - throw new IllegalArgumentException("Invalid " + keyType + " checksum '" + hash + "'"); + throw new InvalidChecksumException(keyType, hash); } return new Checksum(keyType, HashCode.fromString(hash)); } /** Constructs a new Checksum from a hash in Subresource Integrity format. */ - public static Checksum fromSubresourceIntegrity(String integrity) { + public static Checksum fromSubresourceIntegrity(String integrity) + throws InvalidChecksumException { Base64.Decoder decoder = Base64.getDecoder(); KeyType keyType = null; byte[] hash = null; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java index 34cd842cf358f6..439bfd55ad8521 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java @@ -975,7 +975,14 @@ private Checksum calculateChecksum(Optional originalChecksum, Path pat // The checksum is checked on download, so if we got here, the user provided checksum is good return originalChecksum.get(); } - return Checksum.fromString(KeyType.SHA256, RepositoryCache.getChecksum(KeyType.SHA256, path)); + try { + return Checksum.fromString(KeyType.SHA256, RepositoryCache.getChecksum(KeyType.SHA256, path)); + } catch (Checksum.InvalidChecksumException e) { + throw new IllegalStateException( + "Unexpected invalid checksum from internal computation of SHA-256 checksum on " + + path.getPathString(), + e); + } } private Optional validateChecksum(String sha256, String integrity, List urls) @@ -986,7 +993,7 @@ private Optional validateChecksum(String sha256, String integrity, Lis } try { return Optional.of(Checksum.fromString(KeyType.SHA256, sha256)); - } catch (IllegalArgumentException e) { + } catch (Checksum.InvalidChecksumException e) { warnAboutChecksumError(urls, e.getMessage()); throw new RepositoryFunctionException( Starlark.errorf( @@ -1002,7 +1009,7 @@ private Optional validateChecksum(String sha256, String integrity, Lis try { return Optional.of(Checksum.fromSubresourceIntegrity(integrity)); - } catch (IllegalArgumentException e) { + } catch (Checksum.InvalidChecksumException e) { warnAboutChecksumError(urls, e.getMessage()); throw new RepositoryFunctionException( Starlark.errorf( diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerIntegrationTest.java index 743debcfe9d3dc..930a750b768e72 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerIntegrationTest.java @@ -80,10 +80,16 @@ public class HttpConnectorMultiplexerIntegrationTest { private final HttpConnectorMultiplexer multiplexer = new HttpConnectorMultiplexer(eventHandler, connector, httpStreamFactory, clock, sleeper); + private static Optional makeChecksum(String string) { + try { + return Optional.of(Checksum.fromString(KeyType.SHA256, string)); + } catch (Checksum.InvalidChecksumException e) { + throw new IllegalStateException(e); + } + } + private static final Optional HELLO_SHA256 = - Optional.of( - Checksum.fromString( - KeyType.SHA256, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")); + makeChecksum("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"); @Before public void before() throws Exception { diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerTest.java index 1df50e6b9c4992..d82c89a77d4512 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerTest.java @@ -73,10 +73,16 @@ public class HttpConnectorMultiplexerTest { private static final byte[] data2 = "second".getBytes(UTF_8); private static final byte[] data3 = "third".getBytes(UTF_8); + private static Optional makeChecksum(String string) { + try { + return Optional.of(Checksum.fromString(KeyType.SHA256, string)); + } catch (Checksum.InvalidChecksumException e) { + throw new IllegalStateException(e); + } + } + private static final Optional DUMMY_CHECKSUM = - Optional.of( - Checksum.fromString( - KeyType.SHA256, "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd")); + makeChecksum("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"); @Rule public final ExpectedException thrown = ExpectedException.none(); diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpStreamTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpStreamTest.java index 84cd37af0a05f4..bdfd83ac2623c4 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpStreamTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpStreamTest.java @@ -59,14 +59,19 @@ public class HttpStreamTest { private static final Random randoCalrissian = new Random(); private static final byte[] data = "hello".getBytes(UTF_8); + + private static Optional makeChecksum(String string) { + try { + return Optional.of(Checksum.fromString(KeyType.SHA256, string)); + } catch (Checksum.InvalidChecksumException e) { + throw new IllegalStateException(e); + } + } + private static final Optional GOOD_CHECKSUM = - Optional.of( - Checksum.fromString( - KeyType.SHA256, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")); + makeChecksum("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"); private static final Optional BAD_CHECKSUM = - Optional.of( - Checksum.fromString( - KeyType.SHA256, "0000000000000000000000000000000000000000000000000000000000000000")); + makeChecksum("0000000000000000000000000000000000000000000000000000000000000000"); private static final URL AURL = makeUrl("http://doodle.example"); @Rule @@ -180,9 +185,7 @@ public void bigDataWithValidChecksum_readsOk() throws Exception { streamFactory.create( connection, AURL, - Optional.of( - Checksum.fromString( - KeyType.SHA256, Hashing.sha256().hashBytes(bigData).toString())), + makeChecksum(Hashing.sha256().hashBytes(bigData).toString()), reconnector)) { assertThat(toByteArray(stream)).isEqualTo(bigData); } diff --git a/src/test/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloaderTest.java b/src/test/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloaderTest.java index 202bffd69d0e96..da7be03d003758 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloaderTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloaderTest.java @@ -229,7 +229,7 @@ public void fetchBlob( downloadBlob( downloader, new URL("http://example.com/content.txt"), - Optional.of(Checksum.fromString(KeyType.SHA256, contentDigest.getHash()))); + Optional.of(Checksum.fromString(KeyType.SHA256, contentDigest.getHash()))); assertThat(downloaded).isEqualTo(content); } @@ -272,8 +272,7 @@ public void fetchBlob( downloadBlob( downloader, new URL("http://example.com/content.txt"), - Optional.of( - Checksum.fromString(KeyType.SHA256, contentDigest.getHash())))); + Optional.of(Checksum.fromString(KeyType.SHA256, contentDigest.getHash())))); assertThat(e).hasMessageThat().contains(contentDigest.getHash()); assertThat(e).hasMessageThat().contains(DIGEST_UTIL.computeAsUtf8("wrong content").getHash());