Coverage Report

Created: 2025-12-21 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/uriparser/src/UriCommon.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
/* What encodings are enabled? */
41
#include <uriparser/UriDefsConfig.h>
42
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
43
/* Include SELF twice */
44
#  ifdef URI_ENABLE_ANSI
45
#    define URI_PASS_ANSI 1
46
#    include "UriCommon.c"
47
#    undef URI_PASS_ANSI
48
#  endif
49
#  ifdef URI_ENABLE_UNICODE
50
#    define URI_PASS_UNICODE 1
51
#    include "UriCommon.c"
52
#    undef URI_PASS_UNICODE
53
#  endif
54
#else
55
#  ifdef URI_PASS_ANSI
56
#    include <uriparser/UriDefsAnsi.h>
57
#  else
58
#    include <uriparser/UriDefsUnicode.h>
59
#    include <wchar.h>
60
#  endif
61
62
#  ifndef URI_DOXYGEN
63
#    include <uriparser/Uri.h>
64
#    include "UriCommon.h"
65
#    include "UriSets.h"
66
#  endif
67
68
#  include <assert.h>
69
70
/*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X");
71
/*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT(".");
72
/*extern*/ const URI_CHAR * const URI_FUNC(ConstParent) = _UT("..");
73
74
31.7k
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
75
31.7k
    if (uri == NULL) {
76
0
        return;
77
0
    }
78
31.7k
    memset(uri, 0, sizeof(URI_TYPE(Uri)));
79
31.7k
}
Unexecuted instantiation: uriResetUriA
uriResetUriW
Line
Count
Source
74
31.7k
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
75
31.7k
    if (uri == NULL) {
76
0
        return;
77
0
    }
78
31.7k
    memset(uri, 0, sizeof(URI_TYPE(Uri)));
79
31.7k
}
80
81
51.0k
int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
82
51.0k
    assert(uri != NULL);
83
51.0k
    assert(memory != NULL);
84
85
51.0k
    if (uri->pathHead != NULL) {
86
5.26k
        URI_TYPE(PathSegment) * segWalk = uri->pathHead;
87
24.4k
        while (segWalk != NULL) {
88
19.1k
            URI_TYPE(PathSegment) * const next = segWalk->next;
89
19.1k
            if ((uri->owner == URI_TRUE)
90
5.03k
                && (segWalk->text.first != segWalk->text.afterLast)) {
91
3.40k
                memory->free(memory, (URI_CHAR *)segWalk->text.first);
92
3.40k
            }
93
19.1k
            segWalk->text.first = NULL;
94
19.1k
            segWalk->text.afterLast = NULL;
95
19.1k
            segWalk->next = NULL;
96
19.1k
            memory->free(memory, segWalk);
97
19.1k
            segWalk = next;
98
19.1k
        }
99
5.26k
        uri->pathHead = NULL;
100
5.26k
        uri->pathTail = NULL;
101
5.26k
    }
102
103
51.0k
    return URI_SUCCESS;
104
51.0k
}
Unexecuted instantiation: uriFreeUriPathA
uriFreeUriPathW
Line
Count
Source
81
51.0k
int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
82
51.0k
    assert(uri != NULL);
83
51.0k
    assert(memory != NULL);
84
85
51.0k
    if (uri->pathHead != NULL) {
86
5.26k
        URI_TYPE(PathSegment) * segWalk = uri->pathHead;
87
24.4k
        while (segWalk != NULL) {
88
19.1k
            URI_TYPE(PathSegment) * const next = segWalk->next;
89
19.1k
            if ((uri->owner == URI_TRUE)
90
5.03k
                && (segWalk->text.first != segWalk->text.afterLast)) {
91
3.40k
                memory->free(memory, (URI_CHAR *)segWalk->text.first);
92
3.40k
            }
93
19.1k
            segWalk->text.first = NULL;
94
19.1k
            segWalk->text.afterLast = NULL;
95
19.1k
            segWalk->next = NULL;
96
19.1k
            memory->free(memory, segWalk);
97
19.1k
            segWalk = next;
98
19.1k
        }
99
5.26k
        uri->pathHead = NULL;
100
5.26k
        uri->pathTail = NULL;
101
5.26k
    }
102
103
51.0k
    return URI_SUCCESS;
104
51.0k
}
105
106
/* Compares two text ranges for equal text content */
107
21.2k
int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) {
108
21.2k
    int diff;
109
110
    /* NOTE: Both NULL means equal! */
111
21.2k
    if ((a == NULL) || (b == NULL)) {
112
0
        return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1);
113
0
    }
114
115
    /* NOTE: Both NULL means equal! */
116
21.2k
    if ((a->first == NULL) || (b->first == NULL)) {
117
19.5k
        return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1);
118
19.5k
    }
119
120
1.72k
    diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first));
121
1.72k
    if (diff > 0) {
122
123
        return 1;
123
1.60k
    } else if (diff < 0) {
124
109
        return -1;
125
109
    }
126
127
1.49k
    diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first));
128
129
1.49k
    if (diff > 0) {
130
63
        return 1;
131
1.43k
    } else if (diff < 0) {
132
47
        return -1;
133
47
    }
134
135
1.38k
    return diff;
136
1.49k
}
Unexecuted instantiation: uriCompareRangeA
uriCompareRangeW
Line
Count
Source
107
21.2k
int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) {
108
21.2k
    int diff;
109
110
    /* NOTE: Both NULL means equal! */
111
21.2k
    if ((a == NULL) || (b == NULL)) {
112
0
        return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1);
113
0
    }
114
115
    /* NOTE: Both NULL means equal! */
116
21.2k
    if ((a->first == NULL) || (b->first == NULL)) {
117
19.5k
        return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1);
118
19.5k
    }
119
120
1.72k
    diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first));
121
1.72k
    if (diff > 0) {
122
123
        return 1;
123
1.60k
    } else if (diff < 0) {
124
109
        return -1;
125
109
    }
126
127
1.49k
    diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first));
128
129
1.49k
    if (diff > 0) {
130
63
        return 1;
131
1.43k
    } else if (diff < 0) {
132
47
        return -1;
133
47
    }
134
135
1.38k
    return diff;
136
1.49k
}
137
138
UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange,
139
                            const URI_TYPE(TextRange) * sourceRange,
140
86
                            UriMemoryManager * memory) {
141
86
    const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first);
142
86
    const int lenInBytes = lenInChars * sizeof(URI_CHAR);
143
86
    URI_CHAR * dup = memory->malloc(memory, lenInBytes);
144
86
    if (dup == NULL) {
145
0
        return URI_FALSE;
146
0
    }
147
86
    memcpy(dup, sourceRange->first, lenInBytes);
148
86
    destRange->first = dup;
149
86
    destRange->afterLast = dup + lenInChars;
150
151
86
    return URI_TRUE;
152
86
}
Unexecuted instantiation: uriCopyRangeA
uriCopyRangeW
Line
Count
Source
140
86
                            UriMemoryManager * memory) {
141
86
    const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first);
142
86
    const int lenInBytes = lenInChars * sizeof(URI_CHAR);
143
86
    URI_CHAR * dup = memory->malloc(memory, lenInBytes);
