Coverage Report

Created: 2025-07-23 06:33

/src/php-src/ext/uri/uriparser/src/UriNormalize.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * uriparser - RFC 3986 URI parsing library
3
 *
4
 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5
 * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source  and binary forms, with or without
9
 * modification, are permitted provided  that the following conditions
10
 * are met:
11
 *
12
 *     1. Redistributions  of  source  code   must  retain  the  above
13
 *        copyright notice, this list  of conditions and the following
14
 *        disclaimer.
15
 *
16
 *     2. Redistributions  in binary  form  must  reproduce the  above
17
 *        copyright notice, this list  of conditions and the following
18
 *        disclaimer  in  the  documentation  and/or  other  materials
19
 *        provided with the distribution.
20
 *
21
 *     3. Neither the  name of the  copyright holder nor the  names of
22
 *        its contributors may be used  to endorse or promote products
23
 *        derived from  this software  without specific  prior written
24
 *        permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND  ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT
28
 * LIMITED TO,  THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS
29
 * FOR  A  PARTICULAR  PURPOSE  ARE  DISCLAIMED.  IN  NO  EVENT  SHALL
30
 * THE  COPYRIGHT HOLDER  OR CONTRIBUTORS  BE LIABLE  FOR ANY  DIRECT,
31
 * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32
 * (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS OR
33
 * SERVICES; LOSS OF USE, DATA,  OR PROFITS; OR BUSINESS INTERRUPTION)
34
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35
 * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
36
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37
 * OF THE POSSIBILITY OF SUCH DAMAGE.
38
 */
39
40
/**
41
 * @file UriNormalize.c
42
 * Holds the RFC 3986 %URI normalization implementation.
43
 * NOTE: This source file includes itself twice.
44
 */
45
46
/* What encodings are enabled? */
47
#include <uriparser/UriDefsConfig.h>
48
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
49
/* Include SELF twice */
50
# ifdef URI_ENABLE_ANSI
51
#  define URI_PASS_ANSI 1
52
#  include "UriNormalize.c"
53
#  undef URI_PASS_ANSI
54
# endif
55
# ifdef URI_ENABLE_UNICODE
56
#  define URI_PASS_UNICODE 1
57
#  include "UriNormalize.c"
58
#  undef URI_PASS_UNICODE
59
# endif
60
#else
61
# ifdef URI_PASS_ANSI
62
#  include <uriparser/UriDefsAnsi.h>
63
# else
64
#  include <uriparser/UriDefsUnicode.h>
65
#  include <wchar.h>
66
# endif
67
68
69
70
#ifndef URI_DOXYGEN
71
# include <uriparser/Uri.h>
72
# include "UriNormalizeBase.h"
73
# include "UriCommon.h"
74
# include "UriMemory.h"
75
#endif
76
77
78
79
#include <assert.h>
80
81
82
83
static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask,
84
    unsigned int * outMask, UriMemoryManager * memory);
85
86
static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,
87
    unsigned int maskTest, URI_TYPE(TextRange) * range,
88
    UriMemoryManager * memory);
89
static UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri,
90
    unsigned int * doneMask, UriMemoryManager * memory);
91
92
static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,
93
    const URI_CHAR ** afterLast);
94
static UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,
95
    const URI_CHAR ** afterLast, UriMemoryManager * memory);
96
static void URI_FUNC(FixPercentEncodingEngine)(
97
    const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,
98
    const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast);
99
100
static UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,
101
    const URI_CHAR * afterLast);
102
static UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,
103
    const URI_CHAR * afterLast);
104
105
static void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,
106
    const URI_CHAR * afterLast);
107
static void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first,
108
    const URI_CHAR * afterLast);
109
static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
110
    const URI_CHAR ** afterLast, UriMemoryManager * memory);
111
112
113
114
void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,
115
0
    unsigned int revertMask, UriMemoryManager * memory) {
116
0
  if (revertMask & URI_NORMALIZE_SCHEME) {
117
    /* NOTE: A scheme cannot be the empty string
118
     *       so no need to compare .first with .afterLast, here. */
119
0
    memory->free(memory, (URI_CHAR *)uri->scheme.first);
120
0
    uri->scheme.first = NULL;
121
0
    uri->scheme.afterLast = NULL;
122
0
  }
123
124
0
  if (revertMask & URI_NORMALIZE_USER_INFO) {
125
0
    if (uri->userInfo.first != uri->userInfo.afterLast) {
126
0
      memory->free(memory, (URI_CHAR *)uri->userInfo.first);
127
0
    }
128
0
    uri->userInfo.first = NULL;
129
0
    uri->userInfo.afterLast = NULL;
130
0
  }
131
132
0
  if (revertMask & URI_NORMALIZE_HOST) {
133
0
    if (uri->hostData.ipFuture.first != NULL) {
134
      /* IPvFuture */
135
      /* NOTE: An IPvFuture address cannot be the empty string
136
       *       so no need to compare .first with .afterLast, here. */
137
0
      memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first);
138
0
      uri->hostData.ipFuture.first = NULL;
139
0
      uri->hostData.ipFuture.afterLast = NULL;
140
0
      uri->hostText.first = NULL;
141
0
      uri->hostText.afterLast = NULL;
142
0
    } else if (uri->hostText.first != NULL) {
143
      /* Regname */
144
0
      if (uri->hostText.first != uri->hostText.afterLast) {
145
0
        memory->free(memory, (URI_CHAR *)uri->hostText.first);
146
0
      }
147
0
      uri->hostText.first = NULL;
148
0
      uri->hostText.afterLast = NULL;
149
0
    }
150
0
  }
