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