144
86
    if (dup == NULL) {
145
0
        return URI_FALSE;
146
0
    }
147
86
    memcpy(dup, sourceRange->first, lenInBytes);
148
86
    destRange->first = dup;
149
86
    destRange->afterLast = dup + lenInChars;
150
151
86
    return URI_TRUE;
152
86
}
153
154
UriBool URI_FUNC(CopyRangeAsNeeded)(URI_TYPE(TextRange) * destRange,
155
                                    const URI_TYPE(TextRange) * sourceRange,
156
0
                                    UriMemoryManager * memory) {
157
0
    if (sourceRange->first == NULL) {
158
0
        destRange->first = NULL;
159
0
        destRange->afterLast = NULL;
160
0
    } else if (sourceRange->first == sourceRange->afterLast) {
161
0
        destRange->first = URI_FUNC(SafeToPointTo);
162
0
        destRange->afterLast = URI_FUNC(SafeToPointTo);
163
0
    } else {
164
0
        return URI_FUNC(CopyRange)(destRange, sourceRange, memory);
165
0
    }
166
167
0
    return URI_TRUE;
168
0
}
Unexecuted instantiation: uriCopyRangeAsNeededA
Unexecuted instantiation: uriCopyRangeAsNeededW
169
170
UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative,
171
6.27k
                                      UriBool pathOwned, UriMemoryManager * memory) {
172
6.27k
    URI_TYPE(PathSegment) * walker;
173
6.27k
    if ((uri == NULL) || (uri->pathHead == NULL)) {
174
4.74k
        return URI_TRUE;
175
4.74k
    }
176
177
1.53k
    walker = uri->pathHead;
178
1.53k
    walker->reserved = NULL; /* Prev pointer */
179
14.2k
    do {
180
14.2k
        UriBool removeSegment = URI_FALSE;
181
14.2k
        int len = (int)(walker->text.afterLast - walker->text.first);
182
14.2k
        switch (len) {
183
3.81k
        case 1:
184
3.81k
            if ((walker->text.first)[0] == _UT('.')) {
185
                /* "." segment -> remove if not essential */
186
2.14k
                URI_TYPE(PathSegment) * const prev = walker->reserved;
187
2.14k
                URI_TYPE(PathSegment) * const nextBackup = walker->next;
188
189
                /*
190
                 * Is this dot segment essential,
191
                 * i.e. is there a chance of changing semantics by dropping this dot
192
                 * segment?
193
                 *
194
                 * For example, changing "./http://foo" into "http://foo" would change
195
                 * semantics and hence the dot segment is essential to that case and
196
                 * cannot be removed.
197
                 *
198
                 * Other examples that would change semantics are:
199
                 * - cutting "/.//" down to "//"
200
                 * - cutting "scheme:/.//" down to "scheme://".
201
                 */
202
2.14k
                removeSegment = URI_TRUE;
203
2.14k
                if ((walker == uri->pathHead) && (walker->next != NULL)) {
204
                    /* Detect case "/.//" (with or without scheme) */
205
1.21k
                    if ((walker->next->text.first == walker->next->text.afterLast)
206
279
                        && (URI_FUNC(HasHost)(uri) == URI_FALSE)) {
207
83
                        removeSegment = URI_FALSE;
208
                        /* Detect case "./withcolon:" */
209
1.12k
                    } else if (relative) {
210
488
                        const URI_CHAR * ch = walker->next->text.first;
211
1.27k
                        for (; ch < walker->next->text.afterLast; ch++) {
212
984
                            if (*ch == _UT(':')) {
213
195
                                removeSegment = URI_FALSE;
214
195
                                break;
215
195
                            }
216
984
                        }
217
488
                    }
218
1.21k
                }
219
220
2.14k
                if (removeSegment) {
221
                    /* .. then let's go remove that segment. */
222
                    /* Last segment? */
223
1.86k
                    if (walker->next != NULL) {
224
                        /* Not last segment, i.e. first or middle segment
225
                         * OLD: (prev|NULL) <- walker <- next
226
                         * NEW: (prev|NULL) <----------- next */
227
1.83k
                        walker->next->reserved = prev;
228
229
1.83k
                        if (prev == NULL) {
230
                            /* First but not last segment
231
                             * OLD: head -> walker -> next
232
                             * NEW: head -----------> next */
233
934
                            uri->pathHead = walker->next;
234
934
                        } else {
235
                            /* Middle segment
236
                             * OLD: prev -> walker -> next
237
                             * NEW: prev -----------> next */
238
901
                            prev->next = walker->next;
239
901
                        }
240
241
1.83k
                        if (pathOwned && (walker->text.first != walker->text.afterLast)) {
242
1.20k
                            memory->free(memory, (URI_CHAR *)walker->text.first);
243
1.20k
                        }
244
1.83k
                        memory->free(memory, walker);
245
1.83k
                    } else {
246
                        /* Last segment */
247
32
                        if (pathOwned && (walker->text.first != walker->text.afterLast)) {
248
32
                            memory->free(memory, (URI_CHAR *)walker->text.first);
249
32
                        }
250
251
32
                        if (prev == NULL) {
252
                            /* Last and first */
253
16
                            if (URI_FUNC(HasHost)(uri)) {
254
                                /* Replace "." with empty segment to represent trailing
255
                                 * slash */
256
1
                                walker->text.first = URI_FUNC(SafeToPointTo);
257
1
                                walker->text.afterLast = URI_FUNC(SafeToPointTo);
258
15
                            } else {
259
15
                                memory->free(memory, walker);
260
261
15
                                uri->pathHead = NULL;
262
15
                                uri->pathTail = NULL;
263
15
                            }
264
16
                        } else {
265
                            /* Last but not first, replace "." with empty segment to
266
                             * represent trailing slash */
267
16
                            walker->text.first = URI_FUNC(SafeToPointTo);
268
16
                            walker->text.afterLast = URI_FUNC(SafeToPointTo);
269
16
                        }
270
32
                    }
271
272
1.86k
                    walker = nextBackup;
273
1.86k
                }
274
2.14k
            }
275
3.81k
            break;
276
277
5.06k
        case 2:
278
5.06k
            if (((walker->text.first)[0] == _UT('.'))
279
4.14k
                && ((walker->text.first)[1] == _UT('.'))) {
280
                /* Path ".." -> remove this and the previous segment */
281
3.63k
                URI_TYPE(PathSegment) * const prev = walker->reserved;
282
3.63k
                URI_TYPE(PathSegment) * prevPrev;
283
3.63k
                URI_TYPE(PathSegment) * const nextBackup = walker->next;
284
285
3.63k
                removeSegment = URI_TRUE;
286
3.63k
                if (relative) {
287
1.84k
                    if (prev == NULL) {
288
                        /* We cannot remove traversal beyond because the
289
                         * URI is relative and may be resolved later.
290
                         * So we can simplify "a/../b/d" to "b/d" but
291
                         * we cannot simplify "../b/d" (outside of reference resolution).
292
                         */
293
29
                        removeSegment = URI_FALSE;
294
1.82k
                    } else if ((prev != NULL)
295
1.82k
                               && ((prev->text.afterLast - prev->text.first) == 2)
296
697
                               && ((prev->text.first)[0] == _UT('.'))
297
437
                               && ((prev->text.first)[1] == _UT('.'))) {
298
                        /* We need to protect against mis-simplifying "a/../../b" to
299
                         * "a/b". */
300
204
                        removeSegment = URI_FALSE;
301
204
                    }
302
1.84k
                }
303
304
3.63k
                if (removeSegment) {
305
3.40k
                    if (prev != NULL) {
306
                        /* Not first segment */
307
2.82k
                        prevPrev = prev->reserved;
308
2.82k
                        if (prevPrev != NULL) {
309
                            /* Not even prev is the first one
310
                             * OLD: prevPrev -> prev -> walker -> (next|NULL)
311
                             * NEW: prevPrev -------------------> (next|NULL) */
312
1.65k
                            prevPrev->next = walker->next;
313
1.65k
                            if (walker->next != NULL) {
314
                                /* Update parent relationship as well
315
                                 * OLD: prevPrev <- prev <- walker <- next
316
                                 * NEW: prevPrev <------------------- next */
317
1.63k
                                walker->next->reserved = prevPrev;
318
1.63k
                            } else {
319
                                /* Last segment -> insert "" segment to represent trailing
320
                                 * slash, update tail */
321
16
                                URI_TYPE(PathSegment) * const segment = memory->calloc(
322
16
                                    memory, 1, sizeof(URI_TYPE(PathSegment)));
323
16
                                if (segment == NULL) {
324
0
                                    if (pathOwned
325
0
                                        && (walker->text.first
326
0
                                            != walker->text.afterLast)) {
327
0
                                        memory->free(memory,
328
0
                                                     (URI_CHAR *)walker->text.first);
329
0
                                    }
330
0
                                    memory->free(memory, walker);
331
332
0
                                    if (pathOwned
333
0
                                        && (prev->text.first != prev->text.afterLast)) {
334
0
                                        memory->free(memory,
335
0
                                                     (URI_CHAR *)prev->text.first);
336
0
                                    }
337
0
                                    memory->free(memory, prev);
338
339
0
                                    return URI_FALSE; /* Raises malloc error */
340
0
                                }
341
16
                                segment->text.first = URI_FUNC(SafeToPointTo);
342
16
                                segment->text.afterLast = URI_FUNC(SafeToPointTo);
343
16
                                prevPrev->next = segment;
344
16
                                uri->pathTail = segment;
345
16
                            }
346
347
1.65k
                            if (pathOwned
348
1.34k
                                && (walker->text.first != walker->text.afterLast)) {
349
1.34k
                                memory->free(memory, (URI_CHAR *)walker->text.first);
350
1.34k
                            }
351
1.65k
                            memory->free(memory, walker);
352
353
1.65k
                            if (pathOwned && (prev->text.first != prev->text.afterLast)) {
354
814
                                memory->free(memory, (URI_CHAR *)prev->text.first);
355
814
                            }
356
1.65k
                            memory->free(memory, prev);
357
358
1.65k
                            walker = nextBackup;
359
1.65k
                        } else {
360
                            /* Prev is the first segment */
361
1.16k
                            if (walker->next != NULL) {
362
1.13k
                                uri->pathHead = walker->next;
363
1.13k
                                walker->next->reserved = NULL;
364
365
1.13k
                                if (pathOwned
366
619
                                    && (walker->text.first != walker->text.afterLast)) {
367
619
                                    memory->free(memory, (URI_CHAR *)walker->text.first);
368
619
                                }
369
1.13k
                                memory->free(memory, walker);
370
1.13k
                            } else {
371
                                /* Reuse segment for "" path segment to represent trailing
372
                                 * slash, update tail */
373
37
                                URI_TYPE(PathSegment) * const segment = walker;
374
37
                                if (pathOwned
375
33
                                    && (segment->text.first != segment->text.afterLast)) {
376
33
                                    memory->free(memory, (URI_CHAR *)segment->text.first);
377
33
                                }
378
37
                                segment->text.first = URI_FUNC(SafeToPointTo);
379
37
                                segment->text.afterLast = URI_FUNC(SafeToPointTo);
380
37
                                uri->pathHead = segment;
381
37
                                uri->pathTail = segment;
382
37
                            }
383
384
1.16k
                            if (pathOwned && (prev->text.first != prev->text.afterLast)) {
385
547
                                memory->free(memory, (URI_CHAR *)prev->text.first);
386
547
                            }
387
1.16k
                            memory->free(memory, prev);
388
389
1.16k
                            walker = nextBackup;
390
1.16k
                        }
391
2.82k
                    } else {
392
579
                        URI_TYPE(PathSegment) * const anotherNextBackup = walker->next;
393
579
                        int freeWalker = URI_TRUE;
394
395
                        /* First segment */
396
579
                        if (walker->next != NULL) {
397
                            /* First segment of multiple -> update head
398
                             * OLD: head -> walker -> next
399
                             * NEW: head -----------> next */
400
570
                            uri->pathHead = walker->next;
401
402
                            /* Update parent link as well
403
                             * OLD: head <- walker <- next
404
                             * NEW: head <----------- next */
405
570
                            walker->next->reserved = NULL;
406
570
                        } else {
407
9
                            if (uri->absolutePath) {
408
                                /* First and only segment -> update head
409
                                 * OLD: head -> walker -> NULL
410
                                 * NEW: head -----------> NULL */
411
7
                                uri->pathHead = NULL;
412
413
                                /* Last segment -> update tail
414
                                 * OLD: tail -> walker
415
                                 * NEW: tail -> NULL */
416
7
                                uri->pathTail = NULL;
417
7
                            } else {
418
                                /* Reuse segment for "" path segment to represent trailing
419
                                 * slash, then update head and tail */
420
2
                                if (pathOwned
421
1
                                    && (walker->text.first != walker->text.afterLast)) {
422
1
                                    memory->free(memory, (URI_CHAR *)walker->text.first);
423
1
                                }
424
2
                                walker->text.first = URI_FUNC(SafeToPointTo);
425
2
                                walker->text.afterLast = URI_FUNC(SafeToPointTo);
426
2
                                freeWalker = URI_FALSE;
427
2
                            }
428
9
                        }
429
430
579
                        if (freeWalker) {
431
577
                            if (pathOwned
432
295
                                && (walker->text.first != walker->text.afterLast)) {
433
295
                                memory->free(memory, (URI_CHAR *)walker->text.first);
434
295
                            }
435
577
                            memory->free(memory, walker);
436
577
                        }
437
438
579
                        walker = anotherNextBackup;
439
579
                    }
440
3.40k
                }
441
3.63k
            }
442
5.06k
            break;
443
14.2k
        } /* end of switch */
444
445
14.2k
        if (!removeSegment) {
446
            /* .. then let's move to the next element, and start again. */
447
8.99k
            if (walker->next != NULL) {
448
7.55k
                walker->next->reserved = walker;
449
7.55k
            } else {
450
                /* Last segment -> update tail */
451
1.43k
                uri->pathTail = walker;
452
1.43k
            }
453
8.99k
            walker = walker->next;
454
8.99k
        }
455
14.2k
    } while (walker != NULL);
456
457
1.53k
    return URI_TRUE;
458
1.53k
}
Unexecuted instantiation: uriRemoveDotSegmentsExA
uriRemoveDotSegmentsExW
Line
Count
Source
171
6.27k
                                      UriBool pathOwned, UriMemoryManager * memory) {
172
6.27k
    URI_TYPE(PathSegment) * walker;
173
6.27k
    if ((uri == NULL) || (uri->pathHead == NULL)) {
174
4.74k
        return URI_TRUE;
175
4.74k
    }
176
177
1.53k
    walker = uri->pathHead;
178
1.53k
    walker->reserved = NULL; /* Prev pointer */
179
14.2k
    do {
180
14.2k
        UriBool removeSegment = URI_FALSE;
181
14.2k
        int len = (int)(walker->text.afterLast - walker->text.first);
182
14.2k
        switch (len) {
183
3.81k
        case 1:
184
3.81k
            if ((walker->text.first)[0] == _UT('.')) {
185
                /* "." segment -> remove if not essential */
186
2.14k
                URI_TYPE(PathSegment) * const prev = walker->reserved;
187
2.14k
                URI_TYPE(PathSegment) * const nextBackup = walker->next;
188
189
                /*
190
                 * Is this dot segment essential,
191
                 * i.e. is there a chance of changing semantics by dropping this dot
192
                 * segment?
193
                 *
194
                 * For example, changing "./http://foo" into "http://foo" would change
195
                 * semantics and hence the dot segment is essential to that case and
196
                 * cannot be removed.
197
                 *
198
                 * Other examples that would change semantics are:
199
                 * - cutting "/.//" down to "//"
200
                 * - cutting "scheme:/.//" down to "scheme://".
201
                 */
202
2.14k
                removeSegment = URI_TRUE;
203
2.14k
                if ((walker == uri->pathHead) && (walker->next != NULL)) {
204
                    /* Detect case "/.//" (with or without scheme) */
205
1.21k
                    if ((walker->next->text.first == walker->next->text.afterLast)
206
279
                        && (URI_FUNC(HasHost)(uri) == URI_FALSE)) {
207
83
                        removeSegment = URI_FALSE;
208
                        /* Detect case "./withcolon:" */
209
1.12k
                    } else if (relative) {
210
488
                        const URI_CHAR * ch = walker->next->text.first;
211
1.27k
                        for (; ch < walker->next->text.afterLast; ch++) {
212
984
                            if (*ch == _UT(':')) {
213
195
                                removeSegment = URI_FALSE;
214
195
                                break;
215
195
                            }
216
984
                        }
217
488
                    }
218
1.21k
                }
219
220
2.14k
                if (removeSegment) {
221
                    /* .. then let's go remove that segment. */
222
                    /* Last segment? */
223
1.86k
                    if (walker->next != NULL) {
224
                        /* Not last segment, i.e. first or middle segment
225
                         * OLD: (prev|NULL) <- walker <- next
226
                         * NEW: (prev|NULL) <----------- next */
227
1.83k
                        walker->next->reserved = prev;
228
229
1.83k
                        if (prev == NULL) {
230
                            /* First but not last segment
231
                             * OLD: head -> walker -> next
232
                             * NEW: head -----------> next */
233
934
                            uri->pathHead = walker->next;
234
934
                        } else {
235
                            /* Middle segment
236
                             * OLD: prev -> walker -> next
237
                             * NEW: prev -----------> next */
238
901
                            prev->next = walker->next;
239
901
                        }
240
241
1.83k
                        if (pathOwned && (walker->text.first != walker->text.afterLast)) {
242
1.20k
                            memory->free(memory, (URI_CHAR *)walker->text.first);
243
1.20k
                        }
244
1.83k
                        memory->free(memory, walker);
245
1.83k
                    } else {
246
                        /* Last segment */
247
32
                        if (pathOwned && (walker->text.first != walker->text.afterLast)) {
248
32
                            memory->free(memory, (URI_CHAR *)walker->text.first);
249
32
                        }
250
251
32
                        if (prev == NULL) {
252
                            /* Last and first */
253
16
                            if (URI_FUNC(HasHost)(uri)) {
254
                                /* Replace "." with empty segment to represent trailing
255
                                 * slash */
256
1
                                walker->text.first = URI_FUNC(SafeToPointTo);
257
1
                                walker->text.afterLast = URI_FUNC(SafeToPointTo);
258
15
                            } else {
259
15
                                memory->free(memory, walker);
260
261
15
                                uri->pathHead = NULL;
262
15
                                uri->pathTail = NULL;
263
15
                            }
264
16
                        } else {
265
                            /* Last but not first, replace "." with empty segment to
266
                             * represent trailing slash */
267
16
                            walker->text.first = URI_FUNC(SafeToPointTo);
268
16
                            walker->text.afterLast = URI_FUNC(SafeToPointTo);
269
16
                        }
270
32
                    }
271
272
1.86k
                    walker = nextBackup;
273
1.86k
                }
274
2.14k
            }
275
3.81k
            break;
276
277
5.06k
        case 2:
278
5.06k
            if (((walker->text.first)[0] == _UT('.'))
279
4.14k
                && ((walker->text.first)[1] == _UT('.'))) {
280
                /* Path ".." -> remove this and the previous segment */
281
3.63k
                URI_TYPE(PathSegment) * const prev = walker->reserved;
282
3.63k
                URI_TYPE(PathSegment) * prevPrev;
283
3.63k
                URI_TYPE(PathSegment) * const nextBackup = walker->next;
284
285
3.63k
                removeSegment = URI_TRUE;
286
3.63k
                if (relative) {
287
1.84k
                    if (prev == NULL) {
288
                        /* We cannot remove traversal beyond because the
289
                         * URI is relative and may be resolved later.
290
                         * So we can simplify "a/../b/d" to "b/d" but
291
                         * we cannot simplify "../b/d" (outside of reference resolution).
292
                         */
293
29
                        removeSegment = URI_FALSE;
294
1.82k
                    } else if ((prev != NULL)
295
1.82k
                               && ((prev->text.afterLast - prev->text.first) == 2)
296
697
                               && ((prev->text.first)[0] == _UT('.'))
297
437
                               && ((prev->text.first)[1] == _UT('.'))) {
298
                        /* We need to protect against mis-simplifying "a/../../b" to
299
                         * "a/b". */
300
204
                        removeSegment = URI_FALSE;
301
204
                    }
302
1.84k
                }
303
304
3.63k
                if (removeSegment) {
305
3.40k
                    if (prev != NULL) {
306
                        /* Not first segment */
307
2.82k
                        prevPrev = prev->reserved;
308
2.82k
                        if (prevPrev != NULL) {
309
                            /* Not even prev is the first one
310
                             * OLD: prevPrev -> prev -> walker -> (next|NULL)
311
                             * NEW: prevPrev -------------------> (next|NULL) */
312
1.65k
                            prevPrev->next = walker->next;
313
1.65k
                            if (walker->next != NULL) {
314
                                /* Update parent relationship as well
315
                                 * OLD: prevPrev <- prev <- walker <- next
316
                                 * NEW: prevPrev <------------------- next */
317
1.63k
                                walker->next->reserved = prevPrev;
318
1.63k
                            } else {
319
                                /* Last segment -> insert "" segment to represent trailing
320
                                 * slash, update tail */
321
16
                                URI_TYPE(PathSegment) * const segment = memory->calloc(
322
16
                                    memory, 1, sizeof(URI_TYPE(PathSegment)));
323
16
                                if (segment == NULL) {
324
0
                                    if (pathOwned
325
0
                                        && (walker->text.first
326
0
                                            != walker->text.afterLast)) {
327
0
                                        memory->free(memory,
328
0
                                                     (URI_CHAR *)walker->text.first);
329
0
                                    }
330
0
                                    memory->free(memory, walker);
331
332
0
                                    if (pathOwned
333
0
                                        && (prev->text.first != prev->text.afterLast)) {
334
0
                                        memory->free(memory,
335
0
                                                     (URI_CHAR *)prev->text.first);
336
0
                                    }
337
0
                                    memory->free(memory, prev);
338
339
0
                                    return URI_FALSE; /* Raises malloc error */
340
0
                                }
341
16
                                segment->text.first = URI_FUNC(SafeToPointTo);
342
16
                                segment->text.afterLast = URI_FUNC(SafeToPointTo);
343
16
                                prevPrev->next = segment;
344
16
                                uri->pathTail = segment;
345
16
                            }
346
347
1.65k
                            if (pathOwned
348
1.34k
                                && (walker->text.first != walker->text.afterLast)) {
349
1.34k
                                memory->free(memory, (URI_CHAR *)walker->text.first);
350
1.34k
                            }
351
1.65k
                            memory->free(memory, walker);
352
353
1.65k
                            if (pathOwned && (prev->text.first != prev->text.afterLast)) {
354
814
                                memory->free(memory, (URI_CHAR *)prev->text.first);
355
814
                            }
356
1.65k
                            memory->free(memory, prev);
357
358
1.65k
                            walker = nextBackup;
359
1.65k
                        } else {
360
                            /* Prev is the first segment */
361
1.16k
                            if (walker->next != NULL) {
362
1.13k
                                uri->pathHead = walker->next;
363
1.13k
                                walker->next->reserved = NULL;
364
365
1.13k
                                if (pathOwned
366
619
                                    && (walker->text.first != walker->text.afterLast)) {
367
619
                                    memory->free(memory, (URI_CHAR *)walker->text.first);
368
619
                                }
369
1.13k
                                memory->free(memory, walker);
370
1.13k
                            } else {
371
                                /* Reuse segment for "" path segment to represent trailing
372
                                 * slash, update tail */
373
37
                                URI_TYPE(PathSegment) * const segment = walker;
374
37
                                if (pathOwned
375
33
                                    && (segment->text.first != segment->text.afterLast)) {
376
33
                                    memory->free(memory, (URI_CHAR *)segment->text.first);
377
33
                                }
378
37
                                segment->text.first = URI_FUNC(SafeToPointTo);
379
37
                                segment->text.afterLast = URI_FUNC(SafeToPointTo);
380
37
                                uri->pathHead = segment;
381
37
                                uri->pathTail = segment;
382
37
                            }
383
384
1.16k
                            if (pathOwned && (prev->text.first != prev->text.afterLast)) {
385
547
                                memory->free(memory, (URI_CHAR *)prev->text.first);
386
547
                            }
387
1.16k
                            memory->free(memory, prev);
388
389
1.16k
                            walker = nextBackup;
390
1.16k
                        }
391
2.82k
                    } else {
392
579
                        URI_TYPE(PathSegment) * const anotherNextBackup = walker->next;
393
579
                        int freeWalker = URI_TRUE;
394
395
                        /* First segment */
396
579
                        if (walker->next != NULL) {
397
                            /* First segment of multiple -> update head
398
                             * OLD: head -> walker -> next
399
                             * NEW: head -----------> next */
400
570
                            uri->pathHead = walker->next;
401
402
                            /* Update parent link as well
403
                             * OLD: head <- walker <- next
404
                             * NEW: head <----------- next */
405
570
                            walker->next->reserved = NULL;
406
570
                        } else {
407
9
                            if (uri->absolutePath) {
408
                                /* First and only segment -> update head
409
                                 * OLD: head -> walker -> NULL
410
                                 * NEW: head -----------> NULL */
411
7
                                uri->pathHead = NULL;
412
413
                                /* Last segment -> update tail
414
                                 * OLD: tail -> walker
415
                                 * NEW: tail -> NULL */
416
7
                                uri->pathTail = NULL;
417
7
                            } else {
418
                                /* Reuse segment for "" path segment to represent trailing
419
                                 * slash, then update head and tail */
420
2
                                if (pathOwned
421
1
                                    && (walker->text.first != walker->text.afterLast)) {
422
1
                                    memory->free(memory, (URI_CHAR *)walker->text.first);
423
1
                                }
424
2
                                walker->text.first = URI_FUNC(SafeToPointTo);
425
2
                                walker->text.afterLast = URI_FUNC(SafeToPointTo);
426
2
                                freeWalker = URI_FALSE;
427
2
                            }
428
9
                        }
429
430
579
                        if (freeWalker) {
431
577
                            if (pathOwned
432
295
                                && (walker->text.first != walker->text.afterLast)) {
433
295
                                memory->free(memory, (URI_CHAR *)walker->text.first);
434
295
                            }
435
577
                            memory->free(memory, walker);
436
577
                        }
437
438
579
                        walker = anotherNextBackup;
439
579
                    }
440
3.40k
                }
441
3.63k
            }
442
5.06k
            break;
443
14.2k
        } /* end of switch */
444
445
14.2k
        if (!removeSegment) {
446
            /* .. then let's move to the next element, and start again. */
447
8.99k
            if (walker->next != NULL) {
448
7.55k
                walker->next->reserved = walker;
449
7.55k
            } else {
450
                /* Last segment -> update tail */
451
1.43k
                uri->pathTail = walker;
452
1.43k
            }
453
8.99k
            walker = walker->next;
454
8.99k
        }
455
14.2k
    } while (walker != NULL);
456
457
1.53k
    return URI_TRUE;
458
1.53k
}
459
460
/* Properly removes "." and ".." path segments */
461
UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri,
462
256
                                            UriMemoryManager * memory) {
463
256
    const UriBool ABSOLUTE = URI_FALSE;
464
256
    if (uri == NULL) {
465
0
        return URI_TRUE;
466
0
    }
467
256
    return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory);
