• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/cfx_memorystream.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fxcrt/fx_safe_types.h"
13 #include "core/fxcrt/span_util.h"
14 
15 CFX_MemoryStream::CFX_MemoryStream() = default;
16 
17 CFX_MemoryStream::~CFX_MemoryStream() = default;
18 
GetSize()19 FX_FILESIZE CFX_MemoryStream::GetSize() {
20   return static_cast<FX_FILESIZE>(m_nCurSize);
21 }
22 
IsEOF()23 bool CFX_MemoryStream::IsEOF() {
24   return m_nCurPos >= static_cast<size_t>(GetSize());
25 }
26 
GetPosition()27 FX_FILESIZE CFX_MemoryStream::GetPosition() {
28   return static_cast<FX_FILESIZE>(m_nCurPos);
29 }
30 
Flush()31 bool CFX_MemoryStream::Flush() {
32   return true;
33 }
34 
GetSpan() const35 pdfium::span<const uint8_t> CFX_MemoryStream::GetSpan() const {
36   return pdfium::make_span(m_data).first(m_nCurSize);
37 }
38 
ReadBlockAtOffset(pdfium::span<uint8_t> buffer,FX_FILESIZE offset)39 bool CFX_MemoryStream::ReadBlockAtOffset(pdfium::span<uint8_t> buffer,
40                                          FX_FILESIZE offset) {
41   if (buffer.empty() || offset < 0)
42     return false;
43 
44   FX_SAFE_SIZE_T new_pos = buffer.size();
45   new_pos += offset;
46   if (!new_pos.IsValid() || new_pos.ValueOrDefault(0) == 0 ||
47       new_pos.ValueOrDie() > m_nCurSize) {
48     return false;
49   }
50 
51   m_nCurPos = new_pos.ValueOrDie();
52   // Safe to cast `offset` because it was used to calculate `new_pos` above, and
53   // `new_pos` is valid.
54   fxcrt::spancpy(buffer,
55                  GetSpan().subspan(static_cast<size_t>(offset), buffer.size()));
56   return true;
57 }
58 
ReadBlock(pdfium::span<uint8_t> buffer)59 size_t CFX_MemoryStream::ReadBlock(pdfium::span<uint8_t> buffer) {
60   if (m_nCurPos >= m_nCurSize)
61     return 0;
62 
63   size_t nRead = std::min(buffer.size(), m_nCurSize - m_nCurPos);
64   if (!ReadBlockAtOffset(buffer.first(nRead), static_cast<int32_t>(m_nCurPos)))
65     return 0;
66 
67   return nRead;
68 }
69 
WriteBlockAtOffset(pdfium::span<const uint8_t> buffer,FX_FILESIZE offset)70 bool CFX_MemoryStream::WriteBlockAtOffset(pdfium::span<const uint8_t> buffer,
71                                           FX_FILESIZE offset) {
72   if (offset < 0)
73     return false;
74 
75   if (buffer.empty())
76     return true;
77 
78   FX_SAFE_SIZE_T safe_new_pos = buffer.size();
79   safe_new_pos += offset;
80   if (!safe_new_pos.IsValid())
81     return false;
82 
83   size_t new_pos = safe_new_pos.ValueOrDie();
84   if (new_pos > m_data.size()) {
85     static constexpr size_t kBlockSize = 64 * 1024;
86     FX_SAFE_SIZE_T new_size = new_pos;
87     new_size *= 2;
88     new_size += (kBlockSize - 1);
89     new_size /= kBlockSize;
90     new_size *= kBlockSize;
91     if (!new_size.IsValid())
92       return false;
93 
94     m_data.resize(new_size.ValueOrDie());
95   }
96   m_nCurPos = new_pos;
97 
98   // Safe to cast `offset` because it was used to calculate `safe_new_pos`
99   // above, and `safe_new_pos` is valid.
100   fxcrt::spancpy(pdfium::make_span(m_data).subspan(static_cast<size_t>(offset)),
101                  buffer);
102   m_nCurSize = std::max(m_nCurSize, m_nCurPos);
103 
104   return true;
105 }
106