-
Notifications
You must be signed in to change notification settings - Fork 303
[COMPRESS-714] Internal IllegalArgumentException in ZipFile and TarFile creation is not caught #754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| entries.add(entry); | ||
| } | ||
| } catch (final IOException ex) { | ||
| } catch (final IOException | IllegalArgumentException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m wondering whether extending the catch clause from IOException to IOException | IllegalArgumentException is the right boundary. If the intention is to shield users from any unexpected internal failures we should rather catch Exception.
However, I see unchecked exceptions here as symptoms of underlying bugs. Masking them in the constructor can improve user experience, but only hides the bugs, instead of solving them.
In the specific case of COMPRESS-714, the IllegalArgumentException comes from a bug in SeekableInMemoryByteChannel. According to the position() contract, providing a position larger than the channel size should not result in an exception, so the current implementation violates that contract:
commons-compress/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
Lines 114 to 121 in b83da24
| public SeekableByteChannel position(final long newPosition) throws IOException { | |
| ensureOpen(); | |
| if (newPosition < 0L || newPosition > Integer.MAX_VALUE) { | |
| throw new IllegalArgumentException(String.format("Position must be in range [0..%,d]: %,d", Integer.MAX_VALUE, newPosition)); | |
| } | |
| position = (int) newPosition; | |
| return this; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm good catch, here's a fix: #756 (now merged).
47bf566 to
4c67aef
Compare
creation is not caught
3b6fe46 to
cab216b
Compare
| } catch (final ArithmeticException | IllegalArgumentException e) { | ||
| final ArchiveException archiveException = new ArchiveException(e); | ||
| IOUtils.close(channel, archiveException::addSuppressed); | ||
| throw archiveException; | ||
| throw IOUtils.closeQuietly(channel, new ArchiveException(e)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I wouldn't delay the release of commons-compress version 1.29.0 more than it already has been to wait for a new version of commons-io.
Let's use what we have in 2.21.0:
} catch (final Exception e) {
final IOException ioe = e instanceof IOException ? (IOException) e : new ArchiveException(e);
IOUtils.closeQuietly(channel, ioe::addSuppressed);
throw ioe;
}When we do release Commons IO version 2.22.0, we'll update this call site and all the other call sites that might benefit from the new method. There is no chance to forget that, since closeQuietly becomes ambiguous in IO 2.22.0.
| } catch (final IOException e) { | ||
| final ArchiveException archiveException = e instanceof ArchiveException | ||
| ? (ArchiveException) e | ||
| : new ArchiveException("Error reading Zip content from " + builder.getName(), (Throwable) e); | ||
| this.closed = true; | ||
| IOUtils.close(archive, archiveException::addSuppressed); | ||
| throw archiveException; | ||
| throw IOUtils.closeQuietly(archive, e); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: I wouldn't rely on an unpublished IO method and use what is available now.
} catch (final Exception e) {
this.closed = true;
final IOException ioe = e instanceof IOException ? (IOException) e : new ArchiveException(e);
IOUtils.closeQuietly(archive, ioe::addSuppressed);
throw ioe;
}
Fixes Jira https://issues.apache.org/jira/browse/COMPRESS-714
Before you push a pull request, review this list:
mvn; that'smvnon the command line by itself.