468
256
}
Unexecuted instantiation: uriRemoveDotSegmentsAbsoluteA
uriRemoveDotSegmentsAbsoluteW
Line
Count
Source
462
256
                                            UriMemoryManager * memory) {
463
256
    const UriBool ABSOLUTE = URI_FALSE;
464
256
    if (uri == NULL) {
465
0
        return URI_TRUE;
466
0
    }
467
256
    return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory);
468
256
}
469
470
9.44M
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {
471
9.44M
    switch (hexdig) {
472
65.6M
    case URI_SET_DIGIT(_UT):
473
7.65M
        return (unsigned char)(9 + hexdig - _UT('9'));
474
41.4k
    case URI_SET_HEX_LETTER_LOWER(_UT):
475
14.5k
        return (unsigned char)(15 + hexdig - _UT('f'));
476
1.96M
    case URI_SET_HEX_LETTER_UPPER(_UT):
477
1.77M
        return (unsigned char)(15 + hexdig - _UT('F'));
478
479
0
    default:
480
0
        return 0;
481
9.44M
    }
482
9.44M
}
Unexecuted instantiation: uriHexdigToIntA
uriHexdigToIntW
Line
Count
Source
470
9.44M
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {
471
9.44M
    switch (hexdig) {
472
7.65M
    case URI_SET_DIGIT(_UT):
473
7.65M
        return (unsigned char)(9 + hexdig - _UT('9'));
474
14.5k
    case URI_SET_HEX_LETTER_LOWER(_UT):
475
14.5k
        return (unsigned char)(15 + hexdig - _UT('f'));
476
1.77M
    case URI_SET_HEX_LETTER_UPPER(_UT):
477
1.77M
        return (unsigned char)(15 + hexdig - _UT('F'));
478
479
0
    default:
480
0
        return 0;
481
9.44M
    }
482
9.44M
}
483
484
27.3M
URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) {
485
27.3M
    switch (value) {
486
16.2M
    case 0:
487
16.2M
        return _UT('0');
488
237k
    case 1:
489
237k
        return _UT('1');
490
1.34M
    case 2:
491
1.34M
        return _UT('2');
492
2.09M
    case 3:
493
2.09M
        return _UT('3');
494
246k
    case 4:
495
246k
        return _UT('4');
496
748k
    case 5:
497
748k
        return _UT('5');
498
267k
    case 6:
499
267k
        return _UT('6');
500
334k
    case 7:
501
334k
        return _UT('7');
502
267k
    case 8:
503
267k
        return _UT('8');
504
310k
    case 9:
505
310k
        return _UT('9');
506
507
297k
    case 10:
508
297k
        return (uppercase == URI_TRUE) ? _UT('A') : _UT('a');
509
438k
    case 11:
510
438k
        return (uppercase == URI_TRUE) ? _UT('B') : _UT('b');
511
521k
    case 12:
512
521k
        return (uppercase == URI_TRUE) ? _UT('C') : _UT('c');
513
218k
    case 13:
514
218k
        return (uppercase == URI_TRUE) ? _UT('D') : _UT('d');
515
199k
    case 14:
516
199k
        return (uppercase == URI_TRUE) ? _UT('E') : _UT('e');
517
3.55M
    default:
518
3.55M
        return (uppercase == URI_TRUE) ? _UT('F') : _UT('f');
519
27.3M
    }
520
27.3M
}
Unexecuted instantiation: uriHexToLetterExA
uriHexToLetterExW
Line
Count
Source
484
27.3M
URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) {
485
27.3M
    switch (value) {
486
16.2M
    case 0:
487
16.2M
        return _UT('0');
488
237k
    case 1:
489
237k
        return _UT('1');
490
1.34M
    case 2:
491
1.34M
        return _UT('2');
492
2.09M
    case 3:
493
2.09M
        return _UT('3');
494
246k
    case 4:
495
246k
        return _UT('4');
496
748k
    case 5:
497
748k
        return _UT('5');
498
267k
    case 6:
499
267k
        return _UT('6');
500
334k
    case 7:
501
334k
        return _UT('7');
502
267k
    case 8:
503
267k
        return _UT('8');
504
310k
    case 9:
505
310k
        return _UT('9');
506
507
297k
    case 10:
508
297k
        return (uppercase == URI_TRUE) ? _UT('A') : _UT('a');
509
438k
    case 11:
510
438k
        return (uppercase == URI_TRUE) ? _UT('B') : _UT('b');
511
521k
    case 12:
512
521k
        return (uppercase == URI_TRUE) ? _UT('C') : _UT('c');
513
218k
    case 13:
514
218k
        return (uppercase == URI_TRUE) ? _UT('D') : _UT('d');
515
199k
    case 14:
516
199k
        return (uppercase == URI_TRUE) ? _UT('E') : _UT('e');
517
3.55M
    default:
518
3.55M
        return (uppercase == URI_TRUE) ? _UT('F') : _UT('f');
519
27.3M
    }
520
27.3M
}
521
522
/* Checks if a URI has the host component set. */
523
19.9k
UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri) {
524
    /* NOTE: .hostData.ipFuture.first is not being checked,   *
525
     *       because we do check .hostText.first and          *
526
     *       .hostData.ipFuture.first has to be identical to  *
527
     *       .hostText.first if set, and hence there is       *
528
     *       no more information to be gained.                */
529
19.9k
    return (uri != NULL)
530
19.9k
           && ((uri->hostText.first != NULL) || (uri->hostData.ip4 != NULL)
531
15.1k
               || (uri->hostData.ip6 != NULL));
532
19.9k
}
Unexecuted instantiation: uriHasHostA
uriHasHostW
Line
Count
Source
523
19.9k
UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri) {
524
    /* NOTE: .hostData.ipFuture.first is not being checked,   *
525
     *       because we do check .hostText.first and          *
526
     *       .hostData.ipFuture.first has to be identical to  *
527
     *       .hostText.first if set, and hence there is       *
528
     *       no more information to be gained.                */
529
19.9k
    return (uri != NULL)
530
19.9k
           && ((uri->hostText.first != NULL) || (uri->hostData.ip4 != NULL)
531
15.1k
               || (uri->hostData.ip6 != NULL));
532
19.9k
}
533
534
/* Copies the path segment list from one URI to another. */
535
UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source,
536
424
                           UriMemoryManager * memory) {
537
424
    if (source->pathHead == NULL) {
538
        /* No path component */
539
107
        dest->pathHead = NULL;
540
107
        dest->pathTail = NULL;
541
317
    } else {
542
        /* Copy list but not the text contained */
543
317
        URI_TYPE(PathSegment) * sourceWalker = source->pathHead;
544
317
        URI_TYPE(PathSegment) * destPrev = NULL;
545
4.15k
        do {
546
4.15k
            URI_TYPE(PathSegment) * cur =
547
4.15k
                memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
548
4.15k
            if (cur == NULL) {
549
                /* Fix broken list */
550
0
                if (destPrev != NULL) {
551
0
                    destPrev->next = NULL;
552
0
                }
553
0
                return URI_FALSE; /* Raises malloc error */
554
0
            }
555
556
            /* From this functions usage we know that *
557
             * the dest URI cannot be uri->owner      */
558
4.15k
            cur->text = sourceWalker->text;
559
4.15k
            if (destPrev == NULL) {
560
                /* First segment ever */
561
317
                dest->pathHead = cur;
562
3.83k
            } else {
563
3.83k
                destPrev->next = cur;
564
3.83k
            }
565
4.15k
            destPrev = cur;
566
4.15k
            sourceWalker = sourceWalker->next;
567
4.15k
        } while (sourceWalker != NULL);
568
317
        dest->pathTail = destPrev;
569
317
        dest->pathTail->next = NULL;
570
317
    }
571
572
424
    dest->absolutePath = source->absolutePath;
573
424
    return URI_TRUE;
574
424
}
Unexecuted instantiation: uriCopyPathA
uriCopyPathW
Line
Count
Source
536
424
                           UriMemoryManager * memory) {
537
424
    if (source->pathHead == NULL) {
538
        /* No path component */
539
107
        dest->pathHead = NULL;
540
107
        dest->pathTail = NULL;
541
317
    } else {
542
        /* Copy list but not the text contained */
543
317
        URI_TYPE(PathSegment) * sourceWalker = source->pathHead;
544
317
        URI_TYPE(PathSegment) * destPrev = NULL;
545
4.15k
        do {
546
4.15k
            URI_TYPE(PathSegment) * cur =
547
4.15k
                memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
548
4.15k
            if (cur == NULL) {
549
                /* Fix broken list */
550
0
                if (destPrev != NULL) {
551
0
                    destPrev->next = NULL;
552
0
                }
553
0
                return URI_FALSE; /* Raises malloc error */
554
0
            }
555
556
            /* From this functions usage we know that *
557
             * the dest URI cannot be uri->owner      */
558
4.15k
            cur->text = sourceWalker->text;
559
4.15k
            if (destPrev == NULL) {
560
                /* First segment ever */
561
317
                dest->pathHead = cur;
562
3.83k
            } else {
563
3.83k
                destPrev->next = cur;
564
3.83k
            }
565
4.15k
            destPrev = cur;
566
4.15k
            sourceWalker = sourceWalker->next;
567
4.15k
        } while (sourceWalker != NULL);
568
317
        dest->pathTail = destPrev;
569
317
        dest->pathTail->next = NULL;
570
317
    }
571
572
424
    dest->absolutePath = source->absolutePath;
573
424
    return URI_TRUE;
574
424
}
575
576
/* Copies the authority part of an URI over to another. */
577
UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source,
578
412
                                UriMemoryManager * memory) {
579
    /* From this functions usage we know that *
580
     * the dest URI cannot be uri->owner      */
581
582
    /* Copy userInfo */
583
412
    dest->userInfo = source->userInfo;
584
585
    /* Copy hostText */
586
412
    dest->hostText = source->hostText;
587
588
    /* Copy hostData */
589
412
    if (source->hostData.ip4 != NULL) {
590
9
        dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4));