151
152
  /* NOTE: Port cannot happen! */
153
154
0
  if (revertMask & URI_NORMALIZE_PATH) {
155
0
    URI_TYPE(PathSegment) * walker = uri->pathHead;
156
0
    while (walker != NULL) {
157
0
      URI_TYPE(PathSegment) * const next = walker->next;
158
0
      if (walker->text.afterLast > walker->text.first) {
159
0
        memory->free(memory, (URI_CHAR *)walker->text.first);
160
0
      }
161
0
      memory->free(memory, walker);
162
0
      walker = next;
163
0
    }
164
0
    uri->pathHead = NULL;
165
0
    uri->pathTail = NULL;
166
0
  }
167
168
0
  if (revertMask & URI_NORMALIZE_QUERY) {
169
0
    if (uri->query.first != uri->query.afterLast) {
170
0
      memory->free(memory, (URI_CHAR *)uri->query.first);
171
0
    }
172
0
    uri->query.first = NULL;
173
0
    uri->query.afterLast = NULL;
174
0
  }
175
176
0
  if (revertMask & URI_NORMALIZE_FRAGMENT) {
177
0
    if (uri->fragment.first != uri->fragment.afterLast) {
178
0
      memory->free(memory, (URI_CHAR *)uri->fragment.first);
179
0
    }
180
0
    uri->fragment.first = NULL;
181
0
    uri->fragment.afterLast = NULL;
182
0
  }
183
0
}
Unexecuted instantiation: uriPreventLeakageA
Unexecuted instantiation: uriPreventLeakageW
184
185
186
187
static URI_INLINE UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,
188
0
    const URI_CHAR * afterLast) {
189
0
  if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
190
0
    const URI_CHAR * i = first;
191
0
    for (; i < afterLast; i++) {
192
      /* 6.2.2.1 Case Normalization: uppercase letters in scheme or host */
193
0
      if ((*i >= _UT('A')) && (*i <= _UT('Z'))) {
194
0
        return URI_TRUE;
195
0
      }
196
0
    }
197
0
  }
198
0
  return URI_FALSE;
199
0
}
Unexecuted instantiation: UriNormalize.c:uriContainsUppercaseLettersA
Unexecuted instantiation: UriNormalize.c:uriContainsUppercaseLettersW
200
201
202
203
static URI_INLINE UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,
204
0
    const URI_CHAR * afterLast) {
205
0
  if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
206
0
    const URI_CHAR * i = first;
207
0
    for (; i + 2 < afterLast; i++) {
208
0
      if (i[0] == _UT('%')) {
209
        /* 6.2.2.1 Case Normalization: *
210
         * lowercase percent-encodings */
211
0
        if (((i[1] >= _UT('a')) && (i[1] <= _UT('f')))
212
0
            || ((i[2] >= _UT('a')) && (i[2] <= _UT('f')))) {
213
0
          return URI_TRUE;
214
0
        } else {
215
          /* 6.2.2.2 Percent-Encoding Normalization: *
216
           * percent-encoded unreserved characters   */
217
0
          const unsigned char left = URI_FUNC(HexdigToInt)(i[1]);
218
0
          const unsigned char right = URI_FUNC(HexdigToInt)(i[2]);
219
0
          const int code = 16 * left + right;
220
0
          if (uriIsUnreserved(code)) {
221
0
            return URI_TRUE;
222
0
          }
223
0
        }
224
0
      }
225
0
    }
226
0
  }
227
0
  return URI_FALSE;
228
0
}
Unexecuted instantiation: UriNormalize.c:uriContainsUglyPercentEncodingA
Unexecuted instantiation: UriNormalize.c:uriContainsUglyPercentEncodingW
229
230
231
232
static URI_INLINE void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,
233
0
    const URI_CHAR * afterLast) {
234
0
  if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
235
0
    URI_CHAR * i = (URI_CHAR *)first;
236
0
    const int lowerUpperDiff = (_UT('a') - _UT('A'));
237
0
    for (; i < afterLast; i++) {
238
0
      if ((*i >= _UT('A')) && (*i <=_UT('Z'))) {
239
0
        *i = (URI_CHAR)(*i + lowerUpperDiff);
240
0
      }
241
0
    }
242
0
  }
