Skip to content

Commit 3260cb0

Browse files
authored
Improve ZIP pointer handling (#377)
1 parent b5e9ff9 commit 3260cb0

3 files changed

Lines changed: 92 additions & 62 deletions

File tree

src/odr/internal/html/filesystem.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,20 @@ Html html::translate_filesystem(FileType file_type,
7070
out.write_raw(std::to_string(file.size()));
7171
out.write_element_end("span");
7272

73-
out.write_element_begin("span");
74-
out.write_raw(" ");
75-
out.write_element_end("span");
76-
77-
out.write_element_begin(
78-
"a",
79-
HtmlElementOptions().set_attributes(HtmlAttributesVector{
80-
{"href", file_to_url(*file.stream(), "application/octet-stream")},
81-
{"download", file_path.basename()}}));
82-
out.write_raw("download");
83-
out.write_element_end("a");
73+
std::unique_ptr<std::istream> stream = file.stream();
74+
75+
if (stream != nullptr) {
76+
out.write_element_begin("span");
77+
out.write_raw(" ");
78+
out.write_element_end("span");
79+
80+
out.write_element_begin(
81+
"a", HtmlElementOptions().set_attributes(HtmlAttributesVector{
82+
{"href", file_to_url(*stream, "application/octet-stream")},
83+
{"download", file_path.basename()}}));
84+
out.write_raw("download");
85+
out.write_element_end("a");
86+
}
8487
}
8588

8689
out.write_element_end("p");

src/odr/internal/zip/zip_archive.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
#include <odr/internal/zip/zip_exceptions.hpp>
77
#include <odr/internal/zip/zip_util.hpp>
88

9-
#include <chrono>
109
#include <string>
1110
#include <utility>
12-
#include <vector>
1311

1412
#include <miniz/miniz.h>
1513

@@ -48,7 +46,7 @@ Method ReadonlyZipArchive::Entry::method() const {
4846

4947
std::unique_ptr<abstract::File> ReadonlyZipArchive::Entry::file() const {
5048
if (!is_file()) {
51-
return {};
49+
return nullptr;
5250
}
5351
return std::make_unique<util::FileInZip>(m_parent.m_zip, m_index);
5452
}
@@ -88,11 +86,19 @@ ReadonlyZipArchive::Iterator ReadonlyZipArchive::Iterator::operator++(int) {
8886

8987
ReadonlyZipArchive::ReadonlyZipArchive(
9088
const std::shared_ptr<common::MemoryFile> &file)
91-
: m_zip{std::make_shared<util::Archive>(file)} {}
89+
: m_zip{std::make_shared<util::Archive>(file)} {
90+
if (m_zip == nullptr) {
91+
throw std::invalid_argument("ReadonlyZipArchive: file is nullptr");
92+
}
93+
}
9294

9395
ReadonlyZipArchive::ReadonlyZipArchive(
9496
const std::shared_ptr<common::DiskFile> &file)
95-
: m_zip{std::make_shared<util::Archive>(file)} {}
97+
: m_zip{std::make_shared<util::Archive>(file)} {
98+
if (m_zip == nullptr) {
99+
throw std::invalid_argument("ReadonlyZipArchive: file is nullptr");
100+
}
101+
}
96102

97103
ReadonlyZipArchive::Iterator ReadonlyZipArchive::begin() const {
98104
return {*this, 0};
@@ -149,6 +155,10 @@ ZipArchive::ZipArchive(ReadonlyZipArchive archive)
149155
: ZipArchive(std::make_shared<ReadonlyZipArchive>(std::move(archive))) {}
150156

151157
ZipArchive::ZipArchive(const std::shared_ptr<ReadonlyZipArchive> &archive) {
158+
if (archive == nullptr) {
159+
throw std::invalid_argument("ZipArchive: archive is nullptr");
160+
}
161+
152162
for (auto &&entry : *archive) {
153163
if (entry.is_file()) {
154164
std::uint8_t compression_level = 6;
@@ -189,7 +199,7 @@ ZipArchive::insert_file(Iterator at, common::Path path,
189199

190200
ZipArchive::Iterator ZipArchive::insert_directory(Iterator at,
191201
common::Path path) {
192-
return m_entries.insert(at, ZipArchive::Entry(std::move(path), {}, 0));
202+
return m_entries.insert(at, ZipArchive::Entry(std::move(path), nullptr, 0));
193203
}
194204

195205
bool ZipArchive::move(common::Path, common::Path) { return false; }

src/odr/internal/zip/zip_util.cpp

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,36 @@ namespace {
1313

1414
class ReaderBuffer final : public std::streambuf {
1515
public:
16-
explicit ReaderBuffer(mz_zip_reader_extract_iter_state *iter);
17-
ReaderBuffer(mz_zip_reader_extract_iter_state *iter, std::size_t buffer_size);
18-
~ReaderBuffer() final;
16+
explicit ReaderBuffer(mz_zip_reader_extract_iter_state *iter)
17+
: ReaderBuffer(iter, 4098) {}
18+
ReaderBuffer(mz_zip_reader_extract_iter_state *iter,
19+
std::size_t buffer_size) {
20+
if (iter == nullptr) {
21+
throw std::invalid_argument("ReaderBuffer: iter is nullptr");
22+
}
23+
m_iter = iter;
24+
m_remaining = iter->file_stat.m_uncomp_size;
25+
m_buffer_size = buffer_size;
26+
m_buffer = new char[m_buffer_size];
27+
}
28+
~ReaderBuffer() final {
29+
mz_zip_reader_extract_iter_free(m_iter);
30+
delete[] m_buffer;
31+
}
32+
33+
int underflow() final {
34+
if (m_remaining <= 0) {
35+
return std::char_traits<char>::eof();
36+
}
1937

20-
int underflow() final;
38+
const std::uint64_t amount = std::min(m_remaining, m_buffer_size);
39+
const std::uint32_t result =
40+
mz_zip_reader_extract_iter_read(m_iter, m_buffer, amount);
41+
m_remaining -= result;
42+
setg(m_buffer, m_buffer, m_buffer + result);
43+
44+
return std::char_traits<char>::to_int_type(*gptr());
45+
}
2146

2247
private:
2348
mz_zip_reader_extract_iter_state *m_iter{};
@@ -29,52 +54,26 @@ class ReaderBuffer final : public std::streambuf {
2954
class FileInZipIstream final : public std::istream {
3055
public:
3156
FileInZipIstream(std::shared_ptr<Archive> archive,
32-
std::unique_ptr<ReaderBuffer> sbuf);
57+
std::unique_ptr<ReaderBuffer> sbuf)
58+
: std::istream(sbuf.get()), m_archive{std::move(archive)},
59+
m_sbuf{std::move(sbuf)} {
60+
if (m_archive == nullptr) {
61+
throw std::invalid_argument("FileInZipIstream: archive is nullptr");
62+
}
63+
if (m_sbuf == nullptr) {
64+
throw std::invalid_argument("FileInZipIstream: sbuf is nullptr");
65+
}
66+
}
3367
FileInZipIstream(std::shared_ptr<Archive> archive,
34-
mz_zip_reader_extract_iter_state *iter);
68+
mz_zip_reader_extract_iter_state *iter)
69+
: FileInZipIstream(std::move(archive),
70+
std::make_unique<ReaderBuffer>(iter)) {}
3571

3672
private:
3773
std::shared_ptr<Archive> m_archive;
3874
std::unique_ptr<ReaderBuffer> m_sbuf;
3975
};
4076

41-
ReaderBuffer::ReaderBuffer(mz_zip_reader_extract_iter_state *iter)
42-
: ReaderBuffer(iter, 4098) {}
43-
44-
ReaderBuffer::ReaderBuffer(mz_zip_reader_extract_iter_state *iter,
45-
const std::size_t buffer_size)
46-
: m_iter{iter}, m_remaining{iter->file_stat.m_uncomp_size},
47-
m_buffer_size{buffer_size}, m_buffer{new char[m_buffer_size]} {}
48-
49-
ReaderBuffer::~ReaderBuffer() {
50-
mz_zip_reader_extract_iter_free(m_iter);
51-
delete[] m_buffer;
52-
}
53-
54-
int ReaderBuffer::underflow() {
55-
if (m_remaining <= 0) {
56-
return std::char_traits<char>::eof();
57-
}
58-
59-
const std::uint64_t amount = std::min(m_remaining, m_buffer_size);
60-
const std::uint32_t result =
61-
mz_zip_reader_extract_iter_read(m_iter, m_buffer, amount);
62-
m_remaining -= result;
63-
setg(m_buffer, m_buffer, m_buffer + result);
64-
65-
return std::char_traits<char>::to_int_type(*gptr());
66-
}
67-
68-
FileInZipIstream::FileInZipIstream(std::shared_ptr<Archive> archive,
69-
std::unique_ptr<ReaderBuffer> sbuf)
70-
: std::istream(sbuf.get()), m_archive{std::move(archive)},
71-
m_sbuf{std::move(sbuf)} {}
72-
73-
FileInZipIstream::FileInZipIstream(std::shared_ptr<Archive> archive,
74-
mz_zip_reader_extract_iter_state *iter)
75-
: FileInZipIstream(std::move(archive),
76-
std::make_unique<ReaderBuffer>(iter)) {}
77-
7877
} // namespace
7978

8079
Archive::Archive(const std::shared_ptr<common::MemoryFile> &file)
@@ -85,6 +84,9 @@ Archive::Archive(const std::shared_ptr<common::DiskFile> &file)
8584

8685
Archive::Archive(std::shared_ptr<abstract::File> file)
8786
: m_file{std::move(file)}, m_data{m_file->stream()} {
87+
if (m_file == nullptr) {
88+
throw std::invalid_argument("Archive: file is nullptr");
89+
}
8890
init_();
8991
}
9092

@@ -128,7 +130,11 @@ std::shared_ptr<abstract::File> Archive::file() const { return m_file; }
128130

129131
FileInZip::FileInZip(std::shared_ptr<Archive> archive,
130132
const std::uint32_t index)
131-
: m_archive{std::move(archive)}, m_index{index} {}
133+
: m_archive{std::move(archive)}, m_index{index} {
134+
if (m_archive == nullptr) {
135+
throw std::invalid_argument("FileInZip: archive is nullptr");
136+
}
137+
}
132138

133139
FileLocation FileInZip::location() const noexcept {
134140
return m_archive->file()->location();
@@ -140,12 +146,23 @@ std::size_t FileInZip::size() const {
140146
return stat.m_uncomp_size;
141147
}
142148

143-
std::optional<common::Path> FileInZip::disk_path() const { return {}; }
149+
std::optional<common::Path> FileInZip::disk_path() const {
150+
return std::nullopt;
151+
}
144152

145153
const char *FileInZip::memory_data() const { return nullptr; }
146154

147155
std::unique_ptr<std::istream> FileInZip::stream() const {
156+
if (mz_zip_reader_is_file_encrypted(m_archive->zip(), m_index)) {
157+
return nullptr;
158+
}
159+
if (!mz_zip_reader_is_file_supported(m_archive->zip(), m_index)) {
160+
return nullptr;
161+
}
148162
auto iter = mz_zip_reader_extract_iter_new(m_archive->zip(), m_index, 0);
163+
if (iter == nullptr) {
164+
return nullptr;
165+
}
149166
return std::make_unique<FileInZipIstream>(m_archive, iter);
150167
}
151168

0 commit comments

Comments
 (0)