This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
The following commit(s) were added to refs/heads/master by this push:
new f2ac150d [CODEC-337] Digest ALL reuses System.in, so only the first
algorithm sees the real input (#431)
f2ac150d is described below
commit f2ac150daabcd8aa334b94c3d58c3c1ee695e8e0
Author: Gary Gregory <[email protected]>
AuthorDate: Thu May 21 07:27:10 2026 -0400
[CODEC-337] Digest ALL reuses System.in, so only the first algorithm sees
the real input (#431)
---
.../java/org/apache/commons/codec/cli/Digest.java | 66 ++++++++++++----------
.../org/apache/commons/codec/cli/DigestTest.java | 44 +++++++++++++++
2 files changed, 79 insertions(+), 31 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/cli/Digest.java
b/src/main/java/org/apache/commons/codec/cli/Digest.java
index c887e495..7e1f5283 100644
--- a/src/main/java/org/apache/commons/codec/cli/Digest.java
+++ b/src/main/java/org/apache/commons/codec/cli/Digest.java
@@ -14,8 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.commons.codec.cli;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -36,18 +38,17 @@ import
org.apache.commons.codec.digest.MessageDigestAlgorithms;
*/
public class Digest {
+ private static final String EMPTY = "";
+
/**
- * Runs the digest algorithm in {@code args[0]} on the file in {@code
args[1]}. If there is no {@code args[1]}, use
- * standard input.
+ * Runs the digest algorithm in {@code args[0]} on the file in {@code
args[1]}. If there is no {@code args[1]}, use standard input.
*
* <p>
* The algorithm can also be {@code ALL} or {@code *} to output one line
for each known algorithm.
* </p>
*
- * @param args
- * {@code args[0]} is one of {@link MessageDigestAlgorithms}
name,
- * {@link MessageDigest} name, {@code ALL}, or {@code *}.
- * {@code args[1+]} is a FILE/DIRECTORY/String.
+ * @param args {@code args[0]} is one of {@link MessageDigestAlgorithms}
name, {@link MessageDigest} name, {@code ALL}, or {@code *}. {@code args[1+]}
is a
+ * FILE/DIRECTORY/String.
* @throws IOException if an error occurs.
*/
public static void main(final String[] args) throws IOException {
@@ -62,16 +63,11 @@ public class Digest {
Objects.requireNonNull(args);
final int argsLength = args.length;
if (argsLength == 0) {
- throw new IllegalArgumentException(
- String.format("Usage: java %s [algorithm]
[FILE|DIRECTORY|string] ...", Digest.class.getName()));
+ throw new IllegalArgumentException(String.format("Usage: java %s
[algorithm] [FILE|DIRECTORY|string] ...", Digest.class.getName()));
}
this.args = args;
this.algorithm = args[0];
- if (argsLength <= 1) {
- this.inputs = null;
- } else {
- this.inputs = Arrays.copyOfRange(args, 1, argsLength);
- }
+ this.inputs = argsLength > 1 ? Arrays.copyOfRange(args, 1, argsLength)
: null;
}
private void println(final String prefix, final byte[] digest) {
@@ -84,25 +80,26 @@ public class Digest {
// where '*' is used for binary files
// shasum(1) has a -b option which generates " *" separator
// we don't distinguish binary files at present
- System.out.println(prefix + Hex.encodeHexString(digest) + (fileName !=
null ? " " + fileName : ""));
+ System.out.println(prefix + Hex.encodeHexString(digest) + (fileName !=
null ? " " + fileName : EMPTY));
}
private void run() throws IOException {
+ final BufferedInputStream systemIn = inputs != null ? null : new
BufferedInputStream(System.in);
if (algorithm.equalsIgnoreCase("ALL") || algorithm.equals("*")) {
- run(MessageDigestAlgorithms.values());
+ run(systemIn, MessageDigestAlgorithms.values());
return;
}
final MessageDigest messageDigest = DigestUtils.getDigest(algorithm,
null);
if (messageDigest != null) {
- run("", messageDigest);
+ run(systemIn, EMPTY, messageDigest);
} else {
- run("", DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
+ run(systemIn, EMPTY,
DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
}
}
- private void run(final String prefix, final MessageDigest messageDigest)
throws IOException {
+ private void run(final BufferedInputStream systemIn, final String prefix,
final MessageDigest messageDigest) throws IOException {
if (inputs == null) {
- println(prefix, DigestUtils.digest(messageDigest, System.in));
+ println(prefix, DigestUtils.digest(messageDigest, systemIn));
return;
}
for (final String source : inputs) {
@@ -122,22 +119,29 @@ public class Digest {
}
}
- private void run(final String prefix, final MessageDigest messageDigest,
final File[] files) throws IOException {
- for (final File file : files) {
- if (file.isFile()) {
- println(prefix, DigestUtils.digest(messageDigest, file),
file.getName());
- }
- }
- }
-
- private void run(final String prefix, final String messageDigestAlgorithm)
throws IOException {
- run(prefix, DigestUtils.getDigest(messageDigestAlgorithm));
+ private void run(final BufferedInputStream systemIn, final String prefix,
final String messageDigestAlgorithm) throws IOException {
+ run(systemIn, prefix, DigestUtils.getDigest(messageDigestAlgorithm));
}
- private void run(final String[] digestAlgorithms) throws IOException {
+ private void run(final BufferedInputStream systemIn, final String[]
digestAlgorithms) throws IOException {
for (final String messageDigestAlgorithm : digestAlgorithms) {
if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
- run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
+ if (systemIn != null) {
+ // 1 GB arbitrary default.
+ systemIn.mark(Integer.getInteger(getClass().getName() +
".markReadLimit", 1_073_741_824));
+ }
+ run(systemIn, messageDigestAlgorithm + " ",
messageDigestAlgorithm);
+ if (systemIn != null) {
+ systemIn.reset();
+ }
+ }
+ }
+ }
+
+ private void run(final String prefix, final MessageDigest messageDigest,
final File[] files) throws IOException {
+ for (final File file : files) {
+ if (file.isFile()) {
+ println(prefix, DigestUtils.digest(messageDigest, file),
file.getName());
}
}
}
diff --git a/src/test/java/org/apache/commons/codec/cli/DigestTest.java
b/src/test/java/org/apache/commons/codec/cli/DigestTest.java
index 1955c78e..84e701d5 100644
--- a/src/test/java/org/apache/commons/codec/cli/DigestTest.java
+++ b/src/test/java/org/apache/commons/codec/cli/DigestTest.java
@@ -18,7 +18,16 @@
package org.apache.commons.codec.cli;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.lang3.JavaVersion;
+import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.Test;
/**
@@ -26,6 +35,41 @@ import org.junit.jupiter.api.Test;
*/
class DigestTest {
+ @Test
+ void testAllAlgorithmsUseTheSameStandardInput() throws Exception {
+ final InputStream originalIn = System.in;
+ final PrintStream originalOut = System.out;
+ final ByteArrayOutputStream captured = new ByteArrayOutputStream();
+ try {
+ System.setIn(new
ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8)));
+ System.setOut(new PrintStream(captured, true,
StandardCharsets.UTF_8.name()));
+ Digest.main(new String[] { "ALL" });
+ } finally {
+ System.setIn(originalIn);
+ System.setOut(originalOut);
+ }
+ final String output = captured.toString(StandardCharsets.UTF_8.name());
+ assertTrue(output.contains("MD2 da853b0d3f88d99b30283a69e6ded6bb"),
output);
+ assertTrue(output.contains("MD5 900150983cd24fb0d6963f7d28e17f72"),
output);
+ assertTrue(output.contains("SHA-1
a9993e364706816aba3e25717850c26c9cd0d89d"), output);
+ assertTrue(output.contains("SHA-224
23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"), output);
+ assertTrue(output.contains("SHA-256
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), output);
+ assertTrue(output.contains("SHA-384
cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"),
output);
+ assertTrue(output.contains(
+ "SHA-512
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"),
+ output);
+ assertTrue(output.contains("SHA-512/224
4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"), output);
+ assertTrue(output.contains("SHA-512/256
53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), output);
+ if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) {
+ assertTrue(output.contains("SHA3-224
e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"), output);
+ assertTrue(output.contains("SHA3-256
3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"), output);
+ assertTrue(output.contains("SHA3-384
ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"),
output);
+ assertTrue(output.contains(
+ "SHA3-512
b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"),
+ output);
+ }
+ }
+
/**
* Tests if empty arguments are handled correctly.
*/