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()41DataElementReader::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()84DataElementReader::DataElement DataElementReader::ParseFail() { 85 it_ = end_; 86 return std::monostate(); 87 } 88 89 template <class IntegerType> ReadInteger()90DataElementReader::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()98DataElementReader::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)109DataElementReader::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)129DataElementReader::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)149DataElementReader::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)176DataElementReader::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)208DataElementReader::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