243
0
}
Unexecuted instantiation: UriNormalize.c:uriLowercaseInplaceA
Unexecuted instantiation: UriNormalize.c:uriLowercaseInplaceW
244
245
246
247
static URI_INLINE void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first,
248
0
    const URI_CHAR * afterLast) {
249
0
  if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
250
0
    URI_CHAR * i = (URI_CHAR *)first;
251
0
    const int lowerUpperDiff = (_UT('a') - _UT('A'));
252
0
    for (; i < afterLast; i++) {
253
0
      if ((*i >= _UT('A')) && (*i <=_UT('Z'))) {
254
0
        *i = (URI_CHAR)(*i + lowerUpperDiff);
255
0
      } else if (*i == _UT('%')) {
256
0
        if (i + 3 >= afterLast) {
257
0
          return;
258
0
        }
259
0
        i += 2;
260
0
      }
261
0
    }
262
0
  }
263
0
}
Unexecuted instantiation: UriNormalize.c:uriLowercaseInplaceExceptPercentEncodingA
Unexecuted instantiation: UriNormalize.c:uriLowercaseInplaceExceptPercentEncodingW
264
265
266
267
static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
268
0
    const URI_CHAR ** afterLast, UriMemoryManager * memory) {
269
0
  int lenInChars;
270
0
  const int lowerUpperDiff = (_UT('a') - _UT('A'));
271
0
  URI_CHAR * buffer;
272
0
  int i = 0;
273
274
0
  if ((first == NULL) || (afterLast == NULL) || (*first == NULL)
275
0
      || (*afterLast == NULL)) {
276
0
    return URI_FALSE;
277
0
  }
278
279
0
  lenInChars = (int)(*afterLast - *first);
280
0
  if (lenInChars == 0) {
281
0
    return URI_TRUE;
282
0
  } else if (lenInChars < 0) {
283
0
    return URI_FALSE;
284
0
  }
285
286
0
  buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));
287
0
  if (buffer == NULL) {
288
0
    return URI_FALSE;
289
0
  }
290
291
0
  for (; i < lenInChars; i++) {
292
0
    if (((*first)[i] >= _UT('A')) && ((*first)[i] <=_UT('Z'))) {
293
0
      buffer[i] = (URI_CHAR)((*first)[i] + lowerUpperDiff);
294
0
    } else {
295
0
      buffer[i] = (*first)[i];
296
0
    }
297
0
  }
298
299
0
  *first = buffer;
300
0
  *afterLast = buffer + lenInChars;
301
0
  return URI_TRUE;
302
0
}
Unexecuted instantiation: UriNormalize.c:uriLowercaseMallocA
Unexecuted instantiation: UriNormalize.c:uriLowercaseMallocW
303
304
305
306
/* NOTE: Implementation must stay inplace-compatible */
307
static URI_INLINE void URI_FUNC(FixPercentEncodingEngine)(
308
    const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,
309
0
    const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast) {
310
0
  URI_CHAR * write = (URI_CHAR *)outFirst;
311
0
  const int lenInChars = (int)(inAfterLast - inFirst);
312
0
  int i = 0;
313
314
  /* All but last two */
315
0
  for (; i + 2 < lenInChars; i++) {
316
0
    if (inFirst[i] != _UT('%')) {
317
0
      write[0] = inFirst[i];
318
0
      write++;
319
0
    } else {
320
      /* 6.2.2.2 Percent-Encoding Normalization: *
321
       * percent-encoded unreserved characters   */
322
0
      const URI_CHAR one = inFirst[i + 1];
323
0
      const URI_CHAR two = inFirst[i + 2];
324
0
      const unsigned char left = URI_FUNC(HexdigToInt)(one);
325
0
      const unsigned char right = URI_FUNC(HexdigToInt)(two);
326
0
      const int code = 16 * left + right;
327
0
      if (uriIsUnreserved(code)) {
328
0
        write[0] = (URI_CHAR)(code);
329
0
        write++;
330
0
      } else {
331
        /* 6.2.2.1 Case Normalization: *
332
         * lowercase percent-encodings */
333
0
        write[0] = _UT('%');
334
0
        write[1] = URI_FUNC(HexToLetter)(left);
335
0
        write[2] = URI_FUNC(HexToLetter)(right);
336
0
        write += 3;
337
0
      }
338
339
0
      i += 2; /* For the two chars of the percent group we just ate */
340
0
    }
341
0
  }
342
343
  /* Last two */
344
0
  for (; i < lenInChars; i++) {
345
0
    write[0] = inFirst[i];
346
0
    write++;
347
0
  }
348
349
0
  *outAfterLast = write;
350
0
}
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingEngineA
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingEngineW
351
352
353
354
static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,
355
0
    const URI_CHAR ** afterLast) {
356
  /* Death checks */
357
0
  if ((first == NULL) || (afterLast == NULL) || (*afterLast == NULL)) {
358
0
    return;
359
0
  }
360
361
  /* Fix inplace */
362
0
  URI_FUNC(FixPercentEncodingEngine)(first, *afterLast, first, afterLast);
363
0
}
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingInplaceA
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingInplaceW
364
365
366
367
static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,
368
0
    const URI_CHAR ** afterLast, UriMemoryManager * memory) {
369
0
  int lenInChars;
370
0
  URI_CHAR * buffer;
371
372
  /* Death checks */
373
0
  if ((first == NULL) || (afterLast == NULL)
374
0
      || (*first == NULL) || (*afterLast == NULL)) {
375
0
    return URI_FALSE;
376
0
  }
377
378
  /* Old text length */
379
0
  lenInChars = (int)(*afterLast - *first);
380
0
  if (lenInChars == 0) {
381
0
    return URI_TRUE;
382
0
  } else if (lenInChars < 0) {
383
0
    return URI_FALSE;
384
0
  }
385
386
  /* New buffer */
387
0
  buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));
