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.
      */

Reply via email to