1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "data_element_reader.h"
18
19 #include <bluetooth/log.h>
20
21 #include <type_traits>
22
23 #include "sdp_logging_helper.h"
24 #include "types/bluetooth/uuid.h"
25
26 // A helper macro that can verify that there is enough data remaining in the
27 // reader to extract without overflowing. end_ - it_ should never be negative
28 // so casting it to a size_t is always safe. If it does fail, set it_ to end_
29 // so that all additional readings fail.
30 #define CHECK_REMAINING_LEN(x) \
31 do { \
32 if ((size_t)(end_ - it_) < x) { \
33 log::warn("Extract would read past end of data."); \
34 return ParseFail(); \
35 } \
36 } while (0)
37
38 namespace bluetooth {
39 namespace sdp {
40
ReadNext()41 DataElementReader::DataElement DataElementReader::ReadNext() {
42 if (it_ > end_) log::fatal("Beginning of buffer is past end of buffer.");
43 if (it_ == end_) return std::monostate();
44
45 uint8_t descriptor = *it_++;
46 DataElementType type = static_cast<DataElementType>(descriptor >> 3);
47 DataElementSize size = static_cast<DataElementSize>(descriptor & 0b00000111);
48
49 // All types with a value greater than URL are currently reserved.
50 if (type > DataElementType::MAX_VALUE) {
51 log::warn("Trying to use a reserved data element type");
52 return ParseFail();
53 }
54
55 switch (type) {
56 case DataElementType::BOOLEAN:
57 if (size != DataElementSize::BYTE1) {
58 log::warn("Invalid size for bool: {}", size);
59 return ParseFail();
60 }
61
62 CHECK_REMAINING_LEN(1);
63 return (it_.extract<uint8_t>() != 0);
64 case DataElementType::SIGNED_INT:
65 return ReadSignedInt(size);
66 case DataElementType::UNSIGNED_INT:
67 return ReadUnsignedInt(size);
68 case DataElementType::UUID:
69 return ReadUuid(size);
70 case DataElementType::STRING:
71 return ReadString(size);
72 case DataElementType::DATA_ELEMENT_SEQUENCE:
73 return ReadSequence(size);
74 default:
75 // TODO: The other data element types are never used in the previous SDP
76 // implementation. We should properly handle them in the future though
77 // for completeness.
78 log::error("Unhandled Data Element Type: {}", type);
79 }
80
81 return ParseFail();
82 }
83
ParseFail()84 DataElementReader::DataElement DataElementReader::ParseFail() {
85 it_ = end_;
86 return std::monostate();
87 }
88
89 template <class IntegerType>
ReadInteger()90 DataElementReader::DataElement DataElementReader::ReadInteger() {
91 static_assert(std::is_integral<IntegerType>::value,
92 "ReadInteger requires an integral type.");
93
94 CHECK_REMAINING_LEN(sizeof(IntegerType));
95 return it_.extractBE<IntegerType>();
96 }
97
ReadLargeInt()98 DataElementReader::DataElement DataElementReader::ReadLargeInt() {
99 CHECK_REMAINING_LEN(16);
100
101 std::array<uint8_t, 16> array;
102 for (size_t i = 0; i < sizeof(uint8_t[16]); i++) {
103 array[i] = it_.extract<uint8_t>();
104 }
105
106 return array;
107 }
108
ReadSignedInt(DataElementSize size)109 DataElementReader::DataElement DataElementReader::ReadSignedInt(
110 DataElementSize size) {
111 switch (size) {
112 case DataElementSize::BYTE1:
113 return ReadInteger<int8_t>();
114 case DataElementSize::BYTE2:
115 return ReadInteger<int16_t>();
116 case DataElementSize::BYTE4:
117 return ReadInteger<int32_t>();
118 case DataElementSize::BYTE8:
119 return ReadInteger<int64_t>();
120 case DataElementSize::BYTE16:
121 return ReadLargeInt();
122 default:
123 log::warn("Invalid size for int: {}", size);
124 }
125
126 return ParseFail();
127 }
128
ReadUnsignedInt(DataElementSize size)129 DataElementReader::DataElement DataElementReader::ReadUnsignedInt(
130 DataElementSize size) {
131 switch (size) {
132 case DataElementSize::BYTE1:
133 return ReadInteger<uint8_t>();
134 case DataElementSize::BYTE2:
135 return ReadInteger<uint16_t>();
136 case DataElementSize::BYTE4:
137 return ReadInteger<uint32_t>();
138 case DataElementSize::BYTE8:
139 return ReadInteger<uint64_t>();
140 case DataElementSize::BYTE16:
141 return ReadLargeInt();
142 default:
143 log::warn("Invalid size for uint: {}", size);
144 }
145
146 return ParseFail();
147 }
148
ReadUuid(DataElementSize size)149 DataElementReader::DataElement DataElementReader::ReadUuid(
150 DataElementSize size) {
151 if (size == DataElementSize::BYTE2) {
152 CHECK_REMAINING_LEN(2);
153 return Uuid::From16Bit(it_.extractBE<uint16_t>());
154 }
155
156 if (size == DataElementSize::BYTE4) {
157 CHECK_REMAINING_LEN(4);
158 return Uuid::From32Bit(it_.extractBE<uint32_t>());
159 }
160
161 if (size == DataElementSize::BYTE16) {
162 CHECK_REMAINING_LEN(16);
163
164 Uuid::UUID128Bit uuid_array;
165 for (int i = 0; i < 16; i++) {
166 uuid_array[i] = it_.extract<uint8_t>();
167 }
168
169 return Uuid::From128BitBE(uuid_array);
170 }
171
172 log::warn("Invalid size for UUID: {}", size);
173 return ParseFail();
174 }
175
ReadString(DataElementSize size)176 DataElementReader::DataElement DataElementReader::ReadString(
177 DataElementSize size) {
178 uint32_t num_bytes = 0;
179
180 switch (size) {
181 case DataElementSize::ADDITIONAL_8BIT:
182 CHECK_REMAINING_LEN(1);
183 num_bytes = it_.extractBE<uint8_t>();
184 break;
185 case DataElementSize::ADDITIONAL_16BIT:
186 CHECK_REMAINING_LEN(2);
187 num_bytes = it_.extractBE<uint16_t>();
188 break;
189 case DataElementSize::ADDITIONAL_32BIT:
190 CHECK_REMAINING_LEN(4);
191 num_bytes = it_.extractBE<uint32_t>();
192 break;
193 default:
194 log::warn("Invalid size for string: {}", size);
195 return ParseFail();
196 }
197
198 CHECK_REMAINING_LEN(num_bytes);
199
200 std::string str;
201 for (uint32_t i = 0; i < num_bytes; i++) {
202 str.push_back(it_.extractBE<uint8_t>());
203 }
204
205 return str;
206 }
207
ReadSequence(DataElementSize size)208 DataElementReader::DataElement DataElementReader::ReadSequence(
209 DataElementSize size) {
210 uint32_t num_bytes = 0;
211
212 switch (size) {
213 case DataElementSize::ADDITIONAL_8BIT:
214 CHECK_REMAINING_LEN(1);
215 num_bytes = it_.extractBE<uint8_t>();
216 break;
217 case DataElementSize::ADDITIONAL_16BIT:
218 CHECK_REMAINING_LEN(2);
219 num_bytes = it_.extractBE<uint16_t>();
220 break;
221 case DataElementSize::ADDITIONAL_32BIT:
222 CHECK_REMAINING_LEN(4);
223 num_bytes = it_.extractBE<uint32_t>();
224 break;
225 default:
226 log::warn("Invalid size for string: {}", size);
227 return ParseFail();
228 }
229
230 CHECK_REMAINING_LEN(num_bytes);
231
232 // Create a parser that points to the beginning of the next sequence and move
233 // the iterator to past the end of the new sequence.
234 auto&& temp = DataElementReader(it_, it_ + num_bytes);
235 it_ += num_bytes;
236 return std::move(temp);
237 }
238
239 } // namespace sdp
240 } // namespace bluetooth
241