Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/media_params.c
Line
Count
Source
1
/* media_params.c
2
 * Routines for parsing media type parameters as per RFC 822 and RFC 2045
3
 * Copyright 2004, Anders Broman.
4
 * Copyright 2004, Olivier Biot.
5
 *
6
 * Refer to the AUTHORS file or the AUTHORS section in the man page
7
 * for contacting the author(s) of this file.
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <string.h>
19
#include <glib.h>
20
21
#include <epan/media_params.h>
22
23
static const char *
24
ws_get_next_media_type_parameter(const char *pos, size_t *retnamelen,
25
                                 const char **retvalue, size_t *retvaluelen,
26
                                 const char **nextp)
27
0
{
28
0
    const char *p, *namep, *valuep;
29
0
    char c;
30
31
0
    p = pos;
32
0
    while ((c = *p) != '\0' && g_ascii_isspace(c))
33
0
        p++; /* Skip white space */
34
35
0
    if (c == '\0') {
36
        /* No more parameters left */
37
0
        return NULL;
38
0
    }
39
40
0
    namep = p;
41
42
    /* Look for a '\0' (end of string), '=' (end of parameter name,
43
       beginning of parameter value), or ';' (end of parameter). */
44
0
    while ((c = *p) != '\0' && c != '=' && c != ';')
45
0
        p++;
46
0
    *retnamelen = (size_t) (p - namep);
47
0
    if (c == '\0') {
48
        /* End of string, so end of parameter, no parameter value */
49
0
        if (retvalue != NULL)
50
0
            *retvalue = NULL;
51
0
        if (retvaluelen != NULL)
52
0
            *retvaluelen = 0;
53
0
        *nextp = p;
54
0
        return namep;
55
0
    }
56
0
    if (c == ';') {
57
        /* End of parameter, no parameter value */
58
0
        if (retvalue != NULL)
59
0
            *retvalue = NULL;
60
0
        if (retvaluelen != NULL)
61
0
            *retvaluelen = 0;
62
0
        *nextp = p + 1;
63
0
        return namep;
64
0
    }
65
    /* The parameter has a value.  Skip the '=' */
66
0
    p++;
67
0
    valuep = p;
68
0
    if (retvalue != NULL)
69
0
        *retvalue = valuep;
70
    /* Is the value a quoted string? */
71
0
    if (*p == '"') {
72
        /* Yes. Skip the opening quote, and scan forward looking for
73
           a non-escaped closing quote. */
74
0
        p++;
75
0
        for (;;) {
76
0
            c = *p;
77
0
            if (c == '\0') {
78
                /* End-of-string.  We're done.
79
                   (XXX - this is an error.) */
80
0
                if (retvaluelen != NULL) {
81
0
                    *retvaluelen = (size_t) (p - valuep);
82
0
                }
83
0
                *nextp = p;
84
0
                return namep;
85
0
            }
86
0
            if (c == '"') {
87
                /* Closing quote.  Skip it; we're done with
88
                   the quoted-string. */
89
0
                p++;
90
0
                break;
91
0
            }
92
0
            if (c == '\\') {
93
                /* Backslash; this escapes the next character
94
                   (quoted-pair). Skip the backslash, and make
95
                   sure there *is* a next character. */
96
0
                p++;
97
0
                if (*p == '\0') {
98
                    /* Nothing left; we're done.
99
                       (XXX - this is an error.) */
100
0
                    break;
101
0
                }
102
0
            }
103
            /* Skip the character we just processed. */
104
0
            p++;
105
0
        }
106
        /* Now scan forward looking for a '\0' (end of string)
107
           or ';' (end of parameter), in case there's any
108
            extra cruft after the quoted-string. */
109
0
        while ((c = *p) != '\0' && c != ';')
110
0
           p++;
111
0
    } else {
112
        /* No.  Just scan forward looking for a '\0' (end
113
           of string) or ';' (end of parameter). */
114
0
        while ((c = *p) != '\0' && c != ';')
115
0
            p++;
116
0
    }
