8220394: bufferedStream does not honor size limit
Reviewed-by: dholmes, clanger
This commit is contained in:
parent
fd67f8ee69
commit
a46a6bcfeb
@ -939,6 +939,7 @@ bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStrea
|
||||
buffer_pos = 0;
|
||||
buffer_fixed = false;
|
||||
buffer_max = bufmax;
|
||||
truncated = false;
|
||||
}
|
||||
|
||||
bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() {
|
||||
@ -947,12 +948,17 @@ bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, siz
|
||||
buffer_pos = 0;
|
||||
buffer_fixed = true;
|
||||
buffer_max = bufmax;
|
||||
truncated = false;
|
||||
}
|
||||
|
||||
void bufferedStream::write(const char* s, size_t len) {
|
||||
|
||||
if (truncated) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(buffer_pos + len > buffer_max) {
|
||||
flush();
|
||||
flush(); // Note: may be a noop.
|
||||
}
|
||||
|
||||
size_t end = buffer_pos + len;
|
||||
@ -960,19 +966,42 @@ void bufferedStream::write(const char* s, size_t len) {
|
||||
if (buffer_fixed) {
|
||||
// if buffer cannot resize, silently truncate
|
||||
len = buffer_length - buffer_pos - 1;
|
||||
truncated = true;
|
||||
} else {
|
||||
// For small overruns, double the buffer. For larger ones,
|
||||
// increase to the requested size.
|
||||
if (end < buffer_length * 2) {
|
||||
end = buffer_length * 2;
|
||||
}
|
||||
buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal);
|
||||
buffer_length = end;
|
||||
// Impose a cap beyond which the buffer cannot grow - a size which
|
||||
// in all probability indicates a real error, e.g. faulty printing
|
||||
// code looping, while not affecting cases of just-very-large-but-its-normal
|
||||
// output.
|
||||
const size_t reasonable_cap = MAX2(100 * M, buffer_max * 2);
|
||||
if (end > reasonable_cap) {
|
||||
// In debug VM, assert right away.
|
||||
assert(false, "Exceeded max buffer size for this string.");
|
||||
// Release VM: silently truncate. We do this since these kind of errors
|
||||
// are both difficult to predict with testing (depending on logging content)
|
||||
// and usually not serious enough to kill a production VM for it.
|
||||
end = reasonable_cap;
|
||||
size_t remaining = end - buffer_pos;
|
||||
if (len >= remaining) {
|
||||
len = remaining - 1;
|
||||
truncated = true;
|
||||
}
|
||||
}
|
||||
if (buffer_length < end) {
|
||||
buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal);
|
||||
buffer_length = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(buffer + buffer_pos, s, len);
|
||||
buffer_pos += len;
|
||||
update_position(s, len);
|
||||
if (len > 0) {
|
||||
memcpy(buffer + buffer_pos, s, len);
|
||||
buffer_pos += len;
|
||||
update_position(s, len);
|
||||
}
|
||||
}
|
||||
|
||||
char* bufferedStream::as_string() {
|
||||
|
@ -267,6 +267,7 @@ class bufferedStream : public outputStream {
|
||||
size_t buffer_max;
|
||||
size_t buffer_length;
|
||||
bool buffer_fixed;
|
||||
bool truncated;
|
||||
public:
|
||||
bufferedStream(size_t initial_bufsize = 256, size_t bufmax = 1024*1024*10);
|
||||
bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax = 1024*1024*10);
|
||||
|
@ -67,3 +67,51 @@ TEST_VM(ostream, stringStream_dynamic_realloc_1) {
|
||||
TEST_VM(ostream, stringStream_dynamic_realloc_2) {
|
||||
do_test_stringStream_dynamic_realloc(true);
|
||||
}
|
||||
|
||||
TEST_VM(ostream, bufferedStream_static) {
|
||||
char buf[100];
|
||||
bufferedStream bs(buf, sizeof(buf));
|
||||
size_t written = 0;
|
||||
for (int i = 0; i < 100; i ++) {
|
||||
written += print_lorem(&bs, true);
|
||||
if (written < sizeof(buf)) {
|
||||
ASSERT_EQ(bs.size(), written);
|
||||
} else {
|
||||
ASSERT_EQ(bs.size(), sizeof(buf) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_VM(ostream, bufferedStream_dynamic_small) {
|
||||
bufferedStream bs(1); // small to excercise realloc.
|
||||
size_t written = 0;
|
||||
// The max cap imposed is 100M, we should be safely below this in this test.
|
||||
for (int i = 0; i < 10; i ++) {
|
||||
written += print_lorem(&bs, true);
|
||||
ASSERT_EQ(bs.size(), written);
|
||||
}
|
||||
}
|
||||
|
||||
/* Activate to manually test bufferedStream dynamic cap.
|
||||
|
||||
TEST_VM(ostream, bufferedStream_dynamic_large) {
|
||||
bufferedStream bs(1); // small to excercise realloc.
|
||||
size_t written = 0;
|
||||
// The max cap imposed is 100M. Writing this much should safely hit it.
|
||||
// Note that this will assert in debug builds which is the expected behavior.
|
||||
size_t expected_cap_at = 100 * M;
|
||||
for (int i = 0; i < 10000000; i ++) {
|
||||
written += print_lorem(&bs, false);
|
||||
if (written < expected_cap_at) {
|
||||
ASSERT_EQ(bs.size(), written);
|
||||
} else {
|
||||
ASSERT_EQ(bs.size(), expected_cap_at - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user