591
9
        if (dest->hostData.ip4 == NULL) {
592
0
            return URI_FALSE; /* Raises malloc error */
593
0
        }
594
9
        *(dest->hostData.ip4) = *(source->hostData.ip4);
595
9
        dest->hostData.ip6 = NULL;
596
9
        dest->hostData.ipFuture.first = NULL;
597
9
        dest->hostData.ipFuture.afterLast = NULL;
598
403
    } else if (source->hostData.ip6 != NULL) {
599
30
        dest->hostData.ip4 = NULL;
600
30
        dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6));
601
30
        if (dest->hostData.ip6 == NULL) {
602
0
            return URI_FALSE; /* Raises malloc error */
603
0
        }
604
30
        *(dest->hostData.ip6) = *(source->hostData.ip6);
605
30
        dest->hostData.ipFuture.first = NULL;
606
30
        dest->hostData.ipFuture.afterLast = NULL;
607
373
    } else {
608
373
        dest->hostData.ip4 = NULL;
609
373
        dest->hostData.ip6 = NULL;
610
373
        dest->hostData.ipFuture = source->hostData.ipFuture;
611
373
    }
612
613
    /* Copy portText */
614
412
    dest->portText = source->portText;
615
616
412
    return URI_TRUE;
617
412
}
Unexecuted instantiation: uriCopyAuthorityA
uriCopyAuthorityW
Line
Count
Source
578
412
                                UriMemoryManager * memory) {
579
    /* From this functions usage we know that *
580
     * the dest URI cannot be uri->owner      */
581
582
    /* Copy userInfo */
583
412
    dest->userInfo = source->userInfo;
584
585
    /* Copy hostText */
586
412
    dest->hostText = source->hostText;
587
588
    /* Copy hostData */
589
412
    if (source->hostData.ip4 != NULL) {
590
9
        dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4));
591
9
        if (dest->hostData.ip4 == NULL) {
592
0
            return URI_FALSE; /* Raises malloc error */
593
0
        }
594
9
        *(dest->hostData.ip4) = *(source->hostData.ip4);
595
9
        dest->hostData.ip6 = NULL;
596
9
        dest->hostData.ipFuture.first = NULL;
597
9
        dest->hostData.ipFuture.afterLast = NULL;
598
403
    } else if (source->hostData.ip6 != NULL) {
599
30
        dest->hostData.ip4 = NULL;
600
30
        dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6));
601
30
        if (dest->hostData.ip6 == NULL) {
602
0
            return URI_FALSE; /* Raises malloc error */
603
0
        }
604
30
        *(dest->hostData.ip6) = *(source->hostData.ip6);
605
30
        dest->hostData.ipFuture.first = NULL;
606
30
        dest->hostData.ipFuture.afterLast = NULL;
607
373
    } else {
608
373
        dest->hostData.ip4 = NULL;
609
373
        dest->hostData.ip6 = NULL;
610
373
        dest->hostData.ipFuture = source->hostData.ipFuture;
611
373
    }
612
613
    /* Copy portText */
614
412
    dest->portText = source->portText;
615
616
412
    return URI_TRUE;
617
412
}
618
619
76
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
620
76
    URI_TYPE(PathSegment) * segment;
621
622
76
    if (/* Case 1: absolute path, empty first segment */
623
76
        (uri->absolutePath && (uri->pathHead != NULL)
624
15
         && (uri->pathHead->text.afterLast == uri->pathHead->text.first))
625
626
        /* Case 2: relative path, empty first and second segment */
627
75
        || (!uri->absolutePath && (uri->pathHead != NULL) && (uri->pathHead->next != NULL)
628
32
            && (uri->pathHead->text.afterLast == uri->pathHead->text.first)
629
4
            && (uri->pathHead->next->text.afterLast
630
4
                == uri->pathHead->next->text.first))) {
631
        /* NOOP */
632
74
    } else {
633
74
        return URI_TRUE;
634
74
    }
635
636
2
    segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));
637
2
    if (segment == NULL) {
638
0
        return URI_FALSE; /* Raises malloc error */
639
0
    }
640
641
    /* Insert "." segment in front */
642
2
    segment->next = uri->pathHead;
643
2
    segment->text.first = URI_FUNC(ConstPwd);
644
2
    segment->text.afterLast = URI_FUNC(ConstPwd) + 1;
645
2
    uri->pathHead = segment;
646
2
    return URI_TRUE;
647
2
}
Unexecuted instantiation: uriFixAmbiguityA
uriFixAmbiguityW
Line
Count
Source
619
76
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
620
76
    URI_TYPE(PathSegment) * segment;
621
622
76
    if (/* Case 1: absolute path, empty first segment */
623
76
        (uri->absolutePath && (uri->pathHead != NULL)
624
15
         && (uri->pathHead->text.afterLast == uri->pathHead->text.first))
625
626
        /* Case 2: relative path, empty first and second segment */
627
75
        || (!uri->absolutePath && (uri->pathHead != NULL) && (uri->pathHead->next != NULL)
628
32
            && (uri->pathHead->text.afterLast == uri->pathHead->text.first)
629
4
            && (uri->pathHead->next->text.afterLast
630
4
                == uri->pathHead->next->text.first))) {
631
        /* NOOP */
632
74
    } else {
633
74
        return URI_TRUE;
634
74
    }
635
636
2
    segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));
637
2
    if (segment == NULL) {
638
0
        return URI_FALSE; /* Raises malloc error */
639
0
    }
640
641
    /* Insert "." segment in front */
642
2
    segment->next = uri->pathHead;
643
2
    segment->text.first = URI_FUNC(ConstPwd);
644
2
    segment->text.afterLast = URI_FUNC(ConstPwd) + 1;
645
2
    uri->pathHead = segment;
646
2
    return URI_TRUE;
647
2
}
648
649
static UriBool URI_FUNC(PrependNewDotSegment)(URI_TYPE(Uri) * uri,
650
0
                                              UriMemoryManager * memory) {
651
0
    assert(uri != NULL);
652
0
    assert(memory != NULL);
653
654
0
    URI_TYPE(PathSegment) * const segment =
655
0
        memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));
656
657
0
    if (segment == NULL) {
658
0
        return URI_FALSE; /* i.e. raise malloc error */
659
0
    }
660
661
0
    segment->next = uri->pathHead;
662
663
0
    URI_TYPE(TextRange) dotRange;
664
0
    dotRange.first = URI_FUNC(ConstPwd);
665
0
    dotRange.afterLast = URI_FUNC(ConstPwd) + 1;
666
667
0
    if (uri->owner == URI_TRUE) {
668
0
        if (URI_FUNC(CopyRange)(&(segment->text), &dotRange, memory) == URI_FALSE) {
669
0
            memory->free(memory, segment);
670
0
            return URI_FALSE; /* i.e. raise malloc error */
671
0
        }
672
0
    } else {
673
0
        segment->text = dotRange; /* copies all members */
674
0
    }
675
676
0
    uri->pathHead = segment;
677
678
0
    return URI_TRUE;
679
0
}
Unexecuted instantiation: UriCommon.c:uriPrependNewDotSegmentA
Unexecuted instantiation: UriCommon.c:uriPrependNewDotSegmentW
680
681
/* When dropping a scheme from a URI without a host and with a colon (":")
682
 * in the first path segment, a consecutive reparse would rightfully
683
 * mis-classify the first path segment as a scheme due to the colon.
684
 * To protect against this case, we prepend an artificial "." segment
685
 * to the path in here; the function is called after the scheme has
686
 * just been dropped.
687
 *
688
 * 0. We start with parsed URI "scheme:path1:/path2/path3".
689
 * 1. We drop the scheme naively and yield "path1:/path2/path3".
690
 * 2. We prepend "." and yield unambiguous "./path1:/path2/path3".
691
 *
692
 * From the view of the RFC 3986 grammar, this is replacing rule path-rootless
693
 * by path-noscheme content.
694
 *
695
 * Returns URI_TRUE for (a) nothing to do or (b) successful changes.
696
 * Returns URI_FALSE to signal out-of-memory.
697
 */
698
0
UriBool URI_FUNC(FixPathNoScheme)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
699
0
    assert(uri != NULL);
700
0
    assert(memory != NULL);
701
702
0
    if ((uri->absolutePath == URI_TRUE) || (uri->pathHead == NULL)
703
0
        || (uri->scheme.first != NULL) || URI_FUNC(HasHost)(uri)) {
704
0
        return URI_TRUE; /* i.e. nothing to do */
705
0
    }
706
707
    /* Check for troublesome first path segment containing a colon */
708
0
    UriBool colonFound = URI_FALSE;
709
0
    const URI_CHAR * walker = uri->pathHead->text.first;
710
711
0
    while (walker < uri->pathHead->text.afterLast) {
712
0
        if (walker[0] == _UT(':')) {
713
0
            colonFound = URI_TRUE;
714
0
            break;
715
0
        }
716
0
        walker++;
717
0
    }
718
719
0
    assert((walker == uri->pathHead->text.afterLast) || (colonFound == URI_TRUE));
720
721
0
    if (colonFound == URI_FALSE) {
722
0
        return URI_TRUE; /* i.e. nothing to do */
723
0
    }
724
725
    /* Insert "." segment in front */
726
0
    return URI_FUNC(PrependNewDotSegment)(uri, memory);
727
0
}
Unexecuted instantiation: uriFixPathNoSchemeA
Unexecuted instantiation: uriFixPathNoSchemeW
728
729
/* When dropping a host from a URI without a scheme, an absolute path
730
 * and and empty first path segment, a consecutive reparse would rightfully
731
 * mis-classify the first path segment as a host marker due to the "//".
732
 * To protect against this case, we prepend an artificial "." segment
733
 * to the path in here; the function is called after the host has
734
 * just been dropped.
735
 *
736
 * 0. We start with parsed URI "//host//path1/path2".
737
 * 1. We drop the host naively and yield "//path1/path2".
738
 * 2. We insert "./" and yield unambiguous "/.//path1/path2".
739
 *
740
 * Returns URI_TRUE for (a) nothing to do or (b) successful changes.
741
 * Returns URI_FALSE to signal out-of-memory.
742
 */
743
UriBool URI_FUNC(EnsureThatPathIsNotMistakenForHost)(URI_TYPE(Uri) * uri,
744
0
                                                     UriMemoryManager * memory) {
745
0
    assert(uri != NULL);
746
0
    assert(memory != NULL);
747
748
0
    if ((URI_FUNC(HasHost)(uri) == URI_TRUE) || (uri->absolutePath == URI_FALSE)
749
0
        || (uri->pathHead == NULL)
750
0
        || (uri->pathHead == uri->pathTail) /* i.e. no second slash */
751
0
        || (uri->pathHead->text.first != uri->pathHead->text.afterLast)) {
752
0
        return URI_TRUE; /* i.e. nothing to do */
753
0
    }
754
755
    /* Insert "." segment in front */
756
0
    return URI_FUNC(PrependNewDotSegment)(uri, memory);
757
0
}
Unexecuted instantiation: uriEnsureThatPathIsNotMistakenForHostA
Unexecuted instantiation: uriEnsureThatPathIsNotMistakenForHostW
758
759
8.97k
void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
760
    /* Fix path if only one empty segment */
761
8.97k
    if (!uri->absolutePath && !URI_FUNC(HasHost)(uri) && (uri->pathHead != NULL)
762
1.15k
        && (uri->pathHead->next == NULL)
763
926
        && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {
764
39
        memory->free(memory, uri->pathHead);
765
39
        uri->pathHead = NULL;
766
        uri->pathTail = NULL;
767
39
    }
768
8.97k
}
Unexecuted instantiation: uriFixEmptyTrailSegmentA
uriFixEmptyTrailSegmentW
Line
Count
Source
759
8.97k
void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
760
    /* Fix path if only one empty segment */
761
8.97k
    if (!uri->absolutePath && !URI_FUNC(HasHost)(uri) && (uri->pathHead != NULL)
762
1.15k
        && (uri->pathHead->next == NULL)
763
926
        && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {
764
39
        memory->free(memory, uri->pathHead);
765
39
        uri->pathHead = NULL;
766
        uri->pathTail = NULL;
767
39
    }
768
8.97k
}
769
770
#endif