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 "base/logging.h"
18 :
19 : namespace common {
20 :
21 : namespace {
22 :
23 : template <class CharType>
24 : bool GetStringAtImpl(const BinaryBufferParser* parser, size_t pos,
25 E : size_t alignment, const CharType** ptr, size_t* len) {
26 E : DCHECK_NE(static_cast<BinaryBufferParser*>(nullptr), parser);
27 E : DCHECK_NE(static_cast<CharType**>(nullptr), ptr);
28 E : DCHECK_NE(static_cast<size_t*>(nullptr), len);
29 :
30 : if (!common::IsAligned(reinterpret_cast<const uint8*>(parser->data()) + pos,
31 E : alignment)) {
32 i : return false;
33 : }
34 :
35 E : const CharType* start = NULL;
36 E : if (!parser->GetAt(pos, sizeof(*start), &start))
37 E : return false;
38 :
39 E : size_t num_chars = (parser->data_len() - pos) / sizeof(*start);
40 E : for (size_t strlen = 0; strlen < num_chars; ++strlen) {
41 E : if (start[strlen] == '\0') {
42 E : *len = strlen;
43 E : *ptr = start;
44 E : return true;
45 : }
46 E : }
47 :
48 E : return false;
49 E : }
50 :
51 : } // namespace
52 :
53 E : BinaryBufferParser::BinaryBufferParser() : data_(nullptr), data_len_(0) {}
54 :
55 : BinaryBufferParser::BinaryBufferParser(const void* data, size_t data_len)
56 E : : data_(reinterpret_cast<const int8*>(data)), data_len_(data_len) {
57 E : }
58 :
59 E : void BinaryBufferParser::SetData(const void* data, size_t data_len) {
60 E : data_ = reinterpret_cast<const int8*>(data);
61 E : data_len_ = data_len;
62 E : }
63 :
64 E : bool BinaryBufferParser::Contains(size_t pos, size_t data_len) const {
65 : // Guard against overflow.
66 E : if (pos < 0 || pos > data_len_)
67 E : return false;
68 E : if (data_len < 0 || data_len > data_len_)
69 E : return false;
70 :
71 : // Make sure the range is fully contained in the buffer.
72 E : if (pos + data_len > data_len_)
73 E : return false;
74 :
75 E : return true;
76 E : }
77 :
78 : bool BinaryBufferParser::GetAt(size_t pos,
79 : size_t data_len,
80 E : const void** data_ptr) const {
81 E : if (!Contains(pos, data_len))
82 E : return false;
83 :
84 E : *data_ptr = data_ + pos;
85 E : return true;
86 E : }
87 :
88 : bool BinaryBufferParser::GetStringAt(size_t pos, const char** ptr,
89 E : size_t* len) const {
90 E : return GetStringAtImpl(this, pos, sizeof(char), ptr, len);
91 E : }
92 :
93 : bool BinaryBufferParser::GetStringAt(size_t pos, const wchar_t** ptr,
94 E : size_t* len) const {
95 E : return GetStringAtImpl(this, pos, sizeof(wchar_t), ptr, len);
96 E : }
97 :
98 : bool BinaryBufferParser::GetStringAtIgnoreAlignment(
99 : size_t pos, const wchar_t** ptr, size_t* len) const {
100 : return GetStringAtImpl(this, pos, 1, ptr, len);
101 : }
102 :
103 : BinaryBufferReader::BinaryBufferReader(const void* data, size_t data_len)
104 E : : parser_(data, data_len), pos_(0) {
105 E : }
106 :
107 E : size_t BinaryBufferReader::RemainingBytes() const {
108 E : DCHECK(pos_ <= parser_.data_len());
109 E : return parser_.data_len() - pos_;
110 E : }
111 :
112 E : bool BinaryBufferReader::Consume(size_t bytes) {
113 E : if (!parser_.Contains(pos_ + bytes, 0))
114 E : return false;
115 :
116 E : pos_ += bytes;
117 E : return true;
118 E : }
119 :
120 E : bool BinaryBufferReader::Align(size_t bytes) {
121 E : DCHECK((bytes & (bytes - 1)) == 0);
122 E : size_t mask = bytes - 1;
123 E : size_t offset = (bytes - (pos_ & mask)) & mask;
124 E : if (offset == 0)
125 E : return true;
126 :
127 E : return Consume(offset);
128 E : }
129 :
130 E : bool BinaryBufferReader::IsAligned(size_t bytes) {
131 E : DCHECK((bytes & (bytes - 1)) == 0);
132 E : size_t mask = bytes - 1;
133 E : size_t offset = (bytes - (pos_ & mask)) & mask;
134 E : return offset == 0;
135 E : }
136 :
137 E : bool BinaryBufferReader::Peek(size_t data_len, const void** data) {
138 E : return parser_.GetAt(pos_, data_len, data);
139 E : }
140 :
141 E : bool BinaryBufferReader::Read(size_t data_len, const void** data) {
142 E : if (!Peek(data_len, data))
143 E : return false;
144 :
145 E : bool consumed = Consume(data_len);
146 E : DCHECK(consumed == true);
147 E : return true;
148 E : }
149 :
150 E : bool BinaryBufferReader::PeekString(const char** str, size_t* str_len) {
151 E : return parser_.GetStringAt(pos_, str, str_len);
152 E : }
153 :
154 E : bool BinaryBufferReader::PeekString(const wchar_t** str, size_t* str_len) {
155 E : return parser_.GetStringAt(pos_, str, str_len);
156 E : }
157 :
158 E : bool BinaryBufferReader::ReadString(const char** str, size_t* str_len) {
159 E : size_t len = 0;
160 E : if (!PeekString(str, &len))
161 E : return false;
162 :
163 E : bool consumed = Consume(len + 1);
164 E : DCHECK(consumed == true);
165 E : *str_len = len;
166 E : return true;
167 E : }
168 :
169 E : bool BinaryBufferReader::ReadString(const wchar_t** str, size_t* str_len) {
170 E : size_t len = 0;
171 E : if (!PeekString(str, &len))
172 E : return false;
173 :
174 E : bool consumed = Consume((len + 1) * sizeof(**str));
175 E : DCHECK(consumed == true);
176 E : *str_len = len;
177 E : return true;
178 E : }
179 :
180 : } // namespace common
|