Chromium Code Reviews| Index: android_webview/native/input_stream_impl.cc |
| diff --git a/android_webview/native/input_stream_impl.cc b/android_webview/native/input_stream_impl.cc |
| index 24d7be09930bc734cbd56a55b00686f98513db33..2a90730706e2aa3e8be23a15c87070f439ca4474 100644 |
| --- a/android_webview/native/input_stream_impl.cc |
| +++ b/android_webview/native/input_stream_impl.cc |
| @@ -84,46 +84,46 @@ bool InputStreamImpl::Read(net::IOBuffer* dest, int length, int* bytes_read) { |
| return false; |
| } |
| + int remaining_length = length; |
| + char* dest_write_ptr = dest->data(); |
| jbyteArray buffer = buffer_.obj(); |
| *bytes_read = 0; |
| - const int read_size = std::min(length, kBufferSize); |
| - int32_t byte_count; |
| - do { |
| - // Unfortunately it is valid for the Java InputStream to read 0 bytes some |
| - // number of times before returning any more data. Because this method |
| - // signals EOF by setting |bytes_read| to 0 and returning true necessary to |
| - // call the Java-side read method until it returns something other than 0. |
| - byte_count = Java_InputStream_readI_AB_I_I( |
| - env, jobject_.obj(), buffer, 0, read_size); |
| + while (remaining_length > 0) { |
| + const int max_transfer_length = std::min(remaining_length, kBufferSize); |
| + const int transfer_length = Java_InputStream_readI_AB_I_I( |
| + env, jobject_.obj(), buffer, 0, max_transfer_length); |
| if (ClearException(env)) |
| return false; |
| - } while (byte_count == 0); |
| - |
| - // We've reached the end of the stream. |
| - if (byte_count < 0) |
| - return true; |
| - |
| + if (transfer_length < 0) // EOF |
| + break; |
|
joth
2013/09/19 01:11:58
nit: I'd put \n after each these early-outs
Primiano Tucci (use gerrit)
2013/09/19 01:48:57
Done.
|
| + // Note: it is possible, yet unlikely, that the Java InputStream returns |
| + // a transfer_length == 0 from time to time. In such cases we just continue |
| + // the read until we get either valid data or reach EOF. |
| + if (transfer_length > 0) { |
|
joth
2013/09/19 01:11:58
heh, we could go further on this line
if (transfe
Primiano Tucci (use gerrit)
2013/09/19 01:48:57
Done.
|
| #ifndef NDEBUG |
| - int32_t buffer_length = env->GetArrayLength(buffer); |
| - DCHECK_GE(read_size, byte_count); |
| - DCHECK_GE(buffer_length, byte_count); |
| + DCHECK_GE(max_transfer_length, transfer_length); |
| + DCHECK_GE(env->GetArrayLength(buffer), transfer_length); |
| #endif // NDEBUG |
|
joth
2013/09/19 01:11:58
the "#ifndef NDEBUG" guard not needed here now. (i
Primiano Tucci (use gerrit)
2013/09/19 01:48:57
Done.
|
| - // The DCHECKs are in place to help Chromium developers in case of bugs, |
| - // this check is to prevent a malicious InputStream implementation from |
| - // overrunning the |dest| buffer. |
| - if (byte_count > read_size) |
| - return false; |
| - |
| - // Copy the data over to the provided C++ side buffer. |
| - DCHECK_GE(length, byte_count); |
| - env->GetByteArrayRegion(buffer, 0, byte_count, |
| - reinterpret_cast<jbyte*>(dest->data() + *bytes_read)); |
| - if (ClearException(env)) |
| - return false; |
| - |
| - *bytes_read = byte_count; |
| + // This check is to prevent a malicious InputStream implementation from |
| + // overrunning the |dest| buffer. |
| + if (transfer_length > max_transfer_length) |
| + return false; |
| + |
| + // Copy the data over to the provided C++ IOBuffer. |
| + DCHECK_GE(remaining_length, transfer_length); |
| + env->GetByteArrayRegion(buffer, 0, transfer_length, |
| + reinterpret_cast<jbyte*>(dest_write_ptr)); |
| + if (ClearException(env)) |
| + return false; |
| + remaining_length -= transfer_length; |
| + dest_write_ptr += transfer_length; |
| + } |
| + } |
| + // bytes_read can be strictly less than the req. length if EOF is encountered. |
| + DCHECK(remaining_length >= 0 && remaining_length <= length); |
| + *bytes_read = length - remaining_length; |
| return true; |
| } |