388
0
  if (buffer == NULL) {
389
0
    return URI_FALSE;
390
0
  }
391
392
  /* Fix on copy */
393
0
  URI_FUNC(FixPercentEncodingEngine)(*first, *afterLast, buffer, afterLast);
394
0
  *first = buffer;
395
0
  return URI_TRUE;
396
0
}
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingMallocA
Unexecuted instantiation: UriNormalize.c:uriFixPercentEncodingMallocW
397
398
399
400
static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,
401
    unsigned int maskTest, URI_TYPE(TextRange) * range,
402
0
    UriMemoryManager * memory) {
403
0
  if (((*doneMask & maskTest) == 0)
404
0
      && (range->first != NULL)
405
0
      && (range->afterLast != NULL)
406
0
      && (range->afterLast > range->first)) {
407
0
    if (URI_FUNC(CopyRange)(range, range, memory) == URI_FALSE) {
408
0
      return URI_FALSE;
409
0
    }
410
0
    *doneMask |= maskTest;
411
0
  }
412
0
  return URI_TRUE;
413
0
}
Unexecuted instantiation: UriNormalize.c:uriMakeRangeOwnerA
Unexecuted instantiation: UriNormalize.c:uriMakeRangeOwnerW
414
415
416
417
static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri,
418
0
    unsigned int * doneMask, UriMemoryManager * memory) {
419
0
  URI_TYPE(PathSegment) * walker = uri->pathHead;
420
0
  if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME,
421
0
        &(uri->scheme), memory)
422
0
      || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO,
423
0
        &(uri->userInfo), memory)
424
0
      || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY,
425
0
        &(uri->query), memory)
426
0
      || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT,
427
0
        &(uri->fragment), memory)) {
428
0
    return URI_FALSE; /* Raises malloc error */
429
0
  }
430
431
  /* Host */
432
0
  if ((*doneMask & URI_NORMALIZE_HOST) == 0) {
433
0
    if (uri->hostData.ipFuture.first != NULL) {
434
      /* IPvFuture */
435
0
      if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,
436
0
          &(uri->hostData.ipFuture), memory)) {
437
0
        return URI_FALSE; /* Raises malloc error */
438
0
      }
439
0
      uri->hostText.first = uri->hostData.ipFuture.first;
440
0
      uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;
441
0
    } else if (uri->hostText.first != NULL) {
442
      /* Regname */
443
0
      if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,
444
0
          &(uri->hostText), memory)) {
445
0
        return URI_FALSE; /* Raises malloc error */
446
0
      }
447
0
    }
448
0
  }
449
450
  /* Path */
451
0
  if ((*doneMask & URI_NORMALIZE_PATH) == 0) {
452
0
    while (walker != NULL) {
453
0
      if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text), memory)) {
454
        /* Free allocations done so far and kill path */
455
456
        /* Kill path to one before walker (if any) */
457
0
        URI_TYPE(PathSegment) * ranger = uri->pathHead;
458
0
        while (ranger != walker) {
459
0
          URI_TYPE(PathSegment) * const next = ranger->next;
460
0
          if ((ranger->text.first != NULL)
461
0
              && (ranger->text.afterLast != NULL)
462
0
              && (ranger->text.afterLast > ranger->text.first)) {
463
0
            memory->free(memory, (URI_CHAR *)ranger->text.first);
464
0
          }
465
0
          memory->free(memory, ranger);
466
0
          ranger = next;
467
0
        }
468
469
        /* Kill path from walker */
470
0
        while (walker != NULL) {
471
0
          URI_TYPE(PathSegment) * const next = walker->next;
472
0
          memory->free(memory, walker);
473
0
          walker = next;
474
0
        }
475
476
0
        uri->pathHead = NULL;
477
0
        uri->pathTail = NULL;
478
0
        return URI_FALSE; /* Raises malloc error */
479
0
      }
