@@ -65,7 +65,8 @@ DB0_PACKED_END
6565 {
6666 public:
6767 // buffer is 2 pages long
68- DiffReader (Page_IO &, std::uint64_t page_num, std::byte *begin, std::byte *end);
68+ DiffReader (Page_IO &, std::uint64_t page_num, std::byte *begin, std::byte *end,
69+ const std::function<void ()> &decode_fault);
6970
7071 // appy diffs from a specific page / state number into a provided data buffer
7172 // if underflow occurs then next page needs to be fetched and apply repeated
@@ -84,6 +85,7 @@ DB0_PACKED_END
8485 std::byte const *m_end;
8586 // the number of objects remaining to be read
8687 unsigned int m_size = 0 ;
88+ const std::function<void ()> &m_decode_fault;
8789 };
8890
8991 DiffWriter::DiffWriter (Page_IO &page_io, std::byte *begin, std::byte *end)
@@ -166,18 +168,23 @@ DB0_PACKED_END
166168 return m_header.m_size == 0 && m_header.m_offset == 0 ;
167169 }
168170
169- DiffReader::DiffReader (Page_IO &page_io, std::uint64_t page_num, std::byte *begin, std::byte *end)
171+ DiffReader::DiffReader (Page_IO &page_io, std::uint64_t page_num, std::byte *begin, std::byte *end,
172+ const std::function<void ()> &decode_fault)
170173 : m_page_io(page_io)
171174 , m_page_size(page_io.getPageSize())
172175 , m_page_num(page_num)
173176 , m_begin(begin)
174177 , m_current(begin + m_page_size)
175178 , m_end(end)
179+ , m_decode_fault(decode_fault)
176180 {
177181 page_io.read (page_num, m_begin + m_page_size);
178182 m_size = o_diff_header::__const_ref (m_current).m_size ;
179183 // position at the first diff block
180- m_current += o_diff_header::sizeOf ()+ o_diff_header::__const_ref (m_current).m_offset ;
184+ m_current += o_diff_header::sizeOf () + o_diff_header::__const_ref (m_current).m_offset ;
185+ if (m_current > m_end) {
186+ m_decode_fault ();
187+ }
181188 }
182189
183190 bool DiffReader::apply (std::byte *dp_data, std::pair<std::uint64_t , std::uint32_t > page_and_state,
@@ -197,8 +204,11 @@ DB0_PACKED_END
197204 underflow = true ;
198205 return false ;
199206 }
200-
201- o_diff_buffer::__const_ref (m_current).apply (dp_data, dp_data + m_page_size);
207+
208+ auto &diff_buf = o_diff_buffer::__safe_const_ref (
209+ const_bounded_buf_t (m_decode_fault, m_current, m_end)
210+ );
211+ diff_buf.apply (dp_data, dp_data + m_page_size);
202212 m_current += diff_buf_size;
203213 --m_size;
204214 return true ;
@@ -234,12 +244,18 @@ DB0_PACKED_END
234244 , m_writer(std::make_unique<DiffWriter>(
235245 reinterpret_cast <Page_IO&>(*this ), m_write_buf.data(), m_write_buf.data() + m_write_buf.size())
236246 )
247+ , m_decode_fault([]() {
248+ THROWF (db0::IOException) << " Diff_IO: decode fault - corrupt diff data" ;
249+ })
237250 {
238251 }
239252
240253 Diff_IO::Diff_IO (std::size_t header_size, CFile &file, std::uint32_t page_size)
241254 : Page_IO(header_size, file, page_size)
242255 , m_read_buf(page_size * 2 )
256+ , m_decode_fault([]() {
257+ THROWF (db0::IOException) << " Diff_IO: decode fault - corrupt diff data" ;
258+ })
243259 {
244260 }
245261
@@ -294,7 +310,7 @@ DB0_PACKED_END
294310 {
295311 // must lock because the read-buffer is shared
296312 std::unique_lock<std::mutex> lock (m_mx_read);
297- DiffReader reader ((Page_IO&)*this , page_num, m_read_buf.data (), m_read_buf.data () + m_read_buf.size ());
313+ DiffReader reader ((Page_IO&)*this , page_num, m_read_buf.data (), m_read_buf.data () + m_read_buf.size (), m_decode_fault );
298314 for (;;) {
299315 bool underflow = false ;
300316 if (reader.apply ((std::byte*)buffer, page_and_state, underflow)) {
@@ -305,7 +321,7 @@ DB0_PACKED_END
305321 reader.loadNext ();
306322 continue ;
307323 }
308- THROWF (db0::InternalException) << " Diff block not found" ;
324+ THROWF (db0::InternalException) << " Diff block not found" ;
309325 }
310326 }
311327
0 commit comments