Change script for apply upstream code
[platform/upstream/connectedhomeip.git] / src / lib / mdns / minimal / QName.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17 #include <assert.h>
18
19 #include "QName.h"
20
21 namespace mdns {
22 namespace Minimal {
23
24 bool SerializedQNameIterator::Next()
25 {
26     return mIsValid && Next(true);
27 }
28
29 bool SerializedQNameIterator::Next(bool followIndirectPointers)
30 {
31     if (!mIsValid)
32     {
33         return false;
34     }
35
36     while (true)
37     {
38         assert(mValidData.Contains(mCurrentPosition));
39
40         const uint8_t length = *mCurrentPosition;
41         if (*mCurrentPosition == 0)
42         {
43             // Done with all items
44             return false;
45         }
46
47         if ((length & kPtrMask) == kPtrMask)
48         {
49             if (!followIndirectPointers)
50             {
51                 // Stop at first indirect pointer
52                 return false;
53             }
54
55             // PTR contains 2 bytes
56             if (!mValidData.Contains(mCurrentPosition + 1))
57             {
58                 mIsValid = false;
59                 return false;
60             }
61
62             size_t offset = ((*mCurrentPosition & 0x3F) << 8) | *(mCurrentPosition + 1);
63             if (offset > mLookBehindMax)
64             {
65                 // Potential infinite recursion.
66                 mIsValid = false;
67                 return false;
68             }
69             if (offset > mValidData.Size())
70             {
71                 // offset too large
72                 mIsValid = false;
73                 return false;
74             }
75
76             mLookBehindMax   = offset;
77             mCurrentPosition = mValidData.Start() + offset;
78         }
79         else
80         {
81             // This branch handles non-pointer data. This will be string of size [length].
82             if (length > kMaxValueSize)
83             {
84                 // value is too large (larger than RFC limit)
85                 mIsValid = false;
86                 return false;
87             }
88
89             if (!mValidData.Contains(mCurrentPosition + 1 + length))
90             {
91                 // string outside valid data
92                 mIsValid = false;
93                 return false;
94             }
95
96             memcpy(mValue, mCurrentPosition + 1, length);
97             mValue[length]   = '\0';
98             mCurrentPosition = mCurrentPosition + length + 1;
99             return true;
100         }
101     }
102 }
103
104 const uint8_t * SerializedQNameIterator::FindDataEnd()
105 {
106     while (Next(false))
107     {
108         // nothing to do, just advance
109     }
110
111     if (!IsValid())
112     {
113         return nullptr;
114     }
115
116     // normal end
117     if (*mCurrentPosition == 0)
118     {
119         // mCurrentPosition MUST already be valid
120         return mCurrentPosition + 1;
121     }
122
123     // ends with a dataptr
124     if ((*mCurrentPosition & kPtrMask) == kPtrMask)
125     {
126         if (!mValidData.Contains(mCurrentPosition + 1))
127         {
128             return nullptr;
129         }
130         return mCurrentPosition + 2;
131     }
132
133     // invalid data
134     return nullptr;
135 }
136
137 } // namespace Minimal
138 } // namespace mdns