480
0
      walker = walker->next;
481
0
    }
482
0
    *doneMask |= URI_NORMALIZE_PATH;
483
0
  }
484
485
  /* Port text, must come last so we don't have to undo that one if it fails. *
486
   * Otherwise we would need and extra enum flag for it although the port      *
487
   * cannot go unnormalized...                                                */
488
0
  if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->portText), memory)) {
489
0
    return URI_FALSE; /* Raises malloc error */
490
0
  }
491
492
0
  return URI_TRUE;
493
0
}
Unexecuted instantiation: UriNormalize.c:uriMakeOwnerEngineA
Unexecuted instantiation: UriNormalize.c:uriMakeOwnerEngineW
494
495
496
497
0
unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) {
498
0
  unsigned int outMask = URI_NORMALIZED;  /* for NULL uri */
499
0
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(uri, &outMask);
500
0
  return outMask;
501
0
}
Unexecuted instantiation: uriNormalizeSyntaxMaskRequiredA
Unexecuted instantiation: uriNormalizeSyntaxMaskRequiredW
502
503
504
505
int URI_FUNC(NormalizeSyntaxMaskRequiredEx)(const URI_TYPE(Uri) * uri,
506
0
    unsigned int * outMask) {
507
0
  UriMemoryManager * const memory = NULL;  /* no use of memory manager */
508
509
0
#if defined(__GNUC__) && ((__GNUC__ > 4) \
510
0
    || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2)))
511
  /* Slower code that fixes a warning, not sure if this is a smart idea */
512
0
  URI_TYPE(Uri) writeableClone;
513
0
#endif
514
515
0
  if ((uri == NULL) || (outMask == NULL)) {
516
0
    return URI_ERROR_NULL;
517
0
  }
518
519
0
#if defined(__GNUC__) && ((__GNUC__ > 4) \
520
0
    || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2)))
521
  /* Slower code that fixes a warning, not sure if this is a smart idea */
522
0
  memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri)));
523
0
  URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, outMask, memory);
524
#else
525
  URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, outMask, memory);
526
#endif
527
0
  return URI_SUCCESS;
528
0
}
Unexecuted instantiation: uriNormalizeSyntaxMaskRequiredExA
Unexecuted instantiation: uriNormalizeSyntaxMaskRequiredExW
529
530
531
532
0
int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) {
533
0
  return URI_FUNC(NormalizeSyntaxExMm)(uri, mask, NULL);
534
0
}
Unexecuted instantiation: uriNormalizeSyntaxExA
Unexecuted instantiation: uriNormalizeSyntaxExW
535
536
537
538
int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, unsigned int mask,
539
0
    UriMemoryManager * memory) {
540
0
  URI_CHECK_MEMORY_MANAGER(memory);  /* may return */
541
0
  return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL, memory);
542
0
}
Unexecuted instantiation: uriNormalizeSyntaxExMmA
Unexecuted instantiation: uriNormalizeSyntaxExMmW
543
544
545
546
0
int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) {
547
0
  return URI_FUNC(NormalizeSyntaxEx)(uri, (unsigned int)-1);
548
0
}
Unexecuted instantiation: uriNormalizeSyntaxA
Unexecuted instantiation: uriNormalizeSyntaxW
549
550
551
0
static const URI_CHAR * URI_FUNC(PastLeadingZeros)(const URI_CHAR * first, const URI_CHAR * afterLast) {
552
0
  assert(first != NULL);
553
0
  assert(afterLast != NULL);
554
0
  assert(first != afterLast);
555
556
0
  { 
557
    /* Find the first non-zero character */
558
0
    const URI_CHAR * remainderFirst = first;
559
0
    while ((remainderFirst < afterLast) && (remainderFirst[0] == _UT('0'))) {
560
0
      remainderFirst++;
561
0
    }
562
563
    /* Is the string /all/ zeros? */
564
0
    if (remainderFirst == afterLast) {
565
      /* Yes, and length is >=1 because we ruled out the empty string earlier;
566
       * pull back onto rightmost zero */
567
0
      assert(remainderFirst > first);
568
0
      remainderFirst--;
569
0
      assert(remainderFirst[0] == _UT('0'));
570
0
    }
571
572
0
    return remainderFirst;
573
0
  }
574
0
}
Unexecuted instantiation: UriNormalize.c:uriPastLeadingZerosA
Unexecuted instantiation: UriNormalize.c:uriPastLeadingZerosW
575
576
577
578
0
static void URI_FUNC(DropLeadingZerosInplace)(URI_CHAR * first, const URI_CHAR ** afterLast) {
579
0
  assert(first != NULL);
580
0
  assert(afterLast != NULL);
581
0
  assert(*afterLast != NULL);
582
583
0
  if (first == *afterLast) {
584
0
    return;
585
0
  }
586
587
0
  {
588
0
    const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(first, *afterLast);
589
590
0
    if (remainderFirst > first) {
591
0
      const size_t remainderLen = *afterLast - remainderFirst;
592
0
      memmove(first, remainderFirst, remainderLen * sizeof(URI_CHAR));
593
0
      first[remainderLen] = _UT('\0');
594
0
      *afterLast = first + remainderLen;
595
0
    }
596
0
  }
597
0
}
Unexecuted instantiation: UriNormalize.c:uriDropLeadingZerosInplaceA
Unexecuted instantiation: UriNormalize.c:uriDropLeadingZerosInplaceW
598
599
600
601
static void URI_FUNC(AdvancePastLeadingZeros)(
602
0
    const URI_CHAR ** first, const URI_CHAR * afterLast) {
603
0
  assert(first != NULL);
604
0
  assert(*first != NULL);
605
0
  assert(afterLast != NULL);
606
607
0
  if (*first == afterLast) {
608
0
    return;
609
0
  }
610
611
0
  {
612
0
    const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(*first, afterLast);
613
614
    /* Cut off leading zeros */
615
0
    *first = remainderFirst;
616
0
  }
617
0
}
Unexecuted instantiation: UriNormalize.c:uriAdvancePastLeadingZerosA
Unexecuted instantiation: UriNormalize.c:uriAdvancePastLeadingZerosW
618
619
620
621
static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri,
622
    unsigned int inMask, unsigned int * outMask,
