Close leaked output streams (CodeQL java/output-resource-leak)#223
Conversation
a23d16f to
5d884c9
Compare
Re: the CodeQL comments on the
|
|
Addendum after the
Neither entry is ever empty; the query just doesn't follow bytes through the |
Two code paths could leave an output file descriptor open when an exception was thrown before the explicit close(): - script/common Utils.copyURLToFile: the input channel and the FileOutputStream behind the output channel were closed in a finally block, but only after both were created outside the try; if opening the FileOutputStream failed, the already-open input channel leaked. Wrap all three (input channel, output stream, output channel) in try-with-resources. - persistit CLI "dump": the ZipOutputStream over a FileOutputStream was closed only on the normal path (stream.close() at the end); any exception while dumping buffer pools/volumes leaked the file. Wrap the DataOutputStream in try-with-resources so the underlying FileOutputStream is released on every path. The DataOutputStream and PrintWriter are views over the same ZipOutputStream (closing either finalizes the archive), so a single resource is managed; try-with-resources also makes a failing close() a suppressed exception rather than masking the original error from the dump. Behaviour is otherwise unchanged. Verified: script/common and persistit/core compile.
5d884c9 to
63d26ef
Compare
|
Good catch — fixed in 63d26ef. You're right that the Switched to your suggested form: final ZipOutputStream zos = new ZipOutputStream(
new BufferedOutputStream(new FileOutputStream(target), BUFFER_SIZE));
try (final DataOutputStream stream = new DataOutputStream(zos)) {
...
writer.flush();
zos.closeEntry();
}There is a single resource to manage — closing the Thanks also for confirming |
Summary
Resolves 2 of the CodeQL
java/output-resource-leakalerts by closing outputstreams that could remain open when an exception is thrown before the explicit
close(). Behaviour is otherwise unchanged.script/commonUtils.copyURLToFileFileOutputStream/output channeltry; ifnew FileOutputStream(out)failed, the already-open input channel leakedpersistit/coreCLI"dump"ZipOutputStreamoverFileOutputStreamstream.close()at the end); any exception while dumping buffer pools/volumes leaked the filestream.close()into afinallyblockFor the CLI "dump" fix a
try/finallyis used rather than try-with-resources:the
DataOutputStream(stream) andPrintWriter(writer) are views overthe same
ZipOutputStream, and closing either one finalizes the archive andcloses the underlying
FileOutputStream. So there is a single resource torelease — the outer
DataOutputStream, closed infinallyon every path. (Thebulk of the CLI diff is re-indentation of the existing body into the
tryblock.)
Notes on the remaining
java/output-resource-leakalertsThe other alerts of this rule are handled separately:
CLI"open" (OutputStreamWriterover the socket) — already fixed in thecompanion
java/input-resource-leakPR, which wraps theSocketintry-with-resources.
StreamSaverconstructors,IOMeter.setLogFileand the auditStandardCsvWriter/SecureCsvWriter— theFileOutputStreamis owned bythe object and released through its own
close()(the standardresource-owning pattern); dismissed as false positives.
GroovyScriptnew PrintWriter(engine.getWriter(), true)— wraps theengine's borrowed writer and is handed to the script bindings as
out;closing it would close the engine writer. Dismissed.
PrintWriterview insideCLI"dump" (java/output-resource-leak) andthe pre-existing
java/empty-zip-file-entryalert on the same.txtentry —dismissed as false positives; see the PR comment for the reasoning.
Testing
script/commonandpersistit/corecompile.