Coverage Report

Created: 2026-02-09 07:07

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