623
0
    UriMemoryManager * memory) {
624
0
  unsigned int doneMask = URI_NORMALIZED;
625
626
  /* Not just doing inspection? -> memory manager required! */
627
0
  if (outMask == NULL) {
628
0
    assert(memory != NULL);
629
0
  }
630
631
0
  if (uri == NULL) {
632
0
    if (outMask != NULL) {
633
0
      *outMask = URI_NORMALIZED;
634
0
      return URI_SUCCESS;
635
0
    } else {
636
0
      return URI_ERROR_NULL;
637
0
    }
638
0
  }
639
640
0
  if (outMask != NULL) {
641
    /* Reset mask */
642
0
    *outMask = URI_NORMALIZED;
643
0
  } else if (inMask == URI_NORMALIZED) {
644
    /* Nothing to do */
645
0
    return URI_SUCCESS;
646
0
  }
647
648
  /* Scheme, host */
649
0
  if (outMask != NULL) {
650
0
    const UriBool normalizeScheme = URI_FUNC(ContainsUppercaseLetters)(
651
0
        uri->scheme.first, uri->scheme.afterLast);
652
0
    const UriBool normalizeHostCase = URI_FUNC(ContainsUppercaseLetters)(
653
0
      uri->hostText.first, uri->hostText.afterLast);
654
0
    if (normalizeScheme) {
655
0
      *outMask |= URI_NORMALIZE_SCHEME;
656
0
    }
657
658
0
    if (normalizeHostCase) {
659
0
      *outMask |= URI_NORMALIZE_HOST;
660
0
    } else {
661
0
      const UriBool normalizeHostPrecent = URI_FUNC(ContainsUglyPercentEncoding)(
662
0
          uri->hostText.first, uri->hostText.afterLast);
663
0
      if (normalizeHostPrecent) {
664
0
        *outMask |= URI_NORMALIZE_HOST;
665
0
      }
666
0
    }
667
0
  } else {
668
    /* Scheme */
669
0
    if ((inMask & URI_NORMALIZE_SCHEME) && (uri->scheme.first != NULL)) {
670
0
      if (uri->owner) {
671
0
        URI_FUNC(LowercaseInplace)(uri->scheme.first, uri->scheme.afterLast);
672
0
      } else {
673
0
        if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast), memory)) {
674
0
          URI_FUNC(PreventLeakage)(uri, doneMask, memory);
675
0
          return URI_ERROR_MALLOC;
676
0
        }
677
0
        doneMask |= URI_NORMALIZE_SCHEME;
678
0
      }
679
0
    }
680
681
    /* Host */
682
0
    if (inMask & URI_NORMALIZE_HOST) {
683
0
      if (uri->hostData.ipFuture.first != NULL) {
684
        /* IPvFuture */
685
0
        if (uri->owner) {
686
0
          URI_FUNC(LowercaseInplace)(uri->hostData.ipFuture.first,
687
0
              uri->hostData.ipFuture.afterLast);
688
0
        } else {
689
0
          if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first),
690
0
              &(uri->hostData.ipFuture.afterLast), memory)) {
691
0
            URI_FUNC(PreventLeakage)(uri, doneMask, memory);
692
0
            return URI_ERROR_MALLOC;
693
0
          }
694
0
          doneMask |= URI_NORMALIZE_HOST;
695
0
        }
696
0
        uri->hostText.first = uri->hostData.ipFuture.first;
