in libcef/browser/net_service/response_filter_wrapper.cc [120:205]
void ResponseFilterWrapper::Filter(const char* data, size_t size) {
size_t data_in_size = size;
auto data_in_ptr = data_in_size > 0 ? data : nullptr;
size_t data_out_offset = 0;
std::unique_ptr<std::string> data_out;
while (true) {
size_t data_in_read = 0;
if (!data_out) {
// Start a new buffer. Should have no offset to begin with.
DCHECK_EQ(0U, data_out_offset);
data_out = std::make_unique<std::string>();
data_out->resize(kBufferSize);
}
auto data_out_ptr = data_out->data() + data_out_offset;
size_t data_out_size = kBufferSize - data_out_offset;
size_t data_out_written = 0;
last_status_ = filter_->Filter(
const_cast<char*>(data_in_ptr), data_in_size, data_in_read,
const_cast<char*>(data_out_ptr), data_out_size, data_out_written);
if (last_status_ == RESPONSE_FILTER_ERROR)
break;
// Validate the out values.
if (data_in_read > data_in_size) {
LOG(ERROR) << "potential buffer overflow; data_in_read > data_in_size";
last_status_ = RESPONSE_FILTER_ERROR;
break;
}
if (data_out_written > data_out_size) {
LOG(ERROR)
<< "potential buffer overflow; data_out_written > data_out_size";
last_status_ = RESPONSE_FILTER_ERROR;
break;
}
if (data_out_written == 0 && data_in_read != data_in_size) {
LOG(ERROR) << "when no data is written all input must be consumed; "
"data_out_written == 0 && data_in_read != data_in_size";
last_status_ = RESPONSE_FILTER_ERROR;
break;
}
if (data_out_written > 0) {
data_out_offset += data_out_written;
if (data_out_offset > kBufferSize - kMinBufferSpace) {
// The buffer is full or almost full. Write the data that we've
// received so far and start a new buffer.
data_out->resize(data_out_offset);
Write(std::move(data_out));
data_out_offset = 0;
}
}
if (data_in_read < data_in_size) {
// Keep going until the user reads all data.
data_in_ptr += data_in_read;
data_in_size -= data_in_read;
continue;
}
// At this point the user has read all data...
if (data_in_ptr) {
// Clear the input buffer.
data_in_read = data_in_size = 0;
data_in_ptr = nullptr;
}
if (data_out_written == data_out_size &&
last_status_ == RESPONSE_FILTER_NEED_MORE_DATA) {
// Output buffer was filled, but data is still pending.
continue;
}
if (data_out_offset > 0) {
// Write the last of the data that we've received.
data_out->resize(data_out_offset);
Write(std::move(data_out));
}
break;
}
}