1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/common/buffer_parser.h"
16 :
17 : #include <stdint.h>
18 :
19 : #include "base/logging.h"
20 :
21 : namespace common {
22 :
23 : namespace {
24 :
25 : template <class CharType>
26 : bool GetStringAtImpl(const BinaryBufferParser* parser, size_t pos,
27 E : size_t alignment, const CharType** ptr, size_t* len) {
28 E : DCHECK_NE(static_cast<BinaryBufferParser*>(nullptr), parser);
29 E : DCHECK_NE(static_cast<CharType**>(nullptr), ptr);
30 E : DCHECK_NE(static_cast<size_t*>(nullptr), len);
31 :
32 E : if (!common::IsAligned(reinterpret_cast<const uint8_t*>(parser->data()) + pos,
33 : alignment)) {
34 i : return false;
35 : }
36 :
37 E : const CharType* start = NULL;
38 E : if (!parser->GetAt(pos, sizeof(*start), &start))
39 E : return false;
40 :
41 E : size_t num_chars = (parser->data_len() - pos) / sizeof(*start);
42 E : for (size_t strlen = 0; strlen < num_chars; ++strlen) {
43 E : if (start[strlen] == '\0') {
44 E : *len = strlen;
45 E : *ptr = start;
46 E : return true;
47 : }
48 E : }
49 :
50 E : return false;
51 E : }
52 :
53 : } // namespace
54 :
55 E : BinaryBufferParser::BinaryBufferParser() : data_(nullptr), data_len_(0) {}
56 :
57 : BinaryBufferParser::BinaryBufferParser(const void* data, size_t data_len)
58 E : : data_(reinterpret_cast<const int8_t*>(data)), data_len_(data_len) {
59 E : }
60 :
61 E : void BinaryBufferParser::SetData(const void* data, size_t data_len) {
62 E : data_ = reinterpret_cast<const int8_t*>(data);
63 E : data_len_ = data_len;
64 E : }
65 :
66 E : bool BinaryBufferParser::Contains(size_t pos, size_t data_len) const {
67 : // Guard against overflow.
68 E : if (pos < 0 || pos > data_len_)
69 E : return false;
70 E : if (data_len < 0 || data_len > data_len_)
71 E : return false;
72 :
73 : // Make sure the range is fully contained in the buffer.
74 E : if (pos + data_len > data_len_)
75 E : return false;
76 :
77 E : return true;
78 E : }
79 :
80 : bool BinaryBufferParser::GetAt(size_t pos,
81 : size_t data_len,
82 E : const void** data_ptr) const {
83 E : if (!Contains(pos, data_len))
84 E : return false;
85 :
86 E : *data_ptr = data_ + pos;
87 E : return true;
88 E : }
89 :
90 : bool BinaryBufferParser::GetStringAt(size_t pos, const char** ptr,
91 E : size_t* len) const {
92 E : return GetStringAtImpl(this, pos, sizeof(char), ptr, len);
93 E : }
94 :
95 : bool BinaryBufferParser::GetStringAt(size_t pos, const wchar_t** ptr,
96 E : size_t* len) const {
97 E : return GetStringAtImpl(this, pos, sizeof(wchar_t), ptr, len);
98 E : }
99 :
100 : bool BinaryBufferParser::GetStringAtIgnoreAlignment(
101 : size_t pos, const wchar_t** ptr, size_t* len) const {
102 : return GetStringAtImpl(this, pos, 1, ptr, len);
103 : }
104 :
105 : BinaryBufferReader::BinaryBufferReader(const void* data, size_t data_len)
106 E : : parser_(data, data_len), pos_(0) {
107 E : }
108 :
109 E : size_t BinaryBufferReader::RemainingBytes() const {
110 E : DCHECK(pos_ <= parser_.data_len());
111 E : return parser_.data_len() - pos_;
112 E : }
113 :
114 E : bool BinaryBufferReader::Consume(size_t bytes) {
115 E : if (!parser_.Contains(pos_ + bytes, 0))
116 E : return false;
117 :
118 E : pos_ += bytes;
119 E : return true;
120 E : }
121 :
122 E : bool BinaryBufferReader::Align(size_t bytes) {
123 E : DCHECK((bytes & (bytes - 1)) == 0);
124 E : size_t mask = bytes - 1;
125 E : size_t offset = (bytes - (pos_ & mask)) & mask;
126 E : if (offset == 0)
127 E : return true;
128 :
129 E : return Consume(offset);
130 E : }
131 :
132 E : bool BinaryBufferReader::IsAligned(size_t bytes) {
133 E : DCHECK((bytes & (bytes - 1)) == 0);
134 E : size_t mask = bytes - 1;
135 E : size_t offset = (bytes - (pos_ & mask)) & mask;
136 E : return offset == 0;
137 E : }
138 :
139 E : bool BinaryBufferReader::Peek(size_t data_len, const void** data) {
140 E : return parser_.GetAt(pos_, data_len, data);
141 E : }
142 :
143 E : bool BinaryBufferReader::Read(size_t data_len, const void** data) {
144 E : if (!Peek(data_len, data))
145 E : return false;
146 :
147 E : bool consumed = Consume(data_len);
148 E : DCHECK(consumed == true);
149 E : return true;
150 E : }
151 :
152 E : bool BinaryBufferReader::PeekString(const char** str, size_t* str_len) {
153 E : return parser_.GetStringAt(pos_, str, str_len);
154 E : }
155 :
156 E : bool BinaryBufferReader::PeekString(const wchar_t** str, size_t* str_len) {
157 E : return parser_.GetStringAt(pos_, str, str_len);
158 E : }
159 :
160 E : bool BinaryBufferReader::ReadString(const char** str, size_t* str_len) {
161 E : size_t len = 0;
162 E : if (!PeekString(str, &len))
163 E : return false;
164 :
165 E : bool consumed = Consume(len + 1);
166 E : DCHECK(consumed == true);
167 E : *str_len = len;
168 E : return true;
169 E : }
170 :
171 E : bool BinaryBufferReader::ReadString(const wchar_t** str, size_t* str_len) {
172 E : size_t len = 0;
173 E : if (!PeekString(str, &len))
174 E : return false;
175 :
176 E : bool consumed = Consume((len + 1) * sizeof(**str));
177 E : DCHECK(consumed == true);
178 E : *str_len = len;
179 E : return true;
180 E : }
181 :
182 : } // namespace common
|