697
0
        uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;
698
0
      } else if ((uri->hostText.first != NULL)
699
0
          && (uri->hostData.ip4 == NULL)) {
700
        /* Regname or IPv6 */
701
0
        if (uri->owner) {
702
0
          URI_FUNC(FixPercentEncodingInplace)(uri->hostText.first,
703
0
              &(uri->hostText.afterLast));
704
0
        } else {
705
0
          if (!URI_FUNC(FixPercentEncodingMalloc)(
706
0
              &(uri->hostText.first),
707
0
              &(uri->hostText.afterLast),
708
0
              memory)) {
709
0
            URI_FUNC(PreventLeakage)(uri, doneMask, memory);
710
0
            return URI_ERROR_MALLOC;
711
0
          }
712
0
          doneMask |= URI_NORMALIZE_HOST;
713
0
        }
714
715
0
        URI_FUNC(LowercaseInplaceExceptPercentEncoding)(uri->hostText.first,
716
0
            uri->hostText.afterLast);
717
0
      }
718
0
    }
719
0
  }
720
721
  /* Port */
722
0
  if (outMask != NULL) {
723
    /* Is there a port even? */
724
0
    if (uri->portText.first != NULL) {
725
      /* Determine whether the port is already normalized, i.e. either "", "0" or no leading zeros */
726
0
      const size_t portLen = uri->portText.afterLast - uri->portText.first;
727
0
      if ((portLen > 1) && (uri->portText.first[0] == _UT('0'))) {
728
0
        *outMask |= URI_NORMALIZE_PORT;
729
0
      }
730
0
    }
731
0
  } else {
732
    /* Normalize the port, i.e. drop leading zeros (except for string "0") */
733
0
    if ((inMask & URI_NORMALIZE_PORT) && (uri->portText.first != NULL)) {
734
0
      if (uri->owner) {
735
0
        URI_FUNC(DropLeadingZerosInplace)((URI_CHAR *)uri->portText.first, &(uri->portText.afterLast));
736
0
      } else {
737
0
        URI_FUNC(AdvancePastLeadingZeros)(&(uri->portText.first), uri->portText.afterLast);
738
0
      }
739
0
    }
740
0
  }
741
742
  /* User info */
743
0
  if (outMask != NULL) {
744
0
    const UriBool normalizeUserInfo = URI_FUNC(ContainsUglyPercentEncoding)(
745
0
      uri->userInfo.first, uri->userInfo.afterLast);
746
0
    if (normalizeUserInfo) {
747
0
      *outMask |= URI_NORMALIZE_USER_INFO;
748
0
    }
749
0
  } else {
750
0
    if ((inMask & URI_NORMALIZE_USER_INFO) && (uri->userInfo.first != NULL)) {
751
0
      if (uri->owner) {
752
0
        URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, &(uri->userInfo.afterLast));
753
0
      } else {
754
0
        if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first),
755
0
            &(uri->userInfo.afterLast), memory)) {
756
0
          URI_FUNC(PreventLeakage)(uri, doneMask, memory);
757
0
          return URI_ERROR_MALLOC;
758
0
        }
759
0
        doneMask |= URI_NORMALIZE_USER_INFO;
760
0
      }
761
0
    }
762
0
  }
763
764
  /* Path */
765
0
  if (outMask != NULL) {
766
0
    const URI_TYPE(PathSegment) * walker = uri->pathHead;
767
0
    while (walker != NULL) {
768
0
      const URI_CHAR * const first = walker->text.first;
769
0
      const URI_CHAR * const afterLast = walker->text.afterLast;
770
0
      if ((first != NULL)
771
0
          && (afterLast != NULL)
772
0
          && (afterLast > first)
773
0
          && (
774
0
            (((afterLast - first) == 1)
775
0
              && (first[0] == _UT('.')))
776
0
            ||
777
0
            (((afterLast - first) == 2)
778
0
              && (first[0] == _UT('.'))
779
0
              && (first[1] == _UT('.')))
780
0
            ||
781
0
            URI_FUNC(ContainsUglyPercentEncoding)(first, afterLast)
782
0
          )) {
783
0
        *outMask |= URI_NORMALIZE_PATH;
784
0
        break;
785
0
      }
786
0
      walker = walker->next;
787
0
    }
788
0
  } else if (inMask & URI_NORMALIZE_PATH) {
789
0
    URI_TYPE(PathSegment) * walker;
790
0
    const UriBool relative = ((uri->scheme.first == NULL)
791
0
        && !uri->absolutePath) ? URI_TRUE : URI_FALSE;
792
793
    /* Fix percent-encoding for each segment */
794
0
    walker = uri->pathHead;
795
0
    if (uri->owner) {
796
0
      while (walker != NULL) {
797
0
        URI_FUNC(FixPercentEncodingInplace)(walker->text.first, &(walker->text.afterLast));
798
0
        walker = walker->next;
799
0
      }
800
0
    } else {
801
0
      while (walker != NULL) {
802
0
        if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first),
803
0
            &(walker->text.afterLast), memory)) {
804
0
          URI_FUNC(PreventLeakage)(uri, doneMask, memory);
805
0
          return URI_ERROR_MALLOC;
806
0
        }
