Skip to content
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

IOException happens during writing to jar #2077

Merged

Conversation

Ilya-Skiba
Copy link
Contributor

Rolled back try-with resourses block, replaced with simple write #1881

manifest.write(bufOut);
bufOut.flush();
}
manifest.write(new BufferedOutputStream(destination));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that without try-with-resource and without flush the manifest data are always fully written to destination? In my understanding there is a chance that manifest data is only written to the buffer inside BufferedOutputStream but never (completely) flushed to destination.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm sure. This flush happens during closeEntry invocation. Current implementation causes BufferedOutputStream to close, which forces ZipOutputStream to close. As a result, an exception occurs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should the BufferedOutputStream be flushed in closeEntry? The reference to BufferedOutputStream is not known to closeEntry also destination does not know anything about the BufferedOutputStream instance, so how should BufferedOutputStream be flushed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a test for this case. In general, closing manifest entry forces all input buffers to flush. This why it works correctly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to side with @jpstotz here. Calling closeEntry on a ZipOutputStream handles the re-positioning and the CRC calculation, but doesn't close any streams. The JavaDoc does not say that it closes streams and the code doesn't do it.

In my opinion, the call to closeEntry needs to be moved inside the try block. You flush, you call closeEntry, then the try block ends and the stream gets closed. With this approach, we don't get dangling streams and closeEntry should be happy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to closable, try-with-resources will close underlying ZipOutputStream, that is not correct for this method- ZipOutputStream might be used by other methods also. What do you think about removing BufferedOutputStream? I don't think there would be any issues with performance during small manifest file saving

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, closing the BufferedOutputStream closes the inner stream as well.

The addManifest method should only be called by printZip and should only be called once there in line 317. In the stack trace in issue #1881, the line number is different, which confuses me slightly, but let's ignore that for now.

The printZip method owns the ZipOutputStream and the call to addManifest in line 317 is the last operation that does anything with the ZIP file. So no matter whether we close the inner stream in addManifest or not, noone should need that inner stream afterwards anyway. In fact, when printZip returns, it closes the ZipOutputStream anyway in its own try block (which I had overlooked in my previous post, so we don't get a dangling stream, even though closeEntry has nothing to do with it).

So whether we close the stream in adManifest or not, it shouldn't matter. However, this makes me wonder why changing addManifest has any effect on this exception, i.e., whether we're discussing something that is irrelevant to the problem at hand. If the entire ZIP file is closed after the call to addManifest, how can we later get an exception in addManifest? How can the control flow ever return there with the same ZipOutputStream? The ZipOutputStream should never be recycled anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My code was based on the principle, that a stream should not be closed in a method, that did not open it. I've updated the code and returned try-with-resources

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That totally makes sense. I am now just confused why the exception from the issue report happens at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

destination.closeEntry() failed before, because was trying to write entry on closed stream. You can rollback my changes in DexPrinter and run testWritingToJar test to reproduce

@Ilya-Skiba Ilya-Skiba force-pushed the bugfix/1881/not-close-zip-stream branch from d07977d to 1fb6e74 Compare April 30, 2024 09:46
Rolled back try-with resourses block, replaced with simple write
@Ilya-Skiba Ilya-Skiba force-pushed the bugfix/1881/not-close-zip-stream branch from 1fb6e74 to f1637c2 Compare May 2, 2024 06:37
@StevenArzt StevenArzt merged commit e4365f6 into soot-oss:develop May 2, 2024
5 checks passed
@Ilya-Skiba Ilya-Skiba deleted the bugfix/1881/not-close-zip-stream branch May 2, 2024 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants