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