• 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/stl_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::Copy(GetSpan().subspan(static_cast<size_t>(offset), buffer.size()),
55               buffer);
56   return true;
57 }
58 
WriteBlock(pdfium::span<const uint8_t> buffer)59 bool CFX_MemoryStream::WriteBlock(pdfium::span<const uint8_t> buffer) {
60   if (buffer.empty())
61     return true;
62 
63   FX_SAFE_SIZE_T safe_new_pos = buffer.size();
64   safe_new_pos += m_nCurSize;
65   if (!safe_new_pos.IsValid()) {
66     return false;
67   }
68 
69   size_t new_pos = safe_new_pos.ValueOrDie();
70   if (new_pos > m_data.size()) {
71     static constexpr size_t kBlockSize = 64 * 1024;
72     FX_SAFE_SIZE_T new_size = new_pos;
73     new_size *= 2;
74     new_size += (kBlockSize - 1);
75     new_size /= kBlockSize;
76     new_size *= kBlockSize;
77     if (!new_size.IsValid())
78       return false;
79 
80     m_data.resize(new_size.ValueOrDie());
81   }
82   m_nCurPos = new_pos;
83 
84   fxcrt::Copy(buffer, pdfium::make_span(m_data).subspan(m_nCurSize));
85   m_nCurSize = std::max(m_nCurSize, m_nCurPos);
86 
87   return true;
88 }
89