[ 
https://issues.apache.org/jira/browse/CODEC-337?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ruiqi Dong updated CODEC-337:
-----------------------------
    Description: 
*Summary*
When Digest is invoked with ALL or * and no explicit input arguments, each 
algorithm reads directly from `System.in`. The first algorithm consumes the 
stream, and all later algorithms hash the empty stream.
 
*Affected code*
File: src/main/java/org/apache/commons/codec/cli/Digest.java
{code:java}
private void run(final String prefix, final MessageDigest messageDigest) throws 
IOException {
    if (inputs == null) {
        println(prefix, DigestUtils.digest(messageDigest, System.in));
        return;
    }
    ...
}

private void run(final String[] digestAlgorithms) throws IOException {
    for (final String messageDigestAlgorithm : digestAlgorithms) {
        if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
            run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
        }
    }
} {code}
*Reproducer*
Add the following test to 
src/test/java/org/apache/commons/codec/cli/DigestTest.java:
{code:java}
@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("MD5 900150983cd24fb0d6963f7d28e17f72"), output);
    assertTrue(output.contains("SHA-1 
a9993e364706816aba3e25717850c26c9cd0d89d"), output);
} {code}
Run:
{code:java}
mvn -q -Dtest=org.apache.commons.codec.cli.DigestTest test {code}
Observed behavior:
{code:java}
MD2 da853b0d3f88d99b30283a69e6ded6bb
MD5 d41d8cd98f00b204e9800998ecf8427e
SHA-1 da39a3ee5e6b4b0d3255bfef95601890afd80709
...
DigestTest.testAllAlgorithmsUseTheSameStandardInput:67
==> expected: <true> but was: <false> {code}
Expected behavior:
Every listed algorithm should hash the same stdin contents.


The CLI output is internally inconsistent for the same invocation. Only the 
first digest is computed over the actual input; the rest are computed over EOF.

  was:
*Summary*
When Digest is invoked with ALL or * and no explicit input arguments, each 
algorithm reads directly from `System.in`. The first algorithm consumes the 
stream, and all later algorithms hash the empty stream.
 
*Affected code*
File: src/main/java/org/apache/commons/codec/cli/Digest.java
{code:java}
private void run(final String prefix, final MessageDigest messageDigest) throws 
IOException {
    if (inputs == null) {
        println(prefix, DigestUtils.digest(messageDigest, System.in));
        return;
    }
    ...
}

private void run(final String[] digestAlgorithms) throws IOException {
    for (final String messageDigestAlgorithm : digestAlgorithms) {
        if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
            run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
        }
    }
} {code}
*Reproducer*
Add the following test to 
src/test/java/org/apache/commons/codec/cli/DigestTest.java:
{code:java}
@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("MD5 900150983cd24fb0d6963f7d28e17f72"), output);
    assertTrue(output.contains("SHA-1 
a9993e364706816aba3e25717850c26c9cd0d89d"), output);
} {code}
Run:
{code:java}
mvn -q -Dtest=org.apache.commons.codec.cli.DigestTest test {code}
Observed behavior:
{code:java}
MD2 da853b0d3f88d99b30283a69e6ded6bb
MD5 d41d8cd98f00b204e9800998ecf8427e
SHA-1 da39a3ee5e6b4b0d3255bfef95601890afd80709
...
DigestTest.testAllAlgorithmsUseTheSameStandardInput:67
==> expected: <true> but was: <false> {code}
Expected behavior:
Every listed algorithm should hash the same stdin contents.
The CLI output is internally inconsistent for the same invocation. Only the 
first digest is computed over the actual input; the rest are computed over EOF.


> Digest ALL reuses System.in, so only the first algorithm sees the real input
> ----------------------------------------------------------------------------
>
>                 Key: CODEC-337
>                 URL: https://issues.apache.org/jira/browse/CODEC-337
>             Project: Commons Codec
>          Issue Type: Bug
>    Affects Versions: 1.22.0
>            Reporter: Ruiqi Dong
>            Priority: Major
>
> *Summary*
> When Digest is invoked with ALL or * and no explicit input arguments, each 
> algorithm reads directly from `System.in`. The first algorithm consumes the 
> stream, and all later algorithms hash the empty stream.
>  
> *Affected code*
> File: src/main/java/org/apache/commons/codec/cli/Digest.java
> {code:java}
> private void run(final String prefix, final MessageDigest messageDigest) 
> throws IOException {
>     if (inputs == null) {
>         println(prefix, DigestUtils.digest(messageDigest, System.in));
>         return;
>     }
>     ...
> }
> private void run(final String[] digestAlgorithms) throws IOException {
>     for (final String messageDigestAlgorithm : digestAlgorithms) {
>         if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
>             run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
>         }
>     }
> } {code}
> *Reproducer*
> Add the following test to 
> src/test/java/org/apache/commons/codec/cli/DigestTest.java:
> {code:java}
> @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("MD5 900150983cd24fb0d6963f7d28e17f72"), 
> output);
>     assertTrue(output.contains("SHA-1 
> a9993e364706816aba3e25717850c26c9cd0d89d"), output);
> } {code}
> Run:
> {code:java}
> mvn -q -Dtest=org.apache.commons.codec.cli.DigestTest test {code}
> Observed behavior:
> {code:java}
> MD2 da853b0d3f88d99b30283a69e6ded6bb
> MD5 d41d8cd98f00b204e9800998ecf8427e
> SHA-1 da39a3ee5e6b4b0d3255bfef95601890afd80709
> ...
> DigestTest.testAllAlgorithmsUseTheSameStandardInput:67
> ==> expected: <true> but was: <false> {code}
> Expected behavior:
> Every listed algorithm should hash the same stdin contents.
> The CLI output is internally inconsistent for the same invocation. Only the 
> first digest is computed over the actual input; the rest are computed over 
> EOF.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to