Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / mdns / minimal / core / 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 #include <strings.h>
19
20 #include "QName.h"
21
22 namespace mdns {
23 namespace Minimal {
24
25 bool SerializedQNameIterator::Next()
26 {
27     return mIsValid && Next(true);
28 }
29
30 bool SerializedQNameIterator::Next(bool followIndirectPointers)
31 {
32     if (!mIsValid)
33     {
34         return false;
35     }
36
37     while (true)
38     {
39         assert(mValidData.Contains(mCurrentPosition));
40
41         const uint8_t length = *mCurrentPosition;
42         if (*mCurrentPosition == 0)
43         {
44             // Done with all items
45             return false;
46         }
47
48         if ((length & kPtrMask) == kPtrMask)
49         {
50             if (!followIndirectPointers)
51             {
52                 // Stop at first indirect pointer
53                 return false;
54             }
55
56             // PTR contains 2 bytes
57             if (!mValidData.Contains(mCurrentPosition + 1))
58             {
59                 mIsValid = false;
60                 return false;
61             }
62
63             size_t offset = ((*mCurrentPosition & 0x3F) << 8) | *(mCurrentPosition + 1);
64             if (offset > mLookBehindMax)
65             {
66                 // Potential infinite recursion.
67                 mIsValid = false;
68                 return false;
69             }
70             if (offset > mValidData.Size())
71             {
72                 // offset too large
73                 mIsValid = false;
74                 return false;
75             }
76
77             mLookBehindMax   = offset;
78             mCurrentPosition = mValidData.Start() + offset;
79         }
80         else
81         {
82             // This branch handles non-pointer data. This will be string of size [length].
83             if (length > kMaxValueSize)
84             {
85                 // value is too large (larger than RFC limit)
86                 mIsValid = false;
87                 return false;
88             }
89
90             if (!mValidData.Contains(mCurrentPosition + 1 + length))
91             {
92                 // string outside valid data
93                 mIsValid = false;
94                 return false;
95             }
96
97             memcpy(mValue, mCurrentPosition + 1, length);
98             mValue[length]   = '\0';
99             mCurrentPosition = mCurrentPosition + length + 1;
100             return true;
101         }
102     }
103 }
104
105 const uint8_t * SerializedQNameIterator::FindDataEnd()
106 {
107     while (Next(false))
108     {
109         // nothing to do, just advance
110     }
111
112     if (!IsValid())
113     {
114         return nullptr;
115     }
116
117     // normal end
118     if (*mCurrentPosition == 0)
119     {
120         // mCurrentPosition MUST already be valid
121         return mCurrentPosition + 1;
122     }
123
124     // ends with a dataptr
125     if ((*mCurrentPosition & kPtrMask) == kPtrMask)
126     {
127         if (!mValidData.Contains(mCurrentPosition + 1))
128         {
129             return nullptr;
130         }
131         return mCurrentPosition + 2;
132     }
133
134     // invalid data
135     return nullptr;
136 }
137
138 bool SerializedQNameIterator::operator==(const FullQName & other) const
139 {
140     SerializedQNameIterator self = *this; // allow iteration
141     size_t idx                   = 0;
142
143     while ((idx < other.nameCount) && self.Next())
144     {
145         if (strcasecmp(self.Value(), other.names[idx]) != 0)
146         {
147             return false;
148         }
149         idx++;
150     }
151
152     return ((idx == other.nameCount) && !self.Next());
153 }
154
155 bool FullQName::operator==(const FullQName & other) const
156 {
157     if (nameCount != other.nameCount)
158     {
159         return false;
160     }
161     for (size_t i = 0; i < nameCount; i++)
162     {
163         if (strcasecmp(names[i], other.names[i]) != 0)
164         {
165             return false;
166         }
167     }
168     return true;
169 }
170
171 } // namespace Minimal
172 } // namespace mdns