JDK-8220394 : bufferedStream does not honor size limit
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11,12,13
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-03-10
  • Updated: 2019-10-14
  • Resolved: 2019-05-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13
11.0.6-oracleFixed 13 b23Fixed
Related Reports
Relates :  
Description
bufferedStream, in its dynamic variant (where it is supposed to allocate its own buffer from C-Heap) can dynamically grow. It has a "bufmax" parameter which looks like it is supposed to be a limit to the buffer size (defaults to 10M).

bufferedStream(size_t initial_bufsize = 256, size_t bufmax = 1024*1024*10);

However, when growing the buffer it does not honor the bufmax cap. It just grows forever.

That can lead to large memory usage or runaway memory leaks when printing, especially with faulty printing code.


Comments
I see the patch applies cleanly now. Restoring jdk11u-fix-request/jdk11u-fix-yes. Can be pushed after another cycle of testing.
03-09-2019

Important to fix because: Fix limits the memory a bufferedStream can allocate as backing buffer. Today, faulty code - e.g. a misbehaving jcmd - may cause huge allocations or never stop allocating memory. Nature of fix: We limit the internal buffer to max 100M. This cap was arbitrarily chosen to catch pathological cases while leaving non-pathological large output cases alone. Hitting that limit will silently truncate output (release) or assert (debug). Small risk because: The patch itself is simple, and well tested. A small theoretical risk exists where valid output could exceed 100M in size - but this was not found anywhere in the VM. The largest output found was the codeheap analysis and that was about 1-2M. Testing done: Nightly tests at SAP (jtreg, jck, gtest, etc), custom gtest.
27-06-2019

void bufferedStream::write(const char* s, size_t len) { if(buffer_pos + len > buffer_max) { flush(); } I think the intent is that if we try to write more than buffer_max then we will flush the buffer and so empty it again. But AFAICS bufferedStream inherits the empty outputStream::flush, which just seems completely broken!
11-03-2019