LCOV - code coverage report
Current view: top level - lib/dnssd/minimal_mdns/core - QName.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 69 78 88.5 %
Date: 2024-02-15 08:20:41 Functions: 6 6 100.0 %

          Line data    Source code
       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       60405 : bool SerializedQNameIterator::Next()
      26             : {
      27       60405 :     return mIsValid && Next(true);
      28             : }
      29             : 
      30       61909 : bool SerializedQNameIterator::Next(bool followIndirectPointers)
      31             : {
      32       61909 :     if (!mIsValid)
      33             :     {
      34           0 :         return false;
      35             :     }
      36             : 
      37             :     while (true)
      38             :     {
      39       72606 :         assert(mValidData.Contains(mCurrentPosition));
      40             : 
      41       72606 :         const uint8_t length = *mCurrentPosition;
      42       72606 :         if (*mCurrentPosition == 0)
      43             :         {
      44             :             // Done with all items
      45       12229 :             return false;
      46             :         }
      47             : 
      48       60377 :         if ((length & kPtrMask) == kPtrMask)
      49             :         {
      50       11307 :             if (!followIndirectPointers)
      51             :             {
      52             :                 // Stop at first indirect pointer
      53         607 :                 return false;
      54             :             }
      55             : 
      56             :             // PTR contains 2 bytes
      57       10700 :             if (!mValidData.Contains(mCurrentPosition + 1))
      58             :             {
      59           2 :                 mIsValid = false;
      60           2 :                 return false;
      61             :             }
      62             : 
      63       10698 :             size_t offset = static_cast<size_t>(((*mCurrentPosition & 0x3F) << 8) | *(mCurrentPosition + 1));
      64       10698 :             if (offset > mLookBehindMax)
      65             :             {
      66             :                 // Potential infinite recursion.
      67           0 :                 mIsValid = false;
      68           0 :                 return false;
      69             :             }
      70       10698 :             if (offset > mValidData.Size())
      71             :             {
      72             :                 // offset too large
      73           0 :                 mIsValid = false;
      74           0 :                 return false;
      75             :             }
      76             : 
      77             :             // Look behind has to keep going backwards, otherwise we may
      78             :             // get into an infinite list
      79       10698 :             if (offset >= static_cast<size_t>(mCurrentPosition - mValidData.Start()))
      80             :             {
      81           1 :                 mIsValid = false;
      82           1 :                 return false;
      83             :             }
      84             : 
      85       10697 :             mLookBehindMax   = offset;
      86       10697 :             mCurrentPosition = mValidData.Start() + offset;
      87             :         }
      88             :         else
      89             :         {
      90             :             // This branch handles non-pointer data. This will be string of size [length].
      91       49070 :             if (length > kMaxValueSize)
      92             :             {
      93             :                 // value is too large (larger than RFC limit)
      94           3 :                 mIsValid = false;
      95           3 :                 return false;
      96             :             }
      97             : 
      98       49067 :             if (!mValidData.Contains(mCurrentPosition + 1 + length))
      99             :             {
     100             :                 // string outside valid data
     101           7 :                 mIsValid = false;
     102           7 :                 return false;
     103             :             }
     104             : 
     105       49060 :             memcpy(mValue, mCurrentPosition + 1, length);
     106       49060 :             mValue[length]   = '\0';
     107       49060 :             mCurrentPosition = mCurrentPosition + length + 1;
     108       49060 :             return true;
     109             :         }
     110       10697 :     }
     111             : }
     112             : 
     113         744 : const uint8_t * SerializedQNameIterator::FindDataEnd()
     114             : {
     115        1504 :     while (Next(false))
     116             :     {
     117             :         // nothing to do, just advance
     118             :     }
     119             : 
     120         744 :     if (!IsValid())
     121             :     {
     122           0 :         return nullptr;
     123             :     }
     124             : 
     125             :     // normal end
     126         744 :     if (*mCurrentPosition == 0)
     127             :     {
     128             :         // mCurrentPosition MUST already be valid
     129         137 :         return mCurrentPosition + 1;
     130             :     }
     131             : 
     132             :     // ends with a dataptr
     133         607 :     if ((*mCurrentPosition & kPtrMask) == kPtrMask)
     134             :     {
     135         607 :         if (!mValidData.Contains(mCurrentPosition + 1))
     136             :         {
     137           0 :             return nullptr;
     138             :         }
     139         607 :         return mCurrentPosition + 2;
     140             :     }
     141             : 
     142             :     // invalid data
     143           0 :     return nullptr;
     144             : }
     145             : 
     146       27252 : bool SerializedQNameIterator::operator==(const FullQName & other) const
     147             : {
     148       27252 :     SerializedQNameIterator self = *this; // allow iteration
     149       27252 :     size_t idx                   = 0;
     150             : 
     151       33189 :     while ((idx < other.nameCount) && self.Next())
     152             :     {
     153       26429 :         if (strcasecmp(self.Value(), other.names[idx]) != 0)
     154             :         {
     155       20492 :             return false;
     156             :         }
     157        5937 :         idx++;
     158             :     }
     159             : 
     160        6760 :     return ((idx == other.nameCount) && !self.Next());
     161             : }
     162             : 
     163         146 : bool SerializedQNameIterator::operator==(const SerializedQNameIterator & other) const
     164             : {
     165         146 :     SerializedQNameIterator a = *this; // allow iteration
     166         146 :     SerializedQNameIterator b = other;
     167             : 
     168             :     while (true)
     169             :     {
     170         504 :         bool hasA = a.Next();
     171         504 :         bool hasB = b.Next();
     172             : 
     173         504 :         if (hasA ^ hasB)
     174             :         {
     175           6 :             return false; /// one is longer than the other
     176             :         }
     177             : 
     178         498 :         if (!a.IsValid() || !b.IsValid())
     179             :         {
     180           0 :             return false; // invalid data
     181             :         }
     182             : 
     183         498 :         if (!hasA || !hasB)
     184             :         {
     185             :             break;
     186             :         }
     187             : 
     188         375 :         if (strcasecmp(a.Value(), b.Value()) != 0)
     189             :         {
     190          17 :             return false;
     191             :         }
     192         358 :     }
     193             : 
     194         123 :     return a.IsValid() && b.IsValid();
     195             : }
     196             : 
     197        6027 : bool FullQName::operator==(const FullQName & other) const
     198             : {
     199        6027 :     if (nameCount != other.nameCount)
     200             :     {
     201        4641 :         return false;
     202             :     }
     203        4338 :     for (size_t i = 0; i < nameCount; i++)
     204             :     {
     205        3443 :         if (strcasecmp(names[i], other.names[i]) != 0)
     206             :         {
     207         491 :             return false;
     208             :         }
     209             :     }
     210         895 :     return true;
     211             : }
     212             : 
     213             : } // namespace Minimal
     214             : } // namespace mdns

Generated by: LCOV version 1.14