[ 
https://issues.apache.org/jira/browse/CODEC-334?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18064950#comment-18064950
 ] 

Shan Jiang commented on CODEC-334:
----------------------------------

Thanks for looking into this, Gary. You're right that 
AbstractBaseNOutputStreamTest.testClose() passes — but it wraps a 
ByteArrayOutputStream, whose close() is a no-op. The idempotency violation 
surfaces when the underlying stream enforces single-close semantics:
                                                                                
                                                                                
                                                           
  @Test                                                     
  void testCloseIdempotentWithFileStream() throws Exception {
      Path tmp = Files.createTempFile("codec-test", ".bin");
      try {
          BaseNCodecOutputStream out = new Base64OutputStream(
                  new FileOutputStream(tmp.toFile()));
          out.close();
          out.close(); // IOException: Stream Closed
      } finally {
          Files.deleteIfExists(tmp);
      }
  }

 

The second close() calls flush() then out.close() unconditionally — when out is 
a FileOutputStream that's already closed, the flush() (or the inner 
out.close()) throws. A guard like if (closed) return; at the top of close() 
would fix it.

Apologies that the original report didn't include a concrete test case.

> BaseNCodecOutputStream.close() throws on second call; violates Closeable 
> idempotency contract
> ---------------------------------------------------------------------------------------------
>
>                 Key: CODEC-334
>                 URL: https://issues.apache.org/jira/browse/CODEC-334
>             Project: Commons Codec
>          Issue Type: Bug
>            Reporter: Shan Jiang
>            Priority: Major
>
> ### Summary
> `BaseNCodecOutputStream.close()` is not idempotent: the second call attempts 
> to flush to an already-closed underlying stream, throwing `IOException`. The 
> `Closeable` contract (JDK 21 Javadoc) states: "If the stream is already 
> closed then invoking this method has no effect."
> ### How this was found
> Detected by automated JDK conformance oracle (`checkCloseIdempotent`).



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

Reply via email to