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()39DataElementReader::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()82DataElementReader::DataElement DataElementReader::ParseFail() { 83 it_ = end_; 84 return std::monostate(); 85 } 86 87 template <class IntegerType> ReadInteger()88DataElementReader::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()96DataElementReader::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)107DataElementReader::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)127DataElementReader::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)147DataElementReader::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)174DataElementReader::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)206DataElementReader::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