Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2023 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #include <lib/core/TLVReader.h>
19 :
20 : #include <stdint.h>
21 : #include <string.h>
22 :
23 : #include <lib/core/CHIPConfig.h>
24 : #include <lib/core/CHIPEncoding.h>
25 : #include <lib/core/CHIPError.h>
26 : #include <lib/core/CHIPSafeCasts.h>
27 : #include <lib/core/DataModelTypes.h>
28 : #include <lib/core/Optional.h>
29 : #include <lib/core/TLVBackingStore.h>
30 : #include <lib/core/TLVCommon.h>
31 : #include <lib/core/TLVTags.h>
32 : #include <lib/core/TLVTypes.h>
33 : #include <lib/support/BufferWriter.h>
34 : #include <lib/support/BytesToHex.h>
35 : #include <lib/support/CHIPMem.h>
36 : #include <lib/support/CodeUtils.h>
37 : #include <lib/support/SafeInt.h>
38 : #include <lib/support/Span.h>
39 : #include <lib/support/logging/TextOnlyLogging.h>
40 :
41 : #if CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
42 : #include <lib/support/utf8.h>
43 : #endif
44 :
45 : namespace chip {
46 : namespace TLV {
47 :
48 : using namespace chip::Encoding;
49 :
50 : static const uint8_t sTagSizes[] = { 0, 1, 2, 4, 2, 4, 6, 8 };
51 :
52 1461629 : void TLVReader::Init(const uint8_t * data, size_t dataLen)
53 : {
54 : // TODO: Maybe we can just make mMaxLen and mLenRead size_t instead?
55 1461629 : uint32_t actualDataLen = dataLen > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(dataLen);
56 1461629 : mBackingStore = nullptr;
57 1461629 : mReadPoint = data;
58 1461629 : mBufEnd = data + actualDataLen;
59 1461629 : mLenRead = 0;
60 1461629 : mMaxLen = actualDataLen;
61 1461629 : ClearElementState();
62 1461629 : mContainerType = kTLVType_NotSpecified;
63 1461629 : SetContainerOpen(false);
64 :
65 1461629 : ImplicitProfileId = kProfileIdNotSpecified;
66 1461629 : }
67 :
68 4137 : CHIP_ERROR TLVReader::Init(TLVBackingStore & backingStore, uint32_t maxLen)
69 : {
70 4137 : mBackingStore = &backingStore;
71 4137 : mReadPoint = nullptr;
72 4137 : uint32_t bufLen = 0;
73 4137 : CHIP_ERROR err = mBackingStore->OnInit(*this, mReadPoint, bufLen);
74 4137 : if (err != CHIP_NO_ERROR)
75 0 : return err;
76 :
77 4137 : mBufEnd = mReadPoint + bufLen;
78 4137 : mLenRead = 0;
79 4137 : mMaxLen = maxLen;
80 4137 : ClearElementState();
81 4137 : mContainerType = kTLVType_NotSpecified;
82 4137 : SetContainerOpen(false);
83 :
84 4137 : ImplicitProfileId = kProfileIdNotSpecified;
85 4137 : AppData = nullptr;
86 4137 : return CHIP_NO_ERROR;
87 : }
88 :
89 499742 : void TLVReader::Init(const TLVReader & aReader)
90 : {
91 : // Initialize private data members
92 :
93 499742 : mElemTag = aReader.mElemTag;
94 499742 : mElemLenOrVal = aReader.mElemLenOrVal;
95 499742 : mBackingStore = aReader.mBackingStore;
96 499742 : mReadPoint = aReader.mReadPoint;
97 499742 : mBufEnd = aReader.mBufEnd;
98 499742 : mLenRead = aReader.mLenRead;
99 499742 : mMaxLen = aReader.mMaxLen;
100 499742 : mControlByte = aReader.mControlByte;
101 499742 : mContainerType = aReader.mContainerType;
102 499742 : SetContainerOpen(aReader.IsContainerOpen());
103 :
104 : // Initialize public data members
105 :
106 499742 : ImplicitProfileId = aReader.ImplicitProfileId;
107 499742 : AppData = aReader.AppData;
108 499742 : }
109 :
110 7805406 : TLVType TLVReader::GetType() const
111 : {
112 7805406 : TLVElementType elemType = ElementType();
113 7805406 : if (elemType == TLVElementType::EndOfContainer)
114 4 : return kTLVType_NotSpecified;
115 7805402 : if (elemType == TLVElementType::FloatingPointNumber32 || elemType == TLVElementType::FloatingPointNumber64)
116 11442 : return kTLVType_FloatingPointNumber;
117 7793960 : if (elemType == TLVElementType::NotSpecified || elemType >= TLVElementType::Null)
118 3122694 : return static_cast<TLVType>(elemType);
119 4671266 : return static_cast<TLVType>(static_cast<uint8_t>(elemType) & ~kTLVTypeSizeMask);
120 : }
121 :
122 100527 : uint32_t TLVReader::GetLength() const
123 : {
124 100527 : if (TLVTypeHasLength(ElementType()))
125 87389 : return static_cast<uint32_t>(mElemLenOrVal);
126 13138 : return 0;
127 : }
128 :
129 2770769 : CHIP_ERROR TLVReader::Get(bool & v) const
130 : {
131 2770769 : TLVElementType elemType = ElementType();
132 2770769 : if (elemType == TLVElementType::BooleanFalse)
133 1381442 : v = false;
134 1389327 : else if (elemType == TLVElementType::BooleanTrue)
135 1389326 : v = true;
136 : else
137 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
138 2770768 : return CHIP_NO_ERROR;
139 : }
140 :
141 1357639 : CHIP_ERROR TLVReader::Get(int8_t & v) const
142 : {
143 1357639 : int64_t v64 = 0;
144 1357639 : CHIP_ERROR err = Get(v64);
145 1357639 : if (!CanCastTo<int8_t>(v64))
146 : {
147 45 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
148 : }
149 1357594 : v = static_cast<int8_t>(v64);
150 1357594 : return err;
151 : }
152 :
153 1353864 : CHIP_ERROR TLVReader::Get(int16_t & v) const
154 : {
155 1353864 : int64_t v64 = 0;
156 1353864 : CHIP_ERROR err = Get(v64);
157 1353864 : if (!CanCastTo<int16_t>(v64))
158 : {
159 4 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
160 : }
161 1353860 : v = static_cast<int16_t>(v64);
162 1353860 : return err;
163 : }
164 :
165 1354237 : CHIP_ERROR TLVReader::Get(int32_t & v) const
166 : {
167 1354237 : int64_t v64 = 0;
168 1354237 : CHIP_ERROR err = Get(v64);
169 1354237 : if (!CanCastTo<int32_t>(v64))
170 : {
171 2 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
172 : }
173 1354235 : v = static_cast<int32_t>(v64);
174 1354235 : return err;
175 : }
176 :
177 5420580 : CHIP_ERROR TLVReader::Get(int64_t & v) const
178 : {
179 : // Internal callers of this method depend on it not modifying "v" on failure.
180 5420580 : switch (ElementType())
181 : {
182 5419252 : case TLVElementType::Int8:
183 5419252 : v = CastToSigned(static_cast<uint8_t>(mElemLenOrVal));
184 5419252 : break;
185 88 : case TLVElementType::Int16:
186 88 : v = CastToSigned(static_cast<uint16_t>(mElemLenOrVal));
187 88 : break;
188 800 : case TLVElementType::Int32:
189 800 : v = CastToSigned(static_cast<uint32_t>(mElemLenOrVal));
190 800 : break;
191 39 : case TLVElementType::Int64:
192 39 : v = CastToSigned(mElemLenOrVal);
193 39 : break;
194 401 : default:
195 401 : return CHIP_ERROR_WRONG_TLV_TYPE;
196 : }
197 :
198 5420179 : return CHIP_NO_ERROR;
199 : }
200 :
201 1393664 : CHIP_ERROR TLVReader::Get(uint8_t & v) const
202 : {
203 1393664 : uint64_t v64 = 0;
204 1393664 : CHIP_ERROR err = Get(v64);
205 1393664 : if (!CanCastTo<uint8_t>(v64))
206 : {
207 3 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
208 : }
209 1393661 : v = static_cast<uint8_t>(v64);
210 1393661 : return err;
211 : }
212 :
213 69611 : CHIP_ERROR TLVReader::Get(uint16_t & v) const
214 : {
215 69611 : uint64_t v64 = 0;
216 69611 : CHIP_ERROR err = Get(v64);
217 69611 : if (!CanCastTo<uint16_t>(v64))
218 : {
219 4 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
220 : }
221 69607 : v = static_cast<uint16_t>(v64);
222 69607 : return err;
223 : }
224 :
225 73053 : CHIP_ERROR TLVReader::Get(uint32_t & v) const
226 : {
227 73053 : uint64_t v64 = 0;
228 73053 : CHIP_ERROR err = Get(v64);
229 73053 : if (!CanCastTo<uint32_t>(v64))
230 : {
231 1 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
232 : }
233 73052 : v = static_cast<uint32_t>(v64);
234 73052 : return err;
235 : }
236 :
237 1587136 : CHIP_ERROR TLVReader::Get(uint64_t & v) const
238 : {
239 : // Internal callers of this method depend on it not modifying "v" on failure.
240 1587136 : switch (ElementType())
241 : {
242 232120 : case TLVElementType::UInt8:
243 : case TLVElementType::UInt16:
244 : case TLVElementType::UInt32:
245 : case TLVElementType::UInt64:
246 232120 : v = mElemLenOrVal;
247 232120 : break;
248 1355016 : default:
249 1355016 : return CHIP_ERROR_WRONG_TLV_TYPE;
250 : }
251 232120 : return CHIP_NO_ERROR;
252 : }
253 :
254 : namespace {
255 2446 : float BitCastToFloat(const uint64_t elemLenOrVal)
256 : {
257 : float f;
258 2446 : auto unsigned32 = static_cast<uint32_t>(elemLenOrVal);
259 2446 : memcpy(&f, &unsigned32, sizeof(f));
260 2446 : return f;
261 : }
262 : } // namespace
263 :
264 : // Note: Unlike the integer Get functions, this code avoids doing conversions
265 : // between float and double wherever possible, because these conversions are
266 : // relatively expensive on platforms that use soft-float instruction sets.
267 :
268 485 : CHIP_ERROR TLVReader::Get(float & v) const
269 : {
270 485 : switch (ElementType())
271 : {
272 483 : case TLVElementType::FloatingPointNumber32: {
273 483 : v = BitCastToFloat(mElemLenOrVal);
274 483 : break;
275 : }
276 2 : default:
277 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
278 : }
279 483 : return CHIP_NO_ERROR;
280 : }
281 :
282 4031 : CHIP_ERROR TLVReader::Get(double & v) const
283 : {
284 4031 : switch (ElementType())
285 : {
286 1963 : case TLVElementType::FloatingPointNumber32: {
287 1963 : v = BitCastToFloat(mElemLenOrVal);
288 1963 : break;
289 : }
290 2067 : case TLVElementType::FloatingPointNumber64: {
291 : double d;
292 2067 : memcpy(&d, &mElemLenOrVal, sizeof(d));
293 2067 : v = d;
294 2067 : break;
295 : }
296 1 : default:
297 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
298 : }
299 4030 : return CHIP_NO_ERROR;
300 : }
301 :
302 10268 : CHIP_ERROR TLVReader::Get(ByteSpan & v) const
303 : {
304 : const uint8_t * val;
305 10268 : ReturnErrorOnFailure(GetDataPtr(val));
306 10264 : v = ByteSpan(val, GetLength());
307 :
308 10264 : return CHIP_NO_ERROR;
309 : }
310 :
311 : namespace {
312 : constexpr int kUnicodeInformationSeparator1 = 0x1F;
313 : constexpr size_t kMaxLocalizedStringIdentifierLen = 2 * sizeof(LocalizedStringIdentifier);
314 : } // namespace
315 :
316 429 : CHIP_ERROR TLVReader::Get(CharSpan & v) const
317 : {
318 429 : if (!TLVTypeIsUTF8String(ElementType()))
319 : {
320 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
321 : }
322 :
323 : const uint8_t * bytes;
324 427 : ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
325 425 : if (bytes == nullptr)
326 : {
327 : // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
328 98 : return CHIP_NO_ERROR;
329 : }
330 :
331 327 : uint32_t len = GetLength();
332 :
333 : // If Unicode Information Separator 1 (0x1f) is present in the string then method returns
334 : // string ending at first appearance of the Information Separator 1.
335 327 : const uint8_t * infoSeparator = reinterpret_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
336 327 : if (infoSeparator != nullptr)
337 : {
338 5 : len = static_cast<uint32_t>(infoSeparator - bytes);
339 : }
340 :
341 327 : v = CharSpan(Uint8::to_const_char(bytes), len);
342 : #if CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
343 : // Spec requirement: A.11.2. UTF-8 and Octet Strings
344 : //
345 : // For UTF-8 strings, the value octets SHALL encode a valid
346 : // UTF-8 character (code points) sequence.
347 : //
348 : // Senders SHALL NOT include a terminating null character to
349 : // mark the end of a string.
350 :
351 : if (!Utf8::IsValid(v))
352 : {
353 : return CHIP_ERROR_INVALID_UTF8;
354 : }
355 :
356 : if (!v.empty() && (v.back() == 0))
357 : {
358 : return CHIP_ERROR_INVALID_TLV_CHAR_STRING;
359 : }
360 : #endif // CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
361 327 : return CHIP_NO_ERROR;
362 : }
363 :
364 15 : CHIP_ERROR TLVReader::Get(Optional<LocalizedStringIdentifier> & lsid)
365 : {
366 15 : lsid.ClearValue();
367 15 : VerifyOrReturnError(TLVTypeIsUTF8String(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
368 :
369 : const uint8_t * bytes;
370 14 : ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
371 14 : if (bytes == nullptr)
372 : {
373 : // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
374 0 : return CHIP_NO_ERROR;
375 : }
376 :
377 14 : uint32_t len = GetLength();
378 :
379 14 : const uint8_t * infoSeparator1 = static_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
380 14 : if (infoSeparator1 == nullptr)
381 : {
382 1 : return CHIP_NO_ERROR;
383 : }
384 :
385 13 : const uint8_t * lsidPtr = infoSeparator1 + 1;
386 13 : len -= static_cast<uint32_t>(lsidPtr - bytes);
387 :
388 13 : const uint8_t * infoSeparator2 = static_cast<const uint8_t *>(memchr(lsidPtr, kUnicodeInformationSeparator1, len));
389 13 : if (infoSeparator2 != nullptr)
390 : {
391 3 : len = static_cast<uint32_t>(infoSeparator2 - lsidPtr);
392 : }
393 13 : if (len == 0)
394 : {
395 1 : return CHIP_NO_ERROR;
396 : }
397 12 : VerifyOrReturnError(len <= kMaxLocalizedStringIdentifierLen, CHIP_ERROR_INVALID_TLV_ELEMENT);
398 : // Leading zeroes are not allowed.
399 11 : VerifyOrReturnError(static_cast<char>(lsidPtr[0]) != '0', CHIP_ERROR_INVALID_TLV_ELEMENT);
400 :
401 9 : char idStr[kMaxLocalizedStringIdentifierLen] = { '0', '0', '0', '0' };
402 9 : memcpy(&idStr[kMaxLocalizedStringIdentifierLen - len], lsidPtr, len);
403 :
404 : LocalizedStringIdentifier id;
405 9 : VerifyOrReturnError(Encoding::UppercaseHexToUint16(idStr, sizeof(idStr), id) == sizeof(LocalizedStringIdentifier),
406 : CHIP_ERROR_INVALID_TLV_ELEMENT);
407 :
408 8 : lsid.SetValue(id);
409 8 : return CHIP_NO_ERROR;
410 : }
411 :
412 7861 : CHIP_ERROR TLVReader::GetBytes(uint8_t * buf, size_t bufSize)
413 : {
414 7861 : if (!TLVTypeIsString(ElementType()))
415 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
416 :
417 7859 : if (mElemLenOrVal > bufSize)
418 0 : return CHIP_ERROR_BUFFER_TOO_SMALL;
419 :
420 7859 : CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
421 7859 : if (err != CHIP_NO_ERROR)
422 0 : return err;
423 :
424 7859 : mElemLenOrVal = 0;
425 :
426 7859 : return CHIP_NO_ERROR;
427 : }
428 :
429 3039 : CHIP_ERROR TLVReader::GetString(char * buf, size_t bufSize)
430 : {
431 3039 : if (!TLVTypeIsString(ElementType()))
432 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
433 :
434 3038 : if ((mElemLenOrVal + 1) > bufSize)
435 1 : return CHIP_ERROR_BUFFER_TOO_SMALL;
436 :
437 3037 : buf[mElemLenOrVal] = 0;
438 :
439 3037 : return GetBytes(reinterpret_cast<uint8_t *>(buf), bufSize - 1);
440 : }
441 :
442 1 : CHIP_ERROR TLVReader::DupBytes(uint8_t *& buf, uint32_t & dataLen)
443 : {
444 1 : if (!TLVTypeIsString(ElementType()))
445 0 : return CHIP_ERROR_WRONG_TLV_TYPE;
446 :
447 1 : buf = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal)));
448 1 : if (buf == nullptr)
449 0 : return CHIP_ERROR_NO_MEMORY;
450 :
451 1 : CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
452 1 : if (err != CHIP_NO_ERROR)
453 : {
454 0 : chip::Platform::MemoryFree(buf);
455 0 : buf = nullptr;
456 0 : return err;
457 : }
458 :
459 1 : dataLen = static_cast<uint32_t>(mElemLenOrVal);
460 1 : mElemLenOrVal = 0;
461 :
462 1 : return CHIP_NO_ERROR;
463 : }
464 :
465 2 : CHIP_ERROR TLVReader::DupString(char *& buf)
466 : {
467 2 : if (!TLVTypeIsString(ElementType()))
468 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
469 :
470 1 : if (mElemLenOrVal > UINT32_MAX - 1)
471 0 : return CHIP_ERROR_NO_MEMORY;
472 :
473 1 : buf = static_cast<char *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal + 1)));
474 1 : if (buf == nullptr)
475 0 : return CHIP_ERROR_NO_MEMORY;
476 :
477 1 : CHIP_ERROR err = ReadData(reinterpret_cast<uint8_t *>(buf), static_cast<uint32_t>(mElemLenOrVal));
478 1 : if (err != CHIP_NO_ERROR)
479 : {
480 0 : chip::Platform::MemoryFree(buf);
481 0 : buf = nullptr;
482 0 : return err;
483 : }
484 :
485 1 : buf[mElemLenOrVal] = 0;
486 1 : mElemLenOrVal = 0;
487 :
488 1 : return err;
489 : }
490 :
491 20918 : CHIP_ERROR TLVReader::GetDataPtr(const uint8_t *& data) const
492 : {
493 20918 : VerifyOrReturnError(TLVTypeIsString(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
494 :
495 20915 : if (GetLength() == 0)
496 : {
497 3794 : data = nullptr;
498 3794 : return CHIP_NO_ERROR;
499 : }
500 :
501 17121 : uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
502 :
503 : // Verify that the entirety of the data is available in the buffer.
504 : // Note that this may not be possible if the reader is reading from a chain of buffers.
505 17121 : VerifyOrReturnError(remainingLen >= static_cast<uint32_t>(mElemLenOrVal), CHIP_ERROR_TLV_UNDERRUN);
506 17117 : data = mReadPoint;
507 17117 : return CHIP_NO_ERROR;
508 : }
509 :
510 1639 : CHIP_ERROR TLVReader::OpenContainer(TLVReader & containerReader)
511 : {
512 1639 : TLVElementType elemType = ElementType();
513 1639 : if (!TLVTypeIsContainer(elemType))
514 1 : return CHIP_ERROR_INCORRECT_STATE;
515 :
516 1638 : containerReader.mBackingStore = mBackingStore;
517 1638 : containerReader.mReadPoint = mReadPoint;
518 1638 : containerReader.mBufEnd = mBufEnd;
519 1638 : containerReader.mLenRead = mLenRead;
520 1638 : containerReader.mMaxLen = mMaxLen;
521 1638 : containerReader.ClearElementState();
522 1638 : containerReader.mContainerType = static_cast<TLVType>(elemType);
523 1638 : containerReader.SetContainerOpen(false);
524 1638 : containerReader.ImplicitProfileId = ImplicitProfileId;
525 1638 : containerReader.AppData = AppData;
526 :
527 1638 : SetContainerOpen(true);
528 :
529 1638 : return CHIP_NO_ERROR;
530 : }
531 :
532 1566 : CHIP_ERROR TLVReader::CloseContainer(TLVReader & containerReader)
533 : {
534 : CHIP_ERROR err;
535 :
536 1566 : if (!IsContainerOpen())
537 1 : return CHIP_ERROR_INCORRECT_STATE;
538 :
539 1565 : if (static_cast<TLVElementType>(containerReader.mContainerType) != ElementType())
540 0 : return CHIP_ERROR_INCORRECT_STATE;
541 :
542 1565 : err = containerReader.SkipToEndOfContainer();
543 1565 : if (err != CHIP_NO_ERROR)
544 0 : return err;
545 :
546 1565 : mBackingStore = containerReader.mBackingStore;
547 1565 : mReadPoint = containerReader.mReadPoint;
548 1565 : mBufEnd = containerReader.mBufEnd;
549 1565 : mLenRead = containerReader.mLenRead;
550 1565 : mMaxLen = containerReader.mMaxLen;
551 1565 : ClearElementState();
552 :
553 1565 : return CHIP_NO_ERROR;
554 : }
555 :
556 3098058 : CHIP_ERROR TLVReader::EnterContainer(TLVType & outerContainerType)
557 : {
558 3098058 : TLVElementType elemType = ElementType();
559 3098058 : if (!TLVTypeIsContainer(elemType))
560 1 : return CHIP_ERROR_INCORRECT_STATE;
561 :
562 3098057 : outerContainerType = mContainerType;
563 3098057 : mContainerType = static_cast<TLVType>(elemType);
564 :
565 3098057 : ClearElementState();
566 3098057 : SetContainerOpen(false);
567 :
568 3098057 : return CHIP_NO_ERROR;
569 : }
570 :
571 327958 : CHIP_ERROR TLVReader::ExitContainer(TLVType outerContainerType)
572 : {
573 : CHIP_ERROR err;
574 :
575 327958 : err = SkipToEndOfContainer();
576 327958 : if (err != CHIP_NO_ERROR)
577 26 : return err;
578 :
579 327932 : mContainerType = outerContainerType;
580 327932 : ClearElementState();
581 :
582 327932 : return CHIP_NO_ERROR;
583 : }
584 :
585 5879 : CHIP_ERROR TLVReader::VerifyEndOfContainer()
586 : {
587 5879 : CHIP_ERROR err = Next();
588 5879 : if (err == CHIP_END_OF_TLV)
589 5878 : return CHIP_NO_ERROR;
590 1 : if (err == CHIP_NO_ERROR)
591 0 : return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
592 1 : return err;
593 : }
594 :
595 7912499 : CHIP_ERROR TLVReader::Next()
596 : {
597 7912499 : ReturnErrorOnFailure(Skip());
598 7909945 : ReturnErrorOnFailure(ReadElement());
599 :
600 7889489 : TLVElementType elemType = ElementType();
601 :
602 7889489 : VerifyOrReturnError(elemType != TLVElementType::EndOfContainer, CHIP_END_OF_TLV);
603 :
604 : // Ensure that GetDataPtr calls can be called immediately after Next, so
605 : // that `Get(ByteSpan&)` does not need to advance buffers and just works
606 7721066 : if (TLVTypeIsString(elemType) && (GetLength() != 0))
607 : {
608 28066 : ReturnErrorOnFailure(EnsureData(CHIP_ERROR_TLV_UNDERRUN));
609 : }
610 :
611 7721066 : return CHIP_NO_ERROR;
612 : }
613 :
614 79340 : CHIP_ERROR TLVReader::Expect(Tag expectedTag)
615 : {
616 79340 : VerifyOrReturnError(GetType() != kTLVType_NotSpecified, CHIP_ERROR_WRONG_TLV_TYPE);
617 79336 : VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
618 79298 : return CHIP_NO_ERROR;
619 : }
620 :
621 78750 : CHIP_ERROR TLVReader::Next(Tag expectedTag)
622 : {
623 78750 : ReturnErrorOnFailure(Next());
624 76776 : ReturnErrorOnFailure(Expect(expectedTag));
625 76741 : return CHIP_NO_ERROR;
626 : }
627 :
628 6982215 : CHIP_ERROR TLVReader::Expect(TLVType expectedType, Tag expectedTag)
629 : {
630 6982215 : VerifyOrReturnError(GetType() == expectedType, CHIP_ERROR_WRONG_TLV_TYPE);
631 6974000 : VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
632 6917074 : return CHIP_NO_ERROR;
633 : }
634 :
635 6978214 : CHIP_ERROR TLVReader::Next(TLVType expectedType, Tag expectedTag)
636 : {
637 6978214 : ReturnErrorOnFailure(Next());
638 6966899 : ReturnErrorOnFailure(Expect(expectedType, expectedTag));
639 6902729 : return CHIP_NO_ERROR;
640 : }
641 :
642 7939175 : CHIP_ERROR TLVReader::Skip()
643 : {
644 : CHIP_ERROR err;
645 7939175 : TLVElementType elemType = ElementType();
646 :
647 7939175 : if (elemType == TLVElementType::EndOfContainer)
648 2552 : return CHIP_END_OF_TLV;
649 :
650 7936623 : if (TLVTypeIsContainer(elemType))
651 : {
652 : TLVType outerContainerType;
653 180148 : err = EnterContainer(outerContainerType);
654 180148 : if (err != CHIP_NO_ERROR)
655 4 : return err;
656 180148 : err = ExitContainer(outerContainerType);
657 180148 : if (err != CHIP_NO_ERROR)
658 4 : return err;
659 : }
660 :
661 : else
662 : {
663 7756475 : err = SkipData();
664 7756475 : if (err != CHIP_NO_ERROR)
665 0 : return err;
666 :
667 7756475 : ClearElementState();
668 : }
669 :
670 7936619 : return CHIP_NO_ERROR;
671 : }
672 :
673 : /**
674 : * Clear the state of the TLVReader.
675 : * This method is used to position the reader before the first TLV,
676 : * between TLVs or after the last TLV.
677 : */
678 12651433 : void TLVReader::ClearElementState()
679 : {
680 12651433 : mElemTag = AnonymousTag();
681 12651433 : mControlByte = kTLVControlByte_NotSpecified;
682 12651433 : mElemLenOrVal = 0;
683 12651433 : }
684 :
685 : /**
686 : * Skip any data contained in the current TLV by reading over it without
687 : * a destination buffer.
688 : *
689 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the end of the
690 : * data.
691 : * @retval other Other CHIP or platform error codes returned by the configured
692 : * TLVBackingStore.
693 : */
694 10343952 : CHIP_ERROR TLVReader::SkipData()
695 : {
696 10343952 : CHIP_ERROR err = CHIP_NO_ERROR;
697 10343952 : TLVElementType elemType = ElementType();
698 :
699 10343952 : if (TLVTypeHasLength(elemType))
700 : {
701 212035 : err = ReadData(nullptr, static_cast<uint32_t>(mElemLenOrVal));
702 212035 : if (err != CHIP_NO_ERROR)
703 0 : return err;
704 : }
705 :
706 10343952 : return err;
707 : }
708 :
709 329523 : CHIP_ERROR TLVReader::SkipToEndOfContainer()
710 : {
711 : CHIP_ERROR err;
712 329523 : TLVType outerContainerType = mContainerType;
713 329523 : uint32_t nestLevel = 0;
714 :
715 : // If the user calls Next() after having called OpenContainer() but before calling
716 : // CloseContainer() they're effectively doing a close container by skipping over
717 : // the container element. So reset the 'container open' flag here to prevent them
718 : // from calling CloseContainer() with the now orphaned container reader.
719 329523 : SetContainerOpen(false);
720 :
721 : while (true)
722 : {
723 2916974 : TLVElementType elemType = ElementType();
724 :
725 2916974 : if (elemType == TLVElementType::EndOfContainer)
726 : {
727 807715 : if (nestLevel == 0)
728 329497 : return CHIP_NO_ERROR;
729 :
730 478218 : nestLevel--;
731 478218 : mContainerType = (nestLevel == 0) ? outerContainerType : kTLVType_UnknownContainer;
732 : }
733 :
734 2109259 : else if (TLVTypeIsContainer(elemType))
735 : {
736 478219 : nestLevel++;
737 478219 : mContainerType = static_cast<TLVType>(elemType);
738 : }
739 :
740 2587477 : err = SkipData();
741 2587477 : if (err != CHIP_NO_ERROR)
742 0 : return err;
743 :
744 2587477 : err = ReadElement();
745 2587477 : if (err != CHIP_NO_ERROR)
746 26 : return err;
747 2587451 : }
748 : }
749 :
750 10497422 : CHIP_ERROR TLVReader::ReadElement()
751 : {
752 : CHIP_ERROR err;
753 : uint8_t stagingBuf[17]; // 17 = 1 control byte + 8 tag bytes + 8 length/value bytes
754 : const uint8_t * p;
755 : TLVElementType elemType;
756 :
757 : // Make sure we have input data. Return CHIP_END_OF_TLV if no more data is available.
758 10497422 : err = EnsureData(CHIP_END_OF_TLV);
759 10497422 : if (err != CHIP_NO_ERROR)
760 9592 : return err;
761 :
762 10487830 : if (mReadPoint == nullptr)
763 : {
764 0 : return CHIP_ERROR_INVALID_TLV_ELEMENT;
765 : }
766 : // Get the element's control byte.
767 10487830 : mControlByte = *mReadPoint;
768 :
769 : // Extract the element type from the control byte. Fail if it's invalid.
770 10487830 : elemType = ElementType();
771 10487830 : if (!IsValidTLVType(elemType))
772 4101 : return CHIP_ERROR_INVALID_TLV_ELEMENT;
773 :
774 : // Extract the tag control from the control byte.
775 10483729 : TLVTagControl tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
776 :
777 : // Determine the number of bytes in the element's tag, if any.
778 10483729 : uint8_t tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
779 :
780 : // Extract the size of length/value field from the control byte.
781 10483729 : TLVFieldSize lenOrValFieldSize = GetTLVFieldSize(elemType);
782 :
783 : // Determine the number of bytes in the length/value field.
784 10483729 : uint8_t valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
785 :
786 : // Determine the number of bytes in the element's 'head'. This includes: the control byte, the tag bytes (if present), the
787 : // length bytes (if present), and for elements that don't have a length (e.g. integers), the value bytes.
788 10483729 : uint8_t elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
789 :
790 : // If the head of the element overlaps the end of the input buffer, read the bytes into the staging buffer
791 : // and arrange to parse them from there. Otherwise read them directly from the input buffer.
792 10483729 : if (elemHeadBytes > (mBufEnd - mReadPoint))
793 : {
794 137 : err = ReadData(stagingBuf, elemHeadBytes);
795 137 : if (err != CHIP_NO_ERROR)
796 0 : return err;
797 137 : p = stagingBuf;
798 : }
799 : else
800 : {
801 10483592 : p = mReadPoint;
802 10483592 : mReadPoint += elemHeadBytes;
803 10483592 : mLenRead += elemHeadBytes;
804 : }
805 :
806 : // Skip over the control byte.
807 10483729 : p++;
808 :
809 : // Read the tag field, if present.
810 10483729 : mElemTag = ReadTag(tagControl, p);
811 :
812 : // Read the length/value field, if present.
813 10483729 : switch (lenOrValFieldSize)
814 : {
815 7362303 : case kTLVFieldSize_0Byte:
816 7362303 : mElemLenOrVal = 0;
817 7362303 : break;
818 2579685 : case kTLVFieldSize_1Byte:
819 2579685 : mElemLenOrVal = Read8(p);
820 2579685 : break;
821 114717 : case kTLVFieldSize_2Byte:
822 114717 : mElemLenOrVal = LittleEndian::Read16(p);
823 114717 : break;
824 335675 : case kTLVFieldSize_4Byte:
825 335675 : mElemLenOrVal = LittleEndian::Read32(p);
826 335675 : break;
827 91349 : case kTLVFieldSize_8Byte:
828 91349 : mElemLenOrVal = LittleEndian::Read64(p);
829 91349 : VerifyOrReturnError(!TLVTypeHasLength(elemType) || (mElemLenOrVal <= UINT32_MAX), CHIP_ERROR_NOT_IMPLEMENTED);
830 90203 : break;
831 : }
832 :
833 10482583 : return VerifyElement();
834 : }
835 :
836 10482583 : CHIP_ERROR TLVReader::VerifyElement()
837 : {
838 10482583 : if (ElementType() == TLVElementType::EndOfContainer)
839 : {
840 853167 : if (mContainerType == kTLVType_NotSpecified)
841 138 : return CHIP_ERROR_INVALID_TLV_ELEMENT;
842 853029 : if (mElemTag != AnonymousTag())
843 418 : return CHIP_ERROR_INVALID_TLV_TAG;
844 : }
845 : else
846 : {
847 9629416 : if (mElemTag == UnknownImplicitTag())
848 0 : return CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG;
849 9629416 : switch (mContainerType)
850 : {
851 1465531 : case kTLVType_NotSpecified:
852 1465531 : if (IsContextTag(mElemTag))
853 324 : return CHIP_ERROR_INVALID_TLV_TAG;
854 1465207 : break;
855 5556735 : case kTLVType_Structure:
856 5556735 : if (mElemTag == AnonymousTag())
857 1016 : return CHIP_ERROR_INVALID_TLV_TAG;
858 5555719 : break;
859 1632853 : case kTLVType_Array:
860 1632853 : if (mElemTag != AnonymousTag())
861 2249 : return CHIP_ERROR_INVALID_TLV_TAG;
862 1630604 : break;
863 974297 : case kTLVType_UnknownContainer:
864 : case kTLVType_List:
865 974297 : break;
866 0 : default:
867 0 : return CHIP_ERROR_INCORRECT_STATE;
868 : }
869 : }
870 :
871 : // If the current element encodes a specific length (e.g. a UTF8 string or a byte string), verify
872 : // that the purported length fits within the remaining bytes of the encoding (as delineated by mMaxLen).
873 : //
874 : // Note that this check is not strictly necessary to prevent runtime errors, as any attempt to access
875 : // the data of an element with an invalid length will result in an error. However checking the length
876 : // here catches the error earlier, and ensures that the application will never see the erroneous length
877 : // value.
878 : //
879 10478438 : if (TLVTypeHasLength(ElementType()))
880 : {
881 216870 : uint32_t overallLenRemaining = mMaxLen - mLenRead;
882 216870 : if (overallLenRemaining < static_cast<uint32_t>(mElemLenOrVal))
883 1498 : return CHIP_ERROR_TLV_UNDERRUN;
884 : }
885 :
886 10476940 : return CHIP_NO_ERROR;
887 : }
888 :
889 10483729 : Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) const
890 : {
891 : uint16_t vendorId;
892 : uint16_t profileNum;
893 :
894 10483729 : switch (tagControl)
895 : {
896 3732195 : case TLVTagControl::ContextSpecific:
897 3732195 : return ContextTag(Read8(p));
898 1853 : case TLVTagControl::CommonProfile_2Bytes:
899 1853 : return CommonTag(LittleEndian::Read16(p));
900 2246 : case TLVTagControl::CommonProfile_4Bytes:
901 2246 : return CommonTag(LittleEndian::Read32(p));
902 1378278 : case TLVTagControl::ImplicitProfile_2Bytes:
903 1378278 : if (ImplicitProfileId == kProfileIdNotSpecified)
904 0 : return UnknownImplicitTag();
905 1378278 : return ProfileTag(ImplicitProfileId, LittleEndian::Read16(p));
906 3050 : case TLVTagControl::ImplicitProfile_4Bytes:
907 3050 : if (ImplicitProfileId == kProfileIdNotSpecified)
908 0 : return UnknownImplicitTag();
909 3050 : return ProfileTag(ImplicitProfileId, LittleEndian::Read32(p));
910 2833812 : case TLVTagControl::FullyQualified_6Bytes:
911 2833812 : vendorId = LittleEndian::Read16(p);
912 2833812 : profileNum = LittleEndian::Read16(p);
913 2833812 : return ProfileTag(vendorId, profileNum, LittleEndian::Read16(p));
914 1898 : case TLVTagControl::FullyQualified_8Bytes:
915 1898 : vendorId = LittleEndian::Read16(p);
916 1898 : profileNum = LittleEndian::Read16(p);
917 1898 : return ProfileTag(vendorId, profileNum, LittleEndian::Read32(p));
918 2530397 : case TLVTagControl::Anonymous:
919 : default:
920 2530397 : return AnonymousTag();
921 : }
922 : }
923 :
924 241188 : CHIP_ERROR TLVReader::ReadData(uint8_t * buf, uint32_t len)
925 : {
926 : CHIP_ERROR err;
927 :
928 305833 : while (len > 0)
929 : {
930 64645 : err = EnsureData(CHIP_ERROR_TLV_UNDERRUN);
931 64645 : if (err != CHIP_NO_ERROR)
932 0 : return err;
933 :
934 64645 : uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
935 :
936 64645 : uint32_t readLen = len;
937 64645 : if (readLen > remainingLen)
938 156 : readLen = remainingLen;
939 :
940 64645 : if (buf != nullptr)
941 : {
942 24956 : memcpy(buf, mReadPoint, readLen);
943 24956 : buf += readLen;
944 : }
945 64645 : mReadPoint += readLen;
946 64645 : mLenRead += readLen;
947 64645 : len -= readLen;
948 : }
949 :
950 241188 : return CHIP_NO_ERROR;
951 : }
952 :
953 10590133 : CHIP_ERROR TLVReader::EnsureData(CHIP_ERROR noDataErr)
954 : {
955 : CHIP_ERROR err;
956 :
957 10590133 : if (mReadPoint == mBufEnd)
958 : {
959 9878 : if (mLenRead == mMaxLen)
960 9592 : return noDataErr;
961 :
962 286 : if (mBackingStore == nullptr)
963 0 : return noDataErr;
964 :
965 : uint32_t bufLen;
966 286 : err = mBackingStore->GetNextBuffer(*this, mReadPoint, bufLen);
967 286 : if (err != CHIP_NO_ERROR)
968 0 : return err;
969 286 : if (bufLen == 0)
970 0 : return noDataErr;
971 :
972 : // Cap mBufEnd so that we don't read beyond the user's specified maximum length, even
973 : // if the underlying buffer is larger.
974 286 : uint32_t overallLenRemaining = mMaxLen - mLenRead;
975 286 : if (overallLenRemaining < bufLen)
976 0 : bufLen = overallLenRemaining;
977 :
978 286 : mBufEnd = mReadPoint + bufLen;
979 : }
980 :
981 10580541 : return CHIP_NO_ERROR;
982 : }
983 :
984 : /**
985 : * This is a private method used to compute the length of a TLV element head.
986 : */
987 2 : CHIP_ERROR TLVReader::GetElementHeadLength(uint8_t & elemHeadBytes) const
988 : {
989 : uint8_t tagBytes;
990 : uint8_t valOrLenBytes;
991 : TLVTagControl tagControl;
992 : TLVFieldSize lenOrValFieldSize;
993 2 : TLVElementType elemType = ElementType();
994 :
995 : // Verify element is of valid TLVType.
996 2 : VerifyOrReturnError(IsValidTLVType(elemType), CHIP_ERROR_INVALID_TLV_ELEMENT);
997 :
998 : // Extract the tag control from the control byte.
999 2 : tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
1000 :
1001 : // Determine the number of bytes in the element's tag, if any.
1002 2 : tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
1003 :
1004 : // Extract the size of length/value field from the control byte.
1005 2 : lenOrValFieldSize = GetTLVFieldSize(elemType);
1006 :
1007 : // Determine the number of bytes in the length/value field.
1008 2 : valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
1009 :
1010 : // Determine the number of bytes in the element's 'head'. This includes: the
1011 : // control byte, the tag bytes (if present), the length bytes (if present),
1012 : // and for elements that don't have a length (e.g. integers), the value
1013 : // bytes.
1014 2 : VerifyOrReturnError(CanCastTo<uint8_t>(1 + tagBytes + valOrLenBytes), CHIP_ERROR_INTERNAL);
1015 2 : elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
1016 :
1017 2 : return CHIP_NO_ERROR;
1018 : }
1019 :
1020 : /**
1021 : * This is a private method that returns the TLVElementType from mControlByte
1022 : */
1023 81385675 : TLVElementType TLVReader::ElementType() const
1024 : {
1025 81385675 : if (mControlByte == static_cast<uint16_t>(kTLVControlByte_NotSpecified))
1026 9556020 : return TLVElementType::NotSpecified;
1027 71829655 : return static_cast<TLVElementType>(mControlByte & kTLVTypeMask);
1028 : }
1029 :
1030 133345 : CHIP_ERROR TLVReader::FindElementWithTag(Tag tag, TLVReader & destReader) const
1031 : {
1032 133345 : CHIP_ERROR err = CHIP_NO_ERROR;
1033 :
1034 : chip::TLV::TLVReader reader;
1035 133345 : reader.Init(*this);
1036 :
1037 323720 : while (CHIP_NO_ERROR == (err = reader.Next()))
1038 : {
1039 298398 : VerifyOrExit(chip::TLV::kTLVType_NotSpecified != reader.GetType(), err = CHIP_ERROR_INVALID_TLV_ELEMENT);
1040 :
1041 298398 : if (tag == reader.GetTag())
1042 : {
1043 108023 : destReader.Init(reader);
1044 108023 : break;
1045 : }
1046 : }
1047 :
1048 25322 : exit:
1049 133345 : ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
1050 :
1051 133345 : return err;
1052 : }
1053 :
1054 1352 : CHIP_ERROR TLVReader::CountRemainingInContainer(size_t * size) const
1055 : {
1056 1352 : if (mContainerType == kTLVType_NotSpecified)
1057 : {
1058 0 : return CHIP_ERROR_INCORRECT_STATE;
1059 : }
1060 :
1061 1352 : TLVReader tempReader(*this);
1062 1352 : size_t count = 0;
1063 : CHIP_ERROR err;
1064 4102 : while ((err = tempReader.Next()) == CHIP_NO_ERROR)
1065 : {
1066 2750 : ++count;
1067 : };
1068 1352 : if (err == CHIP_END_OF_TLV)
1069 : {
1070 1352 : *size = count;
1071 1352 : return CHIP_NO_ERROR;
1072 : }
1073 0 : return err;
1074 : }
1075 :
1076 10 : CHIP_ERROR ContiguousBufferTLVReader::OpenContainer(ContiguousBufferTLVReader & containerReader)
1077 : {
1078 : // We are going to initialize containerReader by calling our superclass
1079 : // OpenContainer method. The superclass only knows how to initialize
1080 : // members the superclass knows about, so we assert that we don't have any
1081 : // extra members that need initializing. If such members ever get added,
1082 : // they would need to be initialized in this method.
1083 : static_assert(sizeof(ContiguousBufferTLVReader) == sizeof(TLVReader), "We have state the superclass is not initializing?");
1084 10 : return TLVReader::OpenContainer(containerReader);
1085 : }
1086 :
1087 11 : CHIP_ERROR ContiguousBufferTLVReader::GetStringView(Span<const char> & data)
1088 : {
1089 11 : return Get(data);
1090 : }
1091 :
1092 301 : CHIP_ERROR ContiguousBufferTLVReader::GetByteView(ByteSpan & data)
1093 : {
1094 301 : if (!TLVTypeIsByteString(ElementType()))
1095 : {
1096 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
1097 : }
1098 :
1099 299 : return Get(data);
1100 : }
1101 :
1102 : } // namespace TLV
1103 : } // namespace chip
|