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 2541943 : TLVReader::TLVReader() :
53 2541943 : ImplicitProfileId(kProfileIdNotSpecified), AppData(nullptr), mElemLenOrVal(0), mBackingStore(nullptr), mReadPoint(nullptr),
54 2541943 : mBufEnd(nullptr), mLenRead(0), mMaxLen(0), mContainerType(kTLVType_NotSpecified), mControlByte(kTLVControlByte_NotSpecified),
55 2541943 : mContainerOpen(false)
56 2541943 : {}
57 :
58 1699587 : void TLVReader::Init(const uint8_t * data, size_t dataLen)
59 : {
60 : // TODO: Maybe we can just make mMaxLen and mLenRead size_t instead?
61 1699587 : uint32_t actualDataLen = dataLen > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(dataLen);
62 1699587 : mBackingStore = nullptr;
63 1699587 : mReadPoint = data;
64 1699587 : mBufEnd = data + actualDataLen;
65 1699587 : mLenRead = 0;
66 1699587 : mMaxLen = actualDataLen;
67 1699587 : ClearElementState();
68 1699587 : mContainerType = kTLVType_NotSpecified;
69 1699587 : SetContainerOpen(false);
70 :
71 1699587 : ImplicitProfileId = kProfileIdNotSpecified;
72 1699587 : }
73 :
74 4153 : CHIP_ERROR TLVReader::Init(TLVBackingStore & backingStore, uint32_t maxLen)
75 : {
76 4153 : mBackingStore = &backingStore;
77 4153 : mReadPoint = nullptr;
78 4153 : uint32_t bufLen = 0;
79 4153 : CHIP_ERROR err = mBackingStore->OnInit(*this, mReadPoint, bufLen);
80 8306 : if (err != CHIP_NO_ERROR)
81 0 : return err;
82 :
83 4153 : mBufEnd = mReadPoint + bufLen;
84 4153 : mLenRead = 0;
85 4153 : mMaxLen = maxLen;
86 4153 : ClearElementState();
87 4153 : mContainerType = kTLVType_NotSpecified;
88 4153 : SetContainerOpen(false);
89 :
90 4153 : ImplicitProfileId = kProfileIdNotSpecified;
91 4153 : AppData = nullptr;
92 4153 : return CHIP_NO_ERROR;
93 : }
94 :
95 792948 : void TLVReader::Init(const TLVReader & aReader)
96 : {
97 : // Initialize private data members
98 :
99 792948 : mElemTag = aReader.mElemTag;
100 792948 : mElemLenOrVal = aReader.mElemLenOrVal;
101 792948 : mBackingStore = aReader.mBackingStore;
102 792948 : mReadPoint = aReader.mReadPoint;
103 792948 : mBufEnd = aReader.mBufEnd;
104 792948 : mLenRead = aReader.mLenRead;
105 792948 : mMaxLen = aReader.mMaxLen;
106 792948 : mControlByte = aReader.mControlByte;
107 792948 : mContainerType = aReader.mContainerType;
108 792948 : SetContainerOpen(aReader.IsContainerOpen());
109 :
110 : // Initialize public data members
111 :
112 792948 : ImplicitProfileId = aReader.ImplicitProfileId;
113 792948 : AppData = aReader.AppData;
114 792948 : }
115 :
116 9334278 : TLVType TLVReader::GetType() const
117 : {
118 9334278 : TLVElementType elemType = ElementType();
119 9334278 : if (elemType == TLVElementType::EndOfContainer)
120 4 : return kTLVType_NotSpecified;
121 9334274 : if (elemType == TLVElementType::FloatingPointNumber32 || elemType == TLVElementType::FloatingPointNumber64)
122 12062 : return kTLVType_FloatingPointNumber;
123 9322212 : if (elemType == TLVElementType::NotSpecified || elemType >= TLVElementType::Null)
124 3756926 : return static_cast<TLVType>(elemType);
125 5565286 : return static_cast<TLVType>(static_cast<uint8_t>(elemType) & ~kTLVTypeSizeMask);
126 : }
127 :
128 159736 : uint32_t TLVReader::GetLength() const
129 : {
130 159736 : if (TLVTypeHasLength(ElementType()))
131 146663 : return static_cast<uint32_t>(mElemLenOrVal);
132 13073 : return 0;
133 : }
134 :
135 3075948 : CHIP_ERROR TLVReader::Get(bool & v) const
136 : {
137 3075948 : TLVElementType elemType = ElementType();
138 3075948 : if (elemType == TLVElementType::BooleanFalse)
139 1531421 : v = false;
140 1544527 : else if (elemType == TLVElementType::BooleanTrue)
141 1544526 : v = true;
142 : else
143 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
144 3075947 : return CHIP_NO_ERROR;
145 : }
146 :
147 1495990 : CHIP_ERROR TLVReader::Get(int8_t & v) const
148 : {
149 1495990 : int64_t v64 = 0;
150 1495990 : CHIP_ERROR err = Get(v64);
151 1495990 : if (!CanCastTo<int8_t>(v64))
152 : {
153 47 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
154 : }
155 1495943 : v = static_cast<int8_t>(v64);
156 1495943 : return err;
157 : }
158 :
159 1491875 : CHIP_ERROR TLVReader::Get(int16_t & v) const
160 : {
161 1491875 : int64_t v64 = 0;
162 1491875 : CHIP_ERROR err = Get(v64);
163 1491875 : if (!CanCastTo<int16_t>(v64))
164 : {
165 4 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
166 : }
167 1491871 : v = static_cast<int16_t>(v64);
168 1491871 : return err;
169 : }
170 :
171 1492215 : CHIP_ERROR TLVReader::Get(int32_t & v) const
172 : {
173 1492215 : int64_t v64 = 0;
174 1492215 : CHIP_ERROR err = Get(v64);
175 1492215 : if (!CanCastTo<int32_t>(v64))
176 : {
177 2 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
178 : }
179 1492213 : v = static_cast<int32_t>(v64);
180 1492213 : return err;
181 : }
182 :
183 5973061 : CHIP_ERROR TLVReader::Get(int64_t & v) const
184 : {
185 : // Internal callers of this method depend on it not modifying "v" on failure.
186 5973061 : switch (ElementType())
187 : {
188 5971549 : case TLVElementType::Int8:
189 5971549 : v = CastToSigned(static_cast<uint8_t>(mElemLenOrVal));
190 5971549 : break;
191 193 : case TLVElementType::Int16:
192 193 : v = CastToSigned(static_cast<uint16_t>(mElemLenOrVal));
193 193 : break;
194 839 : case TLVElementType::Int32:
195 839 : v = CastToSigned(static_cast<uint32_t>(mElemLenOrVal));
196 839 : break;
197 79 : case TLVElementType::Int64:
198 79 : v = CastToSigned(mElemLenOrVal);
199 79 : break;
200 401 : default:
201 401 : return CHIP_ERROR_WRONG_TLV_TYPE;
202 : }
203 :
204 5972660 : return CHIP_NO_ERROR;
205 : }
206 :
207 1568415 : CHIP_ERROR TLVReader::Get(uint8_t & v) const
208 : {
209 1568415 : uint64_t v64 = 0;
210 1568415 : CHIP_ERROR err = Get(v64);
211 1568415 : if (!CanCastTo<uint8_t>(v64))
212 : {
213 3 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
214 : }
215 1568412 : v = static_cast<uint8_t>(v64);
216 1568412 : return err;
217 : }
218 :
219 293601 : CHIP_ERROR TLVReader::Get(uint16_t & v) const
220 : {
221 293601 : uint64_t v64 = 0;
222 293601 : CHIP_ERROR err = Get(v64);
223 293601 : if (!CanCastTo<uint16_t>(v64))
224 : {
225 6 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
226 : }
227 293595 : v = static_cast<uint16_t>(v64);
228 293595 : return err;
229 : }
230 :
231 121365 : CHIP_ERROR TLVReader::Get(uint32_t & v) const
232 : {
233 121365 : uint64_t v64 = 0;
234 121365 : CHIP_ERROR err = Get(v64);
235 121365 : if (!CanCastTo<uint32_t>(v64))
236 : {
237 1 : return CHIP_ERROR_INVALID_INTEGER_VALUE;
238 : }
239 121364 : v = static_cast<uint32_t>(v64);
240 121364 : return err;
241 : }
242 :
243 2043574 : CHIP_ERROR TLVReader::Get(uint64_t & v) const
244 : {
245 : // Internal callers of this method depend on it not modifying "v" on failure.
246 2043574 : switch (ElementType())
247 : {
248 550612 : case TLVElementType::UInt8:
249 : case TLVElementType::UInt16:
250 : case TLVElementType::UInt32:
251 : case TLVElementType::UInt64:
252 550612 : v = mElemLenOrVal;
253 550612 : break;
254 1492962 : default:
255 1492962 : return CHIP_ERROR_WRONG_TLV_TYPE;
256 : }
257 550612 : return CHIP_NO_ERROR;
258 : }
259 :
260 : namespace {
261 2565 : float BitCastToFloat(const uint64_t elemLenOrVal)
262 : {
263 : float f;
264 2565 : auto unsigned32 = static_cast<uint32_t>(elemLenOrVal);
265 2565 : memcpy(&f, &unsigned32, sizeof(f));
266 2565 : return f;
267 : }
268 : } // namespace
269 :
270 : // Note: Unlike the integer Get functions, this code avoids doing conversions
271 : // between float and double wherever possible, because these conversions are
272 : // relatively expensive on platforms that use soft-float instruction sets.
273 :
274 527 : CHIP_ERROR TLVReader::Get(float & v) const
275 : {
276 527 : switch (ElementType())
277 : {
278 525 : case TLVElementType::FloatingPointNumber32: {
279 525 : v = BitCastToFloat(mElemLenOrVal);
280 525 : break;
281 : }
282 2 : default:
283 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
284 : }
285 525 : return CHIP_NO_ERROR;
286 : }
287 :
288 4228 : CHIP_ERROR TLVReader::Get(double & v) const
289 : {
290 4228 : switch (ElementType())
291 : {
292 2040 : case TLVElementType::FloatingPointNumber32: {
293 2040 : v = BitCastToFloat(mElemLenOrVal);
294 2040 : break;
295 : }
296 2187 : case TLVElementType::FloatingPointNumber64: {
297 : double d;
298 2187 : memcpy(&d, &mElemLenOrVal, sizeof(d));
299 2187 : v = d;
300 2187 : break;
301 : }
302 1 : default:
303 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
304 : }
305 4227 : return CHIP_NO_ERROR;
306 : }
307 :
308 14992 : CHIP_ERROR TLVReader::Get(ByteSpan & v) const
309 : {
310 : const uint8_t * val;
311 14992 : ReturnErrorOnFailure(GetDataPtr(val));
312 14988 : v = ByteSpan(val, GetLength());
313 :
314 14988 : return CHIP_NO_ERROR;
315 : }
316 :
317 : namespace {
318 : constexpr int kUnicodeInformationSeparator1 = 0x1F;
319 : constexpr size_t kMaxLocalizedStringIdentifierLen = 2 * sizeof(LocalizedStringIdentifier);
320 : } // namespace
321 :
322 1025 : CHIP_ERROR TLVReader::Get(CharSpan & v) const
323 : {
324 1025 : if (!TLVTypeIsUTF8String(ElementType()))
325 : {
326 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
327 : }
328 :
329 : const uint8_t * bytes;
330 1023 : ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
331 1021 : if (bytes == nullptr)
332 : {
333 : // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
334 123 : v = {}; // empty data
335 123 : return CHIP_NO_ERROR;
336 : }
337 :
338 898 : uint32_t len = GetLength();
339 :
340 : // If Unicode Information Separator 1 (0x1f) is present in the string then method returns
341 : // string ending at first appearance of the Information Separator 1.
342 898 : const uint8_t * infoSeparator = reinterpret_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
343 898 : if (infoSeparator != nullptr)
344 : {
345 5 : len = static_cast<uint32_t>(infoSeparator - bytes);
346 : }
347 :
348 898 : v = CharSpan(Uint8::to_const_char(bytes), len);
349 : #if CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
350 : // Spec requirement: A.11.2. UTF-8 and Octet Strings
351 : //
352 : // For UTF-8 strings, the value octets SHALL encode a valid
353 : // UTF-8 character (code points) sequence.
354 : //
355 : // Senders SHALL NOT include a terminating null character to
356 : // mark the end of a string.
357 :
358 : if (!Utf8::IsValid(v))
359 : {
360 : return CHIP_ERROR_INVALID_UTF8;
361 : }
362 :
363 : if (!v.empty() && (v.back() == 0))
364 : {
365 : return CHIP_ERROR_INVALID_TLV_CHAR_STRING;
366 : }
367 : #endif // CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
368 898 : return CHIP_NO_ERROR;
369 : }
370 :
371 15 : CHIP_ERROR TLVReader::Get(Optional<LocalizedStringIdentifier> & lsid)
372 : {
373 15 : lsid.ClearValue();
374 15 : VerifyOrReturnError(TLVTypeIsUTF8String(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
375 :
376 : const uint8_t * bytes;
377 14 : ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
378 14 : if (bytes == nullptr)
379 : {
380 : // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
381 : // This treats null/empty LSID as a NullOptional (we clear the value at the start)
382 0 : return CHIP_NO_ERROR;
383 : }
384 :
385 14 : uint32_t len = GetLength();
386 :
387 14 : const uint8_t * infoSeparator1 = static_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
388 14 : if (infoSeparator1 == nullptr)
389 : {
390 : // This treats null/empty LSID as a NullOptional (we clear the value at the start)
391 1 : return CHIP_NO_ERROR;
392 : }
393 :
394 13 : const uint8_t * lsidPtr = infoSeparator1 + 1;
395 13 : len -= static_cast<uint32_t>(lsidPtr - bytes);
396 :
397 13 : const uint8_t * infoSeparator2 = static_cast<const uint8_t *>(memchr(lsidPtr, kUnicodeInformationSeparator1, len));
398 13 : if (infoSeparator2 != nullptr)
399 : {
400 3 : len = static_cast<uint32_t>(infoSeparator2 - lsidPtr);
401 : }
402 13 : if (len == 0)
403 : {
404 : // This treats null/empty LSID as a NullOptional (we clear the value at the start)
405 1 : return CHIP_NO_ERROR;
406 : }
407 12 : VerifyOrReturnError(len <= kMaxLocalizedStringIdentifierLen, CHIP_ERROR_INVALID_TLV_ELEMENT);
408 : // Leading zeroes are not allowed.
409 11 : VerifyOrReturnError(static_cast<char>(lsidPtr[0]) != '0', CHIP_ERROR_INVALID_TLV_ELEMENT);
410 :
411 9 : char idStr[kMaxLocalizedStringIdentifierLen] = { '0', '0', '0', '0' };
412 9 : memcpy(&idStr[kMaxLocalizedStringIdentifierLen - len], lsidPtr, len);
413 :
414 : LocalizedStringIdentifier id;
415 9 : VerifyOrReturnError(Encoding::UppercaseHexToUint16(idStr, sizeof(idStr), id) == sizeof(LocalizedStringIdentifier),
416 : CHIP_ERROR_INVALID_TLV_ELEMENT);
417 :
418 8 : lsid.SetValue(id);
419 8 : return CHIP_NO_ERROR;
420 : }
421 :
422 23175 : CHIP_ERROR TLVReader::GetBytes(uint8_t * buf, size_t bufSize)
423 : {
424 23175 : if (!TLVTypeIsString(ElementType()))
425 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
426 :
427 23174 : if (mElemLenOrVal > bufSize)
428 0 : return CHIP_ERROR_BUFFER_TOO_SMALL;
429 :
430 23174 : CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
431 46348 : if (err != CHIP_NO_ERROR)
432 0 : return err;
433 :
434 23174 : mElemLenOrVal = 0;
435 :
436 23174 : return CHIP_NO_ERROR;
437 : }
438 :
439 11608 : CHIP_ERROR TLVReader::GetString(char * buf, size_t bufSize)
440 : {
441 11608 : if (!TLVTypeIsString(ElementType()))
442 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
443 :
444 11607 : if ((mElemLenOrVal + 1) > bufSize)
445 1 : return CHIP_ERROR_BUFFER_TOO_SMALL;
446 :
447 11606 : buf[mElemLenOrVal] = 0;
448 :
449 11606 : return GetBytes(reinterpret_cast<uint8_t *>(buf), bufSize - 1);
450 : }
451 :
452 1 : CHIP_ERROR TLVReader::DupBytes(uint8_t *& buf, uint32_t & dataLen)
453 : {
454 1 : if (!TLVTypeIsString(ElementType()))
455 0 : return CHIP_ERROR_WRONG_TLV_TYPE;
456 :
457 1 : buf = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal)));
458 1 : if (buf == nullptr)
459 0 : return CHIP_ERROR_NO_MEMORY;
460 :
461 1 : CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
462 2 : if (err != CHIP_NO_ERROR)
463 : {
464 0 : chip::Platform::MemoryFree(buf);
465 0 : buf = nullptr;
466 0 : return err;
467 : }
468 :
469 1 : dataLen = static_cast<uint32_t>(mElemLenOrVal);
470 1 : mElemLenOrVal = 0;
471 :
472 1 : return CHIP_NO_ERROR;
473 : }
474 :
475 2 : CHIP_ERROR TLVReader::DupString(char *& buf)
476 : {
477 2 : if (!TLVTypeIsString(ElementType()))
478 1 : return CHIP_ERROR_WRONG_TLV_TYPE;
479 :
480 1 : if (mElemLenOrVal > UINT32_MAX - 1)
481 0 : return CHIP_ERROR_NO_MEMORY;
482 :
483 1 : buf = static_cast<char *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal + 1)));
484 1 : if (buf == nullptr)
485 0 : return CHIP_ERROR_NO_MEMORY;
486 :
487 1 : CHIP_ERROR err = ReadData(reinterpret_cast<uint8_t *>(buf), static_cast<uint32_t>(mElemLenOrVal));
488 2 : if (err != CHIP_NO_ERROR)
489 : {
490 0 : chip::Platform::MemoryFree(buf);
491 0 : buf = nullptr;
492 0 : return err;
493 : }
494 :
495 1 : buf[mElemLenOrVal] = 0;
496 1 : mElemLenOrVal = 0;
497 :
498 1 : return err;
499 : }
500 :
501 30302 : CHIP_ERROR TLVReader::GetDataPtr(const uint8_t *& data) const
502 : {
503 30302 : VerifyOrReturnError(TLVTypeIsString(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
504 :
505 30299 : if (GetLength() == 0)
506 : {
507 4758 : data = nullptr;
508 4758 : return CHIP_NO_ERROR;
509 : }
510 :
511 25541 : uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
512 :
513 : // Verify that the entirety of the data is available in the buffer.
514 : // Note that this may not be possible if the reader is reading from a chain of buffers.
515 25541 : VerifyOrReturnError(remainingLen >= static_cast<uint32_t>(mElemLenOrVal), CHIP_ERROR_TLV_UNDERRUN);
516 25537 : data = mReadPoint;
517 25537 : return CHIP_NO_ERROR;
518 : }
519 :
520 1863 : CHIP_ERROR TLVReader::OpenContainer(TLVReader & containerReader)
521 : {
522 1863 : TLVElementType elemType = ElementType();
523 1863 : if (!TLVTypeIsContainer(elemType))
524 1 : return CHIP_ERROR_INCORRECT_STATE;
525 :
526 1862 : containerReader.mBackingStore = mBackingStore;
527 1862 : containerReader.mReadPoint = mReadPoint;
528 1862 : containerReader.mBufEnd = mBufEnd;
529 1862 : containerReader.mLenRead = mLenRead;
530 1862 : containerReader.mMaxLen = mMaxLen;
531 1862 : containerReader.ClearElementState();
532 1862 : containerReader.mContainerType = static_cast<TLVType>(elemType);
533 1862 : containerReader.SetContainerOpen(false);
534 1862 : containerReader.ImplicitProfileId = ImplicitProfileId;
535 1862 : containerReader.AppData = AppData;
536 :
537 1862 : SetContainerOpen(true);
538 :
539 1862 : return CHIP_NO_ERROR;
540 : }
541 :
542 1566 : CHIP_ERROR TLVReader::CloseContainer(TLVReader & containerReader)
543 : {
544 : CHIP_ERROR err;
545 :
546 1566 : if (!IsContainerOpen())
547 1 : return CHIP_ERROR_INCORRECT_STATE;
548 :
549 1565 : if (static_cast<TLVElementType>(containerReader.mContainerType) != ElementType())
550 0 : return CHIP_ERROR_INCORRECT_STATE;
551 :
552 1565 : err = containerReader.SkipToEndOfContainer();
553 3130 : if (err != CHIP_NO_ERROR)
554 0 : return err;
555 :
556 1565 : mBackingStore = containerReader.mBackingStore;
557 1565 : mReadPoint = containerReader.mReadPoint;
558 1565 : mBufEnd = containerReader.mBufEnd;
559 1565 : mLenRead = containerReader.mLenRead;
560 1565 : mMaxLen = containerReader.mMaxLen;
561 1565 : ClearElementState();
562 :
563 1565 : return CHIP_NO_ERROR;
564 : }
565 :
566 3643978 : CHIP_ERROR TLVReader::EnterContainer(TLVType & outerContainerType)
567 : {
568 3643978 : TLVElementType elemType = ElementType();
569 3643978 : if (!TLVTypeIsContainer(elemType))
570 1 : return CHIP_ERROR_INCORRECT_STATE;
571 :
572 3643977 : outerContainerType = mContainerType;
573 3643977 : mContainerType = static_cast<TLVType>(elemType);
574 :
575 3643977 : ClearElementState();
576 3643977 : SetContainerOpen(false);
577 :
578 3643977 : return CHIP_NO_ERROR;
579 : }
580 :
581 598148 : CHIP_ERROR TLVReader::ExitContainer(TLVType outerContainerType)
582 : {
583 : CHIP_ERROR err;
584 :
585 598148 : err = SkipToEndOfContainer();
586 1196296 : if (err != CHIP_NO_ERROR)
587 40 : return err;
588 :
589 598108 : mContainerType = outerContainerType;
590 598108 : ClearElementState();
591 :
592 598108 : return CHIP_NO_ERROR;
593 : }
594 :
595 8089 : CHIP_ERROR TLVReader::VerifyEndOfContainer()
596 : {
597 8089 : CHIP_ERROR err = Next();
598 16178 : if (err == CHIP_END_OF_TLV)
599 8086 : return CHIP_NO_ERROR;
600 6 : if (err == CHIP_NO_ERROR)
601 2 : return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
602 1 : return err;
603 : }
604 :
605 9441343 : CHIP_ERROR TLVReader::Next()
606 : {
607 9441343 : ReturnErrorOnFailure(Skip());
608 9437784 : ReturnErrorOnFailure(ReadElement());
609 :
610 9410317 : TLVElementType elemType = ElementType();
611 :
612 9410317 : VerifyOrReturnError(elemType != TLVElementType::EndOfContainer, CHIP_END_OF_TLV);
613 :
614 : // Ensure that GetDataPtr calls can be called immediately after Next, so
615 : // that `Get(ByteSpan&)` does not need to advance buffers and just works
616 9143685 : if (TLVTypeIsString(elemType) && (GetLength() != 0))
617 : {
618 43212 : ReturnErrorOnFailure(EnsureData(CHIP_ERROR_TLV_UNDERRUN));
619 : }
620 :
621 9143685 : return CHIP_NO_ERROR;
622 : }
623 :
624 403253 : CHIP_ERROR TLVReader::Expect(Tag expectedTag)
625 : {
626 403253 : VerifyOrReturnError(GetType() != kTLVType_NotSpecified, CHIP_ERROR_WRONG_TLV_TYPE);
627 403249 : VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
628 403200 : return CHIP_NO_ERROR;
629 : }
630 :
631 402545 : CHIP_ERROR TLVReader::Next(Tag expectedTag)
632 : {
633 402545 : ReturnErrorOnFailure(Next());
634 399684 : ReturnErrorOnFailure(Expect(expectedTag));
635 399638 : return CHIP_NO_ERROR;
636 : }
637 :
638 7708114 : CHIP_ERROR TLVReader::Expect(TLVType expectedType, Tag expectedTag)
639 : {
640 7708114 : VerifyOrReturnError(GetType() == expectedType, CHIP_ERROR_WRONG_TLV_TYPE);
641 7699163 : VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
642 7636401 : return CHIP_NO_ERROR;
643 : }
644 :
645 7699919 : CHIP_ERROR TLVReader::Next(TLVType expectedType, Tag expectedTag)
646 : {
647 7699919 : ReturnErrorOnFailure(Next());
648 7687383 : ReturnErrorOnFailure(Expect(expectedType, expectedTag));
649 7616659 : return CHIP_NO_ERROR;
650 : }
651 :
652 9470606 : CHIP_ERROR TLVReader::Skip()
653 : {
654 9470606 : const TLVElementType elemType = ElementType();
655 9470606 : VerifyOrReturnError(elemType != TLVElementType::EndOfContainer, CHIP_END_OF_TLV);
656 :
657 9467049 : if (TLVTypeIsContainer(elemType))
658 : {
659 : TLVType outerContainerType;
660 276576 : ReturnErrorOnFailure(EnterContainer(outerContainerType));
661 276576 : return ExitContainer(outerContainerType);
662 : }
663 :
664 9190473 : ReturnErrorOnFailure(SkipData());
665 9190473 : ClearElementState();
666 :
667 9190473 : return CHIP_NO_ERROR;
668 : }
669 :
670 : /**
671 : * Clear the state of the TLVReader.
672 : * This method is used to position the reader before the first TLV,
673 : * between TLVs or after the last TLV.
674 : */
675 15139725 : void TLVReader::ClearElementState()
676 : {
677 15139725 : mElemTag = AnonymousTag();
678 15139725 : mControlByte = kTLVControlByte_NotSpecified;
679 15139725 : mElemLenOrVal = 0;
680 15139725 : }
681 :
682 : /**
683 : * Skip any data contained in the current TLV by reading over it without
684 : * a destination buffer.
685 : *
686 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the end of the
687 : * data.
688 : * @retval other Other CHIP or platform error codes returned by the configured
689 : * TLVBackingStore.
690 : */
691 13002233 : CHIP_ERROR TLVReader::SkipData()
692 : {
693 13002233 : CHIP_ERROR err = CHIP_NO_ERROR;
694 13002233 : TLVElementType elemType = ElementType();
695 :
696 13002233 : if (TLVTypeHasLength(elemType))
697 : {
698 319973 : err = ReadData(nullptr, static_cast<uint32_t>(mElemLenOrVal));
699 : }
700 :
701 13002233 : return err;
702 : }
703 :
704 599713 : CHIP_ERROR TLVReader::SkipToEndOfContainer()
705 : {
706 : CHIP_ERROR err;
707 599713 : TLVType outerContainerType = mContainerType;
708 599713 : uint32_t nestLevel = 0;
709 :
710 : // If the user calls Next() after having called OpenContainer() but before calling
711 : // CloseContainer() they're effectively doing a close container by skipping over
712 : // the container element. So reset the 'container open' flag here to prevent them
713 : // from calling CloseContainer() with the now orphaned container reader.
714 599713 : SetContainerOpen(false);
715 :
716 : while (true)
717 : {
718 4411433 : TLVElementType elemType = ElementType();
719 :
720 4411433 : if (elemType == TLVElementType::EndOfContainer)
721 : {
722 1293876 : if (nestLevel == 0)
723 599673 : return CHIP_NO_ERROR;
724 :
725 694203 : nestLevel--;
726 694203 : mContainerType = (nestLevel == 0) ? outerContainerType : kTLVType_UnknownContainer;
727 : }
728 :
729 3117557 : else if (TLVTypeIsContainer(elemType))
730 : {
731 694204 : nestLevel++;
732 694204 : mContainerType = static_cast<TLVType>(elemType);
733 : }
734 :
735 3811760 : err = SkipData();
736 7623520 : if (err != CHIP_NO_ERROR)
737 0 : return err;
738 :
739 3811760 : err = ReadElement();
740 7623520 : if (err != CHIP_NO_ERROR)
741 40 : return err;
742 3811720 : }
743 : }
744 :
745 13249544 : CHIP_ERROR TLVReader::ReadElement()
746 : {
747 : // Make sure we have input data. Return CHIP_END_OF_TLV if no more data is available.
748 13249544 : ReturnErrorOnFailure(EnsureData(CHIP_END_OF_TLV));
749 13234036 : VerifyOrReturnError(mReadPoint != nullptr, CHIP_ERROR_INVALID_TLV_ELEMENT);
750 :
751 : // Get the element's control byte.
752 13234036 : mControlByte = *mReadPoint;
753 :
754 : // Extract the element type from the control byte. Fail if it's invalid.
755 13234036 : TLVElementType elemType = ElementType();
756 13234036 : VerifyOrReturnError(IsValidTLVType(elemType), CHIP_ERROR_INVALID_TLV_ELEMENT);
757 :
758 : // Extract the tag control from the control byte.
759 13229463 : TLVTagControl tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
760 :
761 : // Determine the number of bytes in the element's tag, if any.
762 13229463 : uint8_t tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
763 :
764 : // Extract the size of length/value field from the control byte.
765 13229463 : TLVFieldSize lenOrValFieldSize = GetTLVFieldSize(elemType);
766 :
767 : // Determine the number of bytes in the length/value field.
768 13229463 : const uint8_t valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
769 :
770 : // Determine the number of bytes in the element's 'head'. This includes: the control byte, the tag bytes (if present), the
771 : // length bytes (if present), and for elements that don't have a length (e.g. integers), the value bytes.
772 13229463 : const uint8_t elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
773 :
774 : // 17 = 1 control byte + 8 tag bytes + 8 length/value bytes
775 : uint8_t stagingBuf[17];
776 :
777 : // Odd workaround: clang-tidy claims garbage value otherwise as it does not
778 : // understand that ReadData initializes stagingBuf
779 13229463 : stagingBuf[1] = 0;
780 :
781 : // If the head of the element goes past the end of the current input buffer,
782 : // we need to read it into the staging buffer to parse it. Just do that unconditionally,
783 : // even if the head does not go past end of current buffer, to save codesize.
784 13229463 : ReturnErrorOnFailure(ReadData(stagingBuf, elemHeadBytes));
785 :
786 : // +1 to skip over the control byte
787 13229459 : const uint8_t * p = stagingBuf + 1;
788 :
789 : // Read the tag field, if present.
790 13229459 : mElemTag = ReadTag(tagControl, p);
791 13229459 : mElemLenOrVal = 0;
792 :
793 : // Read the length/value field, if present.
794 : // NOTE: this is works because even though we only memcpy a subset of values and leave
795 : // the rest 0. Value looks like "<le-byte> <le-byte> ... <le-byte> 0 0 ... 0"
796 : // which is the TLV format. HostSwap ensures this becomes a real host value
797 : // (should be a NOOP on LE machines, will full-swap on big-endian machines)
798 13229459 : memcpy(&mElemLenOrVal, p, valOrLenBytes);
799 13229459 : LittleEndian::HostSwap(mElemLenOrVal);
800 :
801 13229459 : VerifyOrReturnError(!TLVTypeHasLength(elemType) || (mElemLenOrVal <= UINT32_MAX), CHIP_ERROR_NOT_IMPLEMENTED);
802 :
803 13228158 : return VerifyElement();
804 : }
805 :
806 13228158 : CHIP_ERROR TLVReader::VerifyElement()
807 : {
808 13228158 : if (ElementType() == TLVElementType::EndOfContainer)
809 : {
810 1357613 : if (mContainerType == kTLVType_NotSpecified)
811 123 : return CHIP_ERROR_INVALID_TLV_ELEMENT;
812 1357490 : if (mElemTag != AnonymousTag())
813 483 : return CHIP_ERROR_INVALID_TLV_TAG;
814 : }
815 : else
816 : {
817 11870545 : if (mElemTag == UnknownImplicitTag())
818 0 : return CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG;
819 11870545 : switch (mContainerType)
820 : {
821 1712104 : case kTLVType_NotSpecified:
822 1712104 : if (IsContextTag(mElemTag))
823 381 : return CHIP_ERROR_INVALID_TLV_TAG;
824 1711723 : break;
825 6696360 : case kTLVType_Structure:
826 6696360 : if (mElemTag == AnonymousTag())
827 1070 : return CHIP_ERROR_INVALID_TLV_TAG;
828 6695290 : break;
829 1926763 : case kTLVType_Array:
830 1926763 : if (mElemTag != AnonymousTag())
831 2490 : return CHIP_ERROR_INVALID_TLV_TAG;
832 1924273 : break;
833 1535318 : case kTLVType_UnknownContainer:
834 : case kTLVType_List:
835 1535318 : break;
836 0 : default:
837 0 : return CHIP_ERROR_INCORRECT_STATE;
838 : }
839 : }
840 :
841 : // If the current element encodes a specific length (e.g. a UTF8 string or a byte string), verify
842 : // that the purported length fits within the remaining bytes of the encoding (as delineated by mMaxLen).
843 : //
844 : // Note that this check is not strictly necessary to prevent runtime errors, as any attempt to access
845 : // the data of an element with an invalid length will result in an error. However checking the length
846 : // here catches the error earlier, and ensures that the application will never see the erroneous length
847 : // value.
848 : //
849 13223611 : if (TLVTypeHasLength(ElementType()))
850 : {
851 326369 : uint32_t overallLenRemaining = mMaxLen - mLenRead;
852 326369 : if (overallLenRemaining < static_cast<uint32_t>(mElemLenOrVal))
853 1574 : return CHIP_ERROR_TLV_UNDERRUN;
854 : }
855 :
856 13222037 : return CHIP_NO_ERROR;
857 : }
858 :
859 13229459 : Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) const
860 : {
861 : uint16_t vendorId;
862 : uint16_t profileNum;
863 :
864 13229459 : switch (tagControl)
865 : {
866 5118987 : case TLVTagControl::ContextSpecific:
867 5118987 : return ContextTag(Read8(p));
868 2008 : case TLVTagControl::CommonProfile_2Bytes:
869 2008 : return CommonTag(LittleEndian::Read16(p));
870 2439 : case TLVTagControl::CommonProfile_4Bytes:
871 2439 : return CommonTag(LittleEndian::Read32(p));
872 1518743 : case TLVTagControl::ImplicitProfile_2Bytes:
873 1518743 : if (ImplicitProfileId == kProfileIdNotSpecified)
874 0 : return UnknownImplicitTag();
875 1518743 : return ProfileTag(ImplicitProfileId, LittleEndian::Read16(p));
876 3205 : case TLVTagControl::ImplicitProfile_4Bytes:
877 3205 : if (ImplicitProfileId == kProfileIdNotSpecified)
878 0 : return UnknownImplicitTag();
879 3205 : return ProfileTag(ImplicitProfileId, LittleEndian::Read32(p));
880 3122567 : case TLVTagControl::FullyQualified_6Bytes:
881 3122567 : vendorId = LittleEndian::Read16(p);
882 3122567 : profileNum = LittleEndian::Read16(p);
883 3122567 : return ProfileTag(vendorId, profileNum, LittleEndian::Read16(p));
884 2069 : case TLVTagControl::FullyQualified_8Bytes:
885 2069 : vendorId = LittleEndian::Read16(p);
886 2069 : profileNum = LittleEndian::Read16(p);
887 2069 : return ProfileTag(vendorId, profileNum, LittleEndian::Read32(p));
888 3459441 : case TLVTagControl::Anonymous:
889 : default:
890 3459441 : return AnonymousTag();
891 : }
892 : }
893 :
894 13595235 : CHIP_ERROR TLVReader::ReadData(uint8_t * buf, uint32_t len)
895 : {
896 26915296 : while (len > 0)
897 : {
898 13320065 : ReturnErrorOnFailure(EnsureData(CHIP_ERROR_TLV_UNDERRUN));
899 :
900 13320061 : uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
901 :
902 13320061 : uint32_t readLen = len;
903 13320061 : if (readLen > remainingLen)
904 161 : readLen = remainingLen;
905 :
906 13320061 : if (buf != nullptr)
907 : {
908 13258345 : memcpy(buf, mReadPoint, readLen);
909 13258345 : buf += readLen;
910 : }
911 13320061 : mReadPoint += readLen;
912 13320061 : mLenRead += readLen;
913 13320061 : len -= readLen;
914 : }
915 :
916 13595231 : return CHIP_NO_ERROR;
917 : }
918 :
919 26612821 : CHIP_ERROR TLVReader::EnsureData(CHIP_ERROR noDataErr)
920 : {
921 26612821 : if (mReadPoint == mBufEnd)
922 : {
923 15799 : VerifyOrReturnError((mLenRead != mMaxLen) && (mBackingStore != nullptr), noDataErr);
924 :
925 : uint32_t bufLen;
926 287 : ReturnErrorOnFailure(mBackingStore->GetNextBuffer(*this, mReadPoint, bufLen));
927 287 : VerifyOrReturnError(bufLen > 0, noDataErr);
928 :
929 : // Cap mBufEnd so that we don't read beyond the user's specified maximum length, even
930 : // if the underlying buffer is larger.
931 287 : bufLen = std::min(bufLen, mMaxLen - mLenRead);
932 287 : mBufEnd = mReadPoint + bufLen;
933 : }
934 :
935 26597309 : return CHIP_NO_ERROR;
936 : }
937 :
938 : /**
939 : * This is a private method used to compute the length of a TLV element head.
940 : */
941 2 : CHIP_ERROR TLVReader::GetElementHeadLength(uint8_t & elemHeadBytes) const
942 : {
943 : uint8_t tagBytes;
944 : uint8_t valOrLenBytes;
945 : TLVTagControl tagControl;
946 : TLVFieldSize lenOrValFieldSize;
947 2 : TLVElementType elemType = ElementType();
948 :
949 : // Verify element is of valid TLVType.
950 2 : VerifyOrReturnError(IsValidTLVType(elemType), CHIP_ERROR_INVALID_TLV_ELEMENT);
951 :
952 : // Extract the tag control from the control byte.
953 2 : tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
954 :
955 : // Determine the number of bytes in the element's tag, if any.
956 2 : tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
957 :
958 : // Extract the size of length/value field from the control byte.
959 2 : lenOrValFieldSize = GetTLVFieldSize(elemType);
960 :
961 : // Determine the number of bytes in the length/value field.
962 2 : valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
963 :
964 : // Determine the number of bytes in the element's 'head'. This includes: the
965 : // control byte, the tag bytes (if present), the length bytes (if present),
966 : // and for elements that don't have a length (e.g. integers), the value
967 : // bytes.
968 2 : VerifyOrReturnError(CanCastTo<uint8_t>(1 + tagBytes + valOrLenBytes), CHIP_ERROR_INTERNAL);
969 2 : elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
970 :
971 2 : return CHIP_NO_ERROR;
972 : }
973 :
974 : /**
975 : * This is a private method that returns the TLVElementType from mControlByte
976 : */
977 100312967 : TLVElementType TLVReader::ElementType() const
978 : {
979 100312967 : if (mControlByte == static_cast<uint16_t>(kTLVControlByte_NotSpecified))
980 11366213 : return TLVElementType::NotSpecified;
981 88946754 : return static_cast<TLVElementType>(mControlByte & kTLVTypeMask);
982 : }
983 :
984 214020 : CHIP_ERROR TLVReader::FindElementWithTag(Tag tag, TLVReader & destReader) const
985 : {
986 214020 : CHIP_ERROR err = CHIP_NO_ERROR;
987 :
988 214020 : chip::TLV::TLVReader reader;
989 214020 : reader.Init(*this);
990 :
991 992286 : while (CHIP_NO_ERROR == (err = reader.Next()))
992 : {
993 461353 : VerifyOrExit(chip::TLV::kTLVType_NotSpecified != reader.GetType(), err = CHIP_ERROR_INVALID_TLV_ELEMENT);
994 :
995 461353 : if (tag == reader.GetTag())
996 : {
997 179230 : destReader.Init(reader);
998 179230 : break;
999 : }
1000 : }
1001 :
1002 34790 : exit:
1003 462830 : ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
1004 :
1005 214020 : return err;
1006 : }
1007 :
1008 1574 : CHIP_ERROR TLVReader::CountRemainingInContainer(size_t * size) const
1009 : {
1010 1574 : if (mContainerType == kTLVType_NotSpecified)
1011 : {
1012 0 : return CHIP_ERROR_INCORRECT_STATE;
1013 : }
1014 :
1015 1574 : TLVReader tempReader(*this);
1016 1574 : size_t count = 0;
1017 : CHIP_ERROR err;
1018 12858 : while ((err = tempReader.Next()) == CHIP_NO_ERROR)
1019 : {
1020 4855 : ++count;
1021 : };
1022 3148 : if (err == CHIP_END_OF_TLV)
1023 : {
1024 1574 : *size = count;
1025 1574 : return CHIP_NO_ERROR;
1026 : }
1027 0 : return err;
1028 : }
1029 :
1030 10 : CHIP_ERROR ContiguousBufferTLVReader::OpenContainer(ContiguousBufferTLVReader & containerReader)
1031 : {
1032 : // We are going to initialize containerReader by calling our superclass
1033 : // OpenContainer method. The superclass only knows how to initialize
1034 : // members the superclass knows about, so we assert that we don't have any
1035 : // extra members that need initializing. If such members ever get added,
1036 : // they would need to be initialized in this method.
1037 : static_assert(sizeof(ContiguousBufferTLVReader) == sizeof(TLVReader), "We have state the superclass is not initializing?");
1038 10 : return TLVReader::OpenContainer(containerReader);
1039 : }
1040 :
1041 11 : CHIP_ERROR ContiguousBufferTLVReader::GetStringView(Span<const char> & data)
1042 : {
1043 11 : return Get(data);
1044 : }
1045 :
1046 670 : CHIP_ERROR ContiguousBufferTLVReader::GetByteView(ByteSpan & data)
1047 : {
1048 670 : if (!TLVTypeIsByteString(ElementType()))
1049 : {
1050 2 : return CHIP_ERROR_WRONG_TLV_TYPE;
1051 : }
1052 :
1053 668 : return Get(data);
1054 : }
1055 :
1056 : } // namespace TLV
1057 : } // namespace chip
|