807
0
        walker = walker->next;
808
0
      }
809
0
      doneMask |= URI_NORMALIZE_PATH;
810
0
    }
811
812
    /* 6.2.2.3 Path Segment Normalization */
813
0
    if (!URI_FUNC(RemoveDotSegmentsEx)(uri, relative,
814
0
        (uri->owner == URI_TRUE)
815
0
        || ((doneMask & URI_NORMALIZE_PATH) != 0),
816
0
        memory)) {
817
0
      URI_FUNC(PreventLeakage)(uri, doneMask, memory);
818
0
      return URI_ERROR_MALLOC;
819
0
    }
820
0
    URI_FUNC(FixEmptyTrailSegment)(uri, memory);
821
0
  }
822
823
  /* Query, fragment */
824
0
  if (outMask != NULL) {
825
0
    const UriBool normalizeQuery = URI_FUNC(ContainsUglyPercentEncoding)(
826
0
        uri->query.first, uri->query.afterLast);
827
0
    const UriBool normalizeFragment = URI_FUNC(ContainsUglyPercentEncoding)(
828
0
        uri->fragment.first, uri->fragment.afterLast);
829
0
    if (normalizeQuery) {
830
0
      *outMask |= URI_NORMALIZE_QUERY;
831
0
    }
832
833
0
    if (normalizeFragment) {
834
0
      *outMask |= URI_NORMALIZE_FRAGMENT;
835
0
    }
836
0
  } else {
837
    /* Query */
838
0
    if ((inMask & URI_NORMALIZE_QUERY) && (uri->query.first != NULL)) {
839
0
      if (uri->owner) {
840
0
        URI_FUNC(FixPercentEncodingInplace)(uri->query.first, &(uri->query.afterLast));
841
0
      } else {
842
0
        if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first),
843
0
            &(uri->query.afterLast), memory)) {
844
0
          URI_FUNC(PreventLeakage)(uri, doneMask, memory);
845
0
          return URI_ERROR_MALLOC;
846
0
        }
847
0
        doneMask |= URI_NORMALIZE_QUERY;
848
0
      }
849
0
    }
850
851
    /* Fragment */
852
0
    if ((inMask & URI_NORMALIZE_FRAGMENT) && (uri->fragment.first != NULL)) {
853
0
      if (uri->owner) {
854
0
        URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, &(uri->fragment.afterLast));
855
0
      } else {
856
0
        if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first),
857
0
            &(uri->fragment.afterLast), memory)) {
858
0
          URI_FUNC(PreventLeakage)(uri, doneMask, memory);
859
0
          return URI_ERROR_MALLOC;
860
0
        }
861
0
        doneMask |= URI_NORMALIZE_FRAGMENT;
862
0
      }
863
0
    }
864
0
  }
865
866
  /* Dup all not duped yet */
867
0
  if ((outMask == NULL) && !uri->owner) {
868
0
    if (!URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) {
869
0
      URI_FUNC(PreventLeakage)(uri, doneMask, memory);
870
0
      return URI_ERROR_MALLOC;
871
0
    }
872
0
    uri->owner = URI_TRUE;
873
0
  }
874
875
0
  return URI_SUCCESS;
876
0
}
Unexecuted instantiation: UriNormalize.c:uriNormalizeSyntaxEngineA
Unexecuted instantiation: UriNormalize.c:uriNormalizeSyntaxEngineW
877
878
879
880
0
int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
881
0
  unsigned int doneMask = URI_NORMALIZED;
882
883
0
  URI_CHECK_MEMORY_MANAGER(memory);  /* may return */
884
885
0
  if (uri == NULL) {
886
0
    return URI_ERROR_NULL;
887
0
  }
888
889
0
  if (uri->owner == URI_TRUE) {
890
0
    return URI_SUCCESS;
891
0
  }
892
893
0
  if (! URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) {
894
0
    URI_FUNC(PreventLeakage)(uri, doneMask, memory);
895
0
    return URI_ERROR_MALLOC;
896
0
  }
897
898
0
  uri->owner = URI_TRUE;
899
900
0
  return URI_SUCCESS;
901
0
}
Unexecuted instantiation: uriMakeOwnerMmA
Unexecuted instantiation: uriMakeOwnerMmW
902
903
904
905
0
int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri) {
906
0
  return URI_FUNC(MakeOwnerMm)(uri, NULL);
907
0
}
Unexecuted instantiation: uriMakeOwnerA
Unexecuted instantiation: uriMakeOwnerW
908
909
910
911
#endif