Coverage Report

Created: 2023-09-25 06:33

/src/botan/src/lib/utils/data_src.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* DataSource
3
* (C) 1999-2007 Jack Lloyd
4
*     2005 Matthew Gregan
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/data_src.h>
10
11
#include <botan/exceptn.h>
12
#include <botan/internal/fmt.h>
13
#include <algorithm>
14
#include <istream>
15
16
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
17
   #include <fstream>
18
#endif
19
20
namespace Botan {
21
22
/*
23
* Read a single byte from the DataSource
24
*/
25
175
size_t DataSource::read_byte(uint8_t& out) {
26
175
   return read(&out, 1);
27
175
}
28
29
/*
30
* Peek a single byte from the DataSource
31
*/
32
0
size_t DataSource::peek_byte(uint8_t& out) const {
33
0
   return peek(&out, 1, 0);
34
0
}
35
36
/*
37
* Discard the next N bytes of the data
38
*/
39
0
size_t DataSource::discard_next(size_t n) {
40
0
   uint8_t buf[64] = {0};
41
0
   size_t discarded = 0;
42
43
0
   while(n) {
44
0
      const size_t got = this->read(buf, std::min(n, sizeof(buf)));
45
0
      discarded += got;
46
0
      n -= got;
47
48
0
      if(got == 0) {
49
0
         break;
50
0
      }
51
0
   }
52
53
0
   return discarded;
54
0
}
55
56
/*
57
* Read from a memory buffer
58
*/
59
88
size_t DataSource_Memory::read(uint8_t out[], size_t length) {
60
88
   const size_t got = std::min<size_t>(m_source.size() - m_offset, length);
61
88
   copy_mem(out, m_source.data() + m_offset, got);
62
88
   m_offset += got;
63
88
   return got;
64
88
}
65
66
29
bool DataSource_Memory::check_available(size_t n) {
67
29
   return (n <= (m_source.size() - m_offset));
68
29
}
69
70
/*
71
* Peek into a memory buffer
72
*/
73
0
size_t DataSource_Memory::peek(uint8_t out[], size_t length, size_t peek_offset) const {
74
0
   const size_t bytes_left = m_source.size() - m_offset;
75
0
   if(peek_offset >= bytes_left) {
76
0
      return 0;
77
0
   }
78
79
0
   const size_t got = std::min(bytes_left - peek_offset, length);
80
0
   copy_mem(out, &m_source[m_offset + peek_offset], got);
81
0
   return got;
82
0
}
83
84
/*
85
* Check if the memory buffer is empty
86
*/
87
0
bool DataSource_Memory::end_of_data() const {
88
0
   return (m_offset == m_source.size());
89
0
}
90
91
/*
92
* DataSource_Memory Constructor
93
*/
94
DataSource_Memory::DataSource_Memory(std::string_view in) :
95
0
      m_source(cast_char_ptr_to_uint8(in.data()), cast_char_ptr_to_uint8(in.data()) + in.length()), m_offset(0) {}
96
97
/*
98
* Read from a stream
99
*/
100
0
size_t DataSource_Stream::read(uint8_t out[], size_t length) {
101
0
   m_source.read(cast_uint8_ptr_to_char(out), length);
102
0
   if(m_source.bad()) {
103
0
      throw Stream_IO_Error("DataSource_Stream::read: Source failure");
104
0
   }
105
106
0
   const size_t got = static_cast<size_t>(m_source.gcount());
107
0
   m_total_read += got;
108
0
   return got;
109
0
}
110
111
0
bool DataSource_Stream::check_available(size_t n) {
112
0
   const std::streampos orig_pos = m_source.tellg();
113
0
   m_source.seekg(0, std::ios::end);
114
0
   const size_t avail = static_cast<size_t>(m_source.tellg() - orig_pos);
115
0
   m_source.seekg(orig_pos);
116
0
   return (avail >= n);
117
0
}
118
119
/*
120
* Peek into a stream
121
*/
122
0
size_t DataSource_Stream::peek(uint8_t out[], size_t length, size_t offset) const {
123
0
   if(end_of_data()) {
124
0
      throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
125
0
   }
126
127
0
   size_t got = 0;
128
129
0
   if(offset) {
130
0
      secure_vector<uint8_t> buf(offset);
131
0
      m_source.read(cast_uint8_ptr_to_char(buf.data()), buf.size());
132
0
      if(m_source.bad()) {
133
0
         throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
134
0
      }
135
0
      got = static_cast<size_t>(m_source.gcount());
136
0
   }
137
138
0
   if(got == offset) {
139
0
      m_source.read(cast_uint8_ptr_to_char(out), length);
140
0
      if(m_source.bad()) {
141
0
         throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
142
0
      }
143
0
      got = static_cast<size_t>(m_source.gcount());
144
0
   }
145
146
0
   if(m_source.eof()) {
147
0
      m_source.clear();
148
0
   }
149
0
   m_source.seekg(m_total_read, std::ios::beg);
150
151
0
   return got;
152
0
}
153
154
/*
155
* Check if the stream is empty or in error
156
*/
157
0
bool DataSource_Stream::end_of_data() const {
158
0
   return (!m_source.good());
159
0
}
160
161
/*
162
* Return a human-readable ID for this stream
163
*/
164
0
std::string DataSource_Stream::id() const {
165
0
   return m_identifier;
166
0
}
167
168
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
169
170
/*
171
* DataSource_Stream Constructor
172
*/
173
DataSource_Stream::DataSource_Stream(std::string_view path, bool use_binary) :
174
      m_identifier(path),
175
      m_source_memory(std::make_unique<std::ifstream>(std::string(path), use_binary ? std::ios::binary : std::ios::in)),
176
      m_source(*m_source_memory),
177
0
      m_total_read(0) {
178
0
   if(!m_source.good()) {
179
0
      throw Stream_IO_Error(fmt("DataSource: Failure opening file '{}'", path));
180
0
   }
181
0
}
182
183
#endif
184
185
/*
186
* DataSource_Stream Constructor
187
*/
188
DataSource_Stream::DataSource_Stream(std::istream& in, std::string_view name) :
189
0
      m_identifier(name), m_source(in), m_total_read(0) {}
190
191
0
DataSource_Stream::~DataSource_Stream() = default;
192
193
}  // namespace Botan