Fix leakage of a too big temporary file in HttpReader.

GitOrigin-RevId: b9bc7646013206fb30490cfb24e939eadb15e9c3
This commit is contained in:
levlam 2018-08-27 15:52:47 +03:00
parent d8f66f8a8e
commit 692bc1f26d
2 changed files with 11 additions and 7 deletions

View File

@ -70,6 +70,7 @@ Result<size_t> HttpReader::read_next(HttpQuery *query) {
if (state_ != ReadHeaders) { if (state_ != ReadHeaders) {
flow_source_.wakeup(); flow_source_.wakeup();
if (flow_sink_.is_ready() && flow_sink_.status().is_error()) { if (flow_sink_.is_ready() && flow_sink_.status().is_error()) {
clean_temporary_file();
return Status::Error(400, PSLICE() << "Bad Request: " << flow_sink_.status().message()); return Status::Error(400, PSLICE() << "Bad Request: " << flow_sink_.status().message());
} }
need_size = flow_source_.get_need_size(); need_size = flow_source_.get_need_size();
@ -772,24 +773,26 @@ Status HttpReader::try_open_temp_file(Slice directory_name, CSlice desired_file_
Status HttpReader::save_file_part(BufferSlice &&file_part) { Status HttpReader::save_file_part(BufferSlice &&file_part) {
file_size_ += narrow_cast<int64>(file_part.size()); file_size_ += narrow_cast<int64>(file_part.size());
if (file_size_ > MAX_FILE_SIZE) { if (file_size_ > MAX_FILE_SIZE) {
string file_name = temp_file_name_; clean_temporary_file();
close_temp_file();
delete_temp_file(file_name);
return Status::Error( return Status::Error(
413, PSLICE() << "Request Entity Too Large: file is too big to be uploaded " << tag("size", file_size_)); 413, PSLICE() << "Request Entity Too Large: file of size " << file_size_ << " is too big to be uploaded");
} }
LOG(DEBUG) << "Save file part of size " << file_part.size() << " to file " << temp_file_name_; LOG(DEBUG) << "Save file part of size " << file_part.size() << " to file " << temp_file_name_;
auto result_written = temp_file_.write(file_part.as_slice()); auto result_written = temp_file_.write(file_part.as_slice());
if (result_written.is_error() || result_written.ok() != file_part.size()) { if (result_written.is_error() || result_written.ok() != file_part.size()) {
string file_name = temp_file_name_; clean_temporary_file();
close_temp_file();
delete_temp_file(file_name);
return Status::Error(500, "Internal server error: can't upload the file"); return Status::Error(500, "Internal server error: can't upload the file");
} }
return Status::OK(); return Status::OK();
} }
void HttpReader::clean_temporary_file() {
string file_name = temp_file_name_;
close_temp_file();
delete_temp_file(file_name);
}
void HttpReader::close_temp_file() { void HttpReader::close_temp_file() {
LOG(DEBUG) << "Close temporary file " << temp_file_name_; LOG(DEBUG) << "Close temporary file " << temp_file_name_;
CHECK(!temp_file_.empty()); CHECK(!temp_file_.empty());

View File

@ -96,6 +96,7 @@ class HttpReader {
Status try_open_temp_file(Slice directory_name, CSlice desired_file_name) TD_WARN_UNUSED_RESULT; Status try_open_temp_file(Slice directory_name, CSlice desired_file_name) TD_WARN_UNUSED_RESULT;
Status save_file_part(BufferSlice &&file_part) TD_WARN_UNUSED_RESULT; Status save_file_part(BufferSlice &&file_part) TD_WARN_UNUSED_RESULT;
void close_temp_file(); void close_temp_file();
void clean_temporary_file();
static constexpr size_t MAX_CONTENT_SIZE = 150 << 20; // Some reasonable limit static constexpr size_t MAX_CONTENT_SIZE = 150 << 20; // Some reasonable limit
static constexpr size_t MAX_TOTAL_PARAMETERS_LENGTH = 1 << 16; // Some reasonable limit static constexpr size_t MAX_TOTAL_PARAMETERS_LENGTH = 1 << 16; // Some reasonable limit