Coverage Report

Created: 2025-06-13 06:12

/src/resiprocate/rutil/ParseBuffer.hxx
Line
Count
Source (jump to first uncovered line)
1
#if !defined(RESIP_PARSEBUFFER_HXX)
2
#define RESIP_PARSEBUFFER_HXX 
3
4
#include "rutil/Data.hxx"
5
#include "rutil/ParseException.hxx"
6
7
namespace resip
8
{
9
10
/**
11
   @brief Provides string-parsing functionality with protection from buffer
12
      overflow.
13
14
   Throws ParseException when parse failures occur.
15
   @ingroup text_proc
16
*/
17
class ParseBuffer
18
{
19
   public:
20
      // does NOT OWN the buffer memory
21
      ParseBuffer(const char* buff, size_t len, 
22
                  const Data& errorContext = Data::Empty);
23
24
      explicit ParseBuffer(const char* buff, 
25
                           const Data& errorContext = Data::Empty);
26
27
      explicit ParseBuffer(const Data& data,
28
                           const Data& errorContext = Data::Empty);
29
30
      ParseBuffer(const ParseBuffer& other);
31
32
///@cond
33
      // .bwc. Backwards-compatibility hack; ParseException used to be
34
      // a full inner class of ParseBuffer, and we also had a separate 
35
      // ParseException class that other things used. For consistency, we have
36
      // moved everything over to use ParseException, but there is app-code
37
      // out there that still expects ParseException to exist.
38
      typedef ParseException Exception;
39
///@endcond
40
41
   private:
42
      /**
43
         @internal
44
         @brief Provides some access to the current position of a ParseBuffer, 
45
         which guards against invalid accesses. Just a wrapper around a 
46
         ParseBuffer&, so is very cheap to initialize/copy.
47
      */
48
      class CurrentPosition
49
      {
50
         public:
51
            inline explicit CurrentPosition(const ParseBuffer& pb) :
52
44.3M
               mPb(pb)
53
44.3M
            {}
54
55
            operator const char*() const
56
16.4M
            {
57
16.4M
               return mPb.mPosition;
58
16.4M
            }
59
60
            const char& operator*() const
61
7.83M
            {
62
7.83M
               mPb.assertNotEof();
63
7.83M
               return *mPb.mPosition;
64
7.83M
            }
65
66
            const ParseBuffer& mPb;
67
      };
68
69
      /**
70
         @internal
71
         @brief Similar to CurrentPosition, but does not move depending on the 
72
         state of the ParseBuffer. Initializing one of these is more expensive.
73
      */
74
      class Pointer
75
      {
76
         public:
77
            Pointer(const ParseBuffer& pb,
78
                    const char* position,
79
                    bool atEof);
80
            Pointer(const CurrentPosition& pos);
81
82
            operator const char*() const
83
5.54k
            {
84
5.54k
               return mPosition;
85
5.54k
            }
86
87
            const char& operator*() const;
88
         private:
89
            const ParseBuffer& mPb;
90
            const char* mPosition;
91
            const bool mIsValid;
92
            static const Data msg;
93
      };
94
95
   public:
96
6.26k
      const Data& getContext() const {return mErrorContext;}
97
      
98
      // allow the buffer to be rolled back
99
      ParseBuffer& operator=(const ParseBuffer& other);
100
      void reset(const char* pos)
101
38.8k
      {
102
38.8k
         resip_assert( mBuff <= mEnd);
103
38.8k
         resip_assert( (pos >= mBuff) && (pos <= mEnd) );
104
38.8k
         mPosition = pos;
105
38.8k
      }
resip::ParseBuffer::reset(char const*)
Line
Count
Source
101
38.8k
      {
102
38.8k
         resip_assert( mBuff <= mEnd);
103
38.8k
         resip_assert( (pos >= mBuff) && (pos <= mEnd) );
104
38.8k
         mPosition = pos;
105
38.8k
      }
Unexecuted instantiation: resip::ParseBuffer::reset(char const*)
106
107
      // abcdef
108
      // ^     ^
109
      // begin end
110
32.0M
      bool eof() const { return mPosition >= mEnd;}
111
1.12k
      bool bof() const { return mPosition <= mBuff;}
112
0
      bool valid() const {return (!eof()) && (!bof());}
113
5.54k
      Pointer start() const { return Pointer(*this, mBuff, eof()); }
114
15.0M
      CurrentPosition position() const { return CurrentPosition(*this); }
115
0
      Pointer end() const { return Pointer(*this, mEnd, true); }
116
0
      size_t lengthRemaining() { return mEnd - mPosition; }
117
118
      CurrentPosition skipChar()
119
3.76M
      {
120
3.76M
         if (eof())
121
114
         {
122
114
            fail(__FILE__, __LINE__,"skipped over eof");
123
114
         }
124
3.76M
         ++mPosition;
125
3.76M
         return CurrentPosition(*this);
126
3.76M
      }
127
128
      CurrentPosition skipChar(char c);
129
      CurrentPosition skipChars(const char* cs);
130
      CurrentPosition skipChars(const Data& cs);
131
      CurrentPosition skipNonWhitespace();
132
      CurrentPosition skipWhitespace();
133
      CurrentPosition skipLWS();
134
      CurrentPosition skipToTermCRLF();
135
      CurrentPosition skipToChar(char c)
136
3.55M
      {
137
3.55M
         mPosition = (const char*)memchr(mPosition, c, mEnd-mPosition);
138
3.55M
         if(!mPosition)
139
12.4k
         {
140
12.4k
            mPosition=mEnd;
141
12.4k
         }
142
3.55M
         return CurrentPosition(*this);
143
3.55M
      }
144
      CurrentPosition skipToChars(const char* cs);
145
      CurrentPosition skipToChars(const Data& cs); // ?dlb? case sensitivity arg?
146
      CurrentPosition skipToOneOf(const char* cs);
147
      CurrentPosition skipToOneOf(const char* cs1, const char* cs2);
148
      CurrentPosition skipToOneOf(const Data& cs);
149
      CurrentPosition skipToOneOf(const Data& cs1, const Data& cs2);
150
151
      // std::bitset based parse function
152
      CurrentPosition skipChars(const std::bitset<256>& cs)
153
0
      {
154
0
         while (mPosition < mEnd)
155
0
         {
156
0
            if (cs.test((unsigned char)(*mPosition)))
157
0
            {
158
0
               mPosition++;
159
0
            }
160
0
            else
161
0
            {
162
0
               return CurrentPosition(*this);
163
0
            }
164
0
         }
165
0
         return CurrentPosition(*this);
166
0
      }
167
168
      CurrentPosition skipToOneOf(const std::bitset<256>& cs)
169
3.74M
      {
170
250M
         while (mPosition < mEnd)
171
250M
         {
172
250M
            if (cs.test((unsigned char)(*mPosition)))
173
3.72M
            {
174
3.72M
               return CurrentPosition(*this);
175
3.72M
            }
176
247M
            else
177
247M
            {
178
247M
               mPosition++;
179
247M
            }
180
250M
         }
181
17.4k
         return CurrentPosition(*this);
182
3.74M
      }
183
184
      const char* skipToEndQuote(char quote = '"');
185
      CurrentPosition skipN(size_t count)
186
6.29k
      {
187
6.29k
         mPosition += count;
188
6.29k
         if (mPosition > mEnd)
189
6.29k
         {
190
6.29k
            fail(__FILE__, __LINE__, "skipped eof");
191
6.29k
         }
192
6.29k
         return CurrentPosition(*this);
193
6.29k
      }
194
195
      CurrentPosition skipToEnd()
196
44.0k
      {
197
44.0k
         mPosition = mEnd;
198
44.0k
         return CurrentPosition(*this);
199
44.0k
      }
200
201
      // inverse of skipChar() -- end up at char not before it
202
      const char* skipBackChar();
203
      const char* skipBackWhitespace();
204
      const char* skipBackN(int count)
205
0
      {
206
0
         mPosition -= count;
207
0
         if (bof())
208
0
         { 
209
0
           fail(__FILE__, __LINE__,"backed over beginning of buffer");
210
0
         }
211
0
         return mPosition;
212
0
      }
213
214
      const char* skipBackChar(char c);
215
      const char* skipBackToChar(char c);
216
      const char* skipBackToOneOf(const char* cs);
217
218
      void assertEof() const
219
2
      {
220
2
         if (!eof())
221
1
         {
222
1
            fail(__FILE__, __LINE__,"expected eof");
223
1
         }
224
2
      }
225
226
      void assertNotEof() const
227
7.87M
      {
228
7.87M
         if (eof())
229
12.3k
         {
230
12.3k
            fail(__FILE__, __LINE__,"unexpected eof");
231
12.3k
         }
232
7.87M
      }
233
234
      void fail(const char* file, unsigned int line,
235
                const Data& errmsg = Data::Empty) const;
236
237
      /// make the passed in data share memory with the buffer (uses Data::Share)
238
      void data(Data& data, const char* start) const;
239
240
      Data data(const char* start) const;
241
242
      void dataUnescaped(Data& data, const char* start) const;      
243
      
244
      int integer();
245
246
      
247
      uint8_t uInt8();
248
      uint32_t uInt32();
249
      uint64_t uInt64();
250
251
0
      RESIP_DEPRECATED(uint64_t unsignedLongLong()){return uInt64();} 
252
0
      RESIP_DEPRECATED(unsigned long unsignedInteger()){return uInt32();}
253
254
#ifndef RESIP_FIXED_POINT   
255
      float floatVal();
256
#endif
257
      int qVal();
258
259
      static bool oneOf(char c, const char* cs);
260
      static bool oneOf(char c, const Data& cs);
261
      static const char* Whitespace;
262
      static const char* ParamTerm;
263
   private:
264
      friend class ParseBuffer::CurrentPosition;
265
      const char* mBuff;
266
      const char* mPosition;
267
      const char* mEnd;
268
      const Data& mErrorContext;
269
};
270
271
}
272
273
#endif
274
275
/* ====================================================================
276
 * The Vovida Software License, Version 1.0 
277
 * 
278
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
279
 * 
280
 * Redistribution and use in source and binary forms, with or without
281
 * modification, are permitted provided that the following conditions
282
 * are met:
283
 * 
284
 * 1. Redistributions of source code must retain the above copyright
285
 *    notice, this list of conditions and the following disclaimer.
286
 * 
287
 * 2. Redistributions in binary form must reproduce the above copyright
288
 *    notice, this list of conditions and the following disclaimer in
289
 *    the documentation and/or other materials provided with the
290
 *    distribution.
291
 * 
292
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
293
 *    and "Vovida Open Communication Application Library (VOCAL)" must
294
 *    not be used to endorse or promote products derived from this
295
 *    software without prior written permission. For written
296
 *    permission, please contact vocal@vovida.org.
297
 *
298
 * 4. Products derived from this software may not be called "VOCAL", nor
299
 *    may "VOCAL" appear in their name, without prior written
300
 *    permission of Vovida Networks, Inc.
301
 * 
302
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
303
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
304
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
305
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
306
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
307
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
308
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
309
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
310
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
311
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
312
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
313
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
314
 * DAMAGE.
315
 * 
316
 * ====================================================================
317
 * 
318
 * This software consists of voluntary contributions made by Vovida
319
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
320
 * Inc.  For more information on Vovida Networks, Inc., please see
321
 * <http://www.vovida.org/>.
322
 *
323
 */