117
0
    if (c == '\0') {
118
        /* End of string, so end of parameter */
119
0
        if (retvaluelen != NULL) {
120
0
            *retvaluelen = (size_t) (p - valuep);
121
0
        }
122
0
        *nextp = p;
123
0
        return namep;
124
0
    }
125
    /* End of parameter; point past the terminating ';' */
126
0
    if (retvaluelen != NULL) {
127
0
        *retvaluelen = (size_t) (p - valuep);
128
0
    }
129
0
    *nextp = p + 1;
130
0
    return namep;
131
0
}
132
133
char *
134
ws_find_media_type_parameter(wmem_allocator_t *scope, const char *parameters, const char *key)
135
0
{
136
0
    const char *p, *name, *value;
137
0
    char c;
138
0
    size_t keylen, namelen, valuelen;
139
0
    char *valuestr, *vp;
140
141
0
    if (parameters == NULL || key == NULL)
142
        /* we won't be able to find anything */
143
0
        return NULL;
144
145
0
    keylen = (size_t) strlen(key);
146
0
    if (keylen == 0) {
147
        /* There's no parameter name to search for */
148
0
        return NULL;
149
0
    }
150
0
    p = parameters;
151
0
    if (*p == '\0') {
152
        /* There are no parameters in which to search */
153
0
        return NULL;
154
0
    }
155
156
0
    do {
157
        /* Get the next parameter. */
158
0
        name = ws_get_next_media_type_parameter(p, &namelen, &value,
159
0
                                                &valuelen, &p);
160
0
        if (name == NULL) {
161
            /* No more parameters - not found. */
162
0
            return NULL;
163
0
        }
164
165
        /* Is it the parameter we're looking for? */
166
0
        if (namelen == keylen && g_ascii_strncasecmp(name, key, keylen) == 0) {
167
            /* Yes. */
168
0
            break;
169
0
        }
170
0
    } while (*p);
171
172
0
    if (value == NULL) {
173
        /* The parameter doesn't have a value. */
174
0
        return NULL;
175
0
    }
176
177
    /* We found the parameter with that name; now extract the value. */
178
0
    valuestr = (char *)wmem_alloc(scope, valuelen + 1);
179
0
    vp = valuestr;
180
0
    p = value;
181
    /* Is the value a quoted string? */
182
0
    if (*p == '"') {
183
        /* Yes. Skip the opening quote, and scan forward looking for
184
           a non-escaped closing quote, copying characters. */
185
0
        p++;
186
0
        for (;;) {
187
0
            c = *p;
188
0
            if (c == '\0') {
189
                /* End-of-string.  We're done.
190
                   (XXX - this is an error.) */
191
0
                *vp = '\0';
192
0
                return valuestr;
193
0
            }
194
0
            if (c == '"') {
195
                /* Closing quote.  Skip it; we're done with
196
                   the quoted-string. */
197
0
                p++;
198
0
                break;
199
0
            }
200
0
            if (c == '\\') {
201
                /* Backslash; this escapes the next character
202
                   (quoted-pair). Skip the backslash, and make
203
                   sure there *is* a next character. */
204
0
                p++;
205
0
                if (*p == '\0') {
206
                    /* Nothing left; we're done.
207
                       (XXX - this is an error.) */
208
0
                    break;
209
0
                }
210
0
            }
211
            /* Copy the character. */
212
0
            *vp++ = *p++;
213
0
        }
214
0
    } else {
215
        /* No.  Just scan forward until we see a '\0' (end of
216
           string or a non-token character, copying characters. */
217
0
        while ((c = *p) != '\0' && g_ascii_isgraph(c) && c != '(' &&
218
0
                c != ')' && c != '<' && c != '>' && c != '@' &&
219
0
                c != ',' && c != ';' && c != ':' && c != '\\' &&
220
0
                c != '"' && c != '/' && c != '[' && c != ']' &&
221
0
                c != '?' && c != '=' && c != '{' && c != '}') {
222
0
            *vp++ = c;
223
0
            p++;
224
0
        }
225
0
    }
226
0
    *vp = '\0';
227
0
    return valuestr;
228
0
}