• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <base/logging.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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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) << __func__ << ": 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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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(WARNING) << __func__ << ": 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