Coverage Report

Created: 2023-03-26 06:28

/src/httpd/include/apreq_parser.h
Line
Count
Source
1
/*
2
**  Licensed to the Apache Software Foundation (ASF) under one or more
3
** contributor license agreements.  See the NOTICE file distributed with
4
** this work for additional information regarding copyright ownership.
5
** The ASF licenses this file to You under the Apache License, Version 2.0
6
** (the "License"); you may not use this file except in compliance with
7
** the License.  You may obtain a copy of the License at
8
**
9
**      http://www.apache.org/licenses/LICENSE-2.0
10
**
11
**  Unless required by applicable law or agreed to in writing, software
12
**  distributed under the License is distributed on an "AS IS" BASIS,
13
**  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
**  See the License for the specific language governing permissions and
15
**  limitations under the License.
16
*/
17
18
#ifndef APREQ_PARSERS_H
19
#define APREQ_PARSERS_H
20
/* These structs are defined below */
21
22
#include "apreq_param.h"
23
24
#ifdef __cplusplus
25
extern "C" {
26
#endif /* __cplusplus */
27
28
/**
29
 * @file apreq_parser.h
30
 * @brief Request body parser API
31
 * @ingroup libapreq2
32
 */
33
34
/**
35
 * A hook is called by the parser whenever data arrives in a file
36
 * upload parameter of the request body. You may associate any number
37
 * of hooks with a parser instance with apreq_parser_add_hook().
38
 */
39
typedef struct apreq_hook_t apreq_hook_t;
40
41
/**
42
 * A request body parser instance.
43
 */
44
typedef struct apreq_parser_t apreq_parser_t;
45
46
/** Parser arguments. */
47
#define APREQ_PARSER_ARGS  apreq_parser_t *parser,     \
48
                           apr_table_t *t,             \
49
                           apr_bucket_brigade *bb
50
51
/** Hook arguments */
52
#define APREQ_HOOK_ARGS    apreq_hook_t *hook,         \
53
                           apreq_param_t *param,       \
54
                           apr_bucket_brigade *bb
55
56
/**
57
 * The callback function implementing a request body parser.
58
 */
59
typedef apr_status_t (*apreq_parser_function_t)(APREQ_PARSER_ARGS);
60
61
/**
62
 * The callback function of a hook. See apreq_hook_t.
63
 */
64
typedef apr_status_t (*apreq_hook_function_t)(APREQ_HOOK_ARGS);
65
66
/**
67
 * Declares a API parser.
68
 */
69
#define APREQ_DECLARE_PARSER(f) APREQ_DECLARE_NONSTD(apr_status_t) \
70
                                f (APREQ_PARSER_ARGS)
71
72
/**
73
 * Declares an API hook.
74
 */
75
#define APREQ_DECLARE_HOOK(f)   APREQ_DECLARE_NONSTD(apr_status_t) \
76
                                f (APREQ_HOOK_ARGS)
77
78
/**
79
 * A hook is called by the parser whenever data arrives in a file
80
 * upload parameter of the request body. You may associate any number
81
 * of hooks with a parser instance with apreq_parser_add_hook().
82
 */
83
struct apreq_hook_t {
84
    apreq_hook_function_t hook; /**< the hook function */
85
    apreq_hook_t         *next; /**< next item in the linked list */
86
    apr_pool_t           *pool; /**< pool which allocated this hook */
87
    void *ctx; /**< a user defined pointer passed to the hook function */
88
};
89
90
/**
91
 * A request body parser instance.
92
 */
93
struct apreq_parser_t {
94
    /** the function which parses chunks of body data */
95
    apreq_parser_function_t parser;
96
    /** the Content-Type request header */
97
    const char             *content_type;
98
    /** a pool which outlasts the bucket_alloc. */
99
    apr_pool_t             *pool;
100
    /** bucket allocator used to create bucket brigades */
101
    apr_bucket_alloc_t     *bucket_alloc;
102
    /** the maximum in-memory bytes a brigade may use */
103
    apr_size_t              brigade_limit;
104
    /** the directory for generating temporary files */
105
    const char             *temp_dir;
106
    /** linked list of hooks */
107
    apreq_hook_t           *hook;
108
    /** internal context pointer used by the parser function */
109
    void                   *ctx;
110
};
111
112
113
/**
114
 * Parse the incoming brigade into a table.  Parsers normally
115
 * consume all the buckets of the brigade during parsing. However
116
 * parsers may leave "rejected" data in the brigade, even during a
117
 * successful parse, so callers may need to clean up the brigade
118
 * themselves (in particular, rejected buckets should not be
119
 * passed back to the parser again).
120
 * @remark  bb == NULL is valid: the parser should return its
121
 * public status: APR_INCOMPLETE, APR_SUCCESS, or an error code.
122
 */
123
static APR_INLINE
124
apr_status_t apreq_parser_run(struct apreq_parser_t *psr, apr_table_t *t,
125
                              apr_bucket_brigade *bb)
126
999
{
127
999
    return psr->parser(psr, t, bb);
128
999
}
Unexecuted instantiation: fuzz_preq.c:apreq_parser_run
Unexecuted instantiation: apreq_parser.c:apreq_parser_run
apreq_parser_multipart.c:apreq_parser_run
Line
Count
Source
126
999
{
127
999
    return psr->parser(psr, t, bb);
128
999
}
Unexecuted instantiation: apreq_parser_urlencoded.c:apreq_parser_run
Unexecuted instantiation: apreq_parser_header.c:apreq_parser_run
129
130
/**
131
 * Run the hook with the current parameter and the incoming
132
 * bucket brigade.  The hook may modify the brigade if necessary.
133
 * Once all hooks have completed, the contents of the brigade will
134
 * be added to the parameter's bb attribute.
135
 * @return APR_SUCCESS on success. All other values represent errors.
136
 */
137
static APR_INLINE
138
apr_status_t apreq_hook_run(struct apreq_hook_t *h, apreq_param_t *param,
139
                            apr_bucket_brigade *bb)
140
1.14k
{
141
1.14k
    return h->hook(h, param, bb);
142
1.14k
}
Unexecuted instantiation: fuzz_preq.c:apreq_hook_run
Unexecuted instantiation: apreq_parser.c:apreq_hook_run
apreq_parser_multipart.c:apreq_hook_run
Line
Count
Source
140
641
{
141
641
    return h->hook(h, param, bb);
142
641
}
apreq_parser_urlencoded.c:apreq_hook_run
Line
Count
Source
140
500
{
141
500
    return h->hook(h, param, bb);
142
500
}
Unexecuted instantiation: apreq_parser_header.c:apreq_hook_run
143
144
145
/**
146
 * RFC 822 Header parser. It will reject all data
147
 * after the first CRLF CRLF sequence (an empty line).
148
 * See apreq_parser_run() for more info on rejected data.
149
 */
150
APREQ_DECLARE_PARSER(apreq_parse_headers);
151
152
/**
153
 * RFC 2396 application/x-www-form-urlencoded parser.
154
 */
155
APREQ_DECLARE_PARSER(apreq_parse_urlencoded);
156
157
/**
158
 * RFC 2388 multipart/form-data (and XForms 1.0 multipart/related)
159
 * parser. It will reject any buckets representing preamble and
160
 * postamble text (this is normal behavior, not an error condition).
161
 * See apreq_parser_run() for more info on rejected data.
162
 */
163
APREQ_DECLARE_PARSER(apreq_parse_multipart);
164
165
/**
166
 * Generic parser.  No table entries will be added to
167
 * the req->body table by this parser.  The parser creates
168
 * a dummy apreq_param_t to pass to any configured hooks.  If
169
 * no hooks are configured, the dummy param's bb slot will
170
 * contain a copy of the request body.  It can be retrieved
171
 * by casting the parser's ctx pointer to (apreq_param_t **).
172
 */
173
APREQ_DECLARE_PARSER(apreq_parse_generic);
174
175
/**
176
 * apr_xml_parser hook. It will parse until EOS appears.
177
 * The parsed document isn't available until parsing has
178
 * completed successfully.  The hook's ctx pointer may
179
 * be cast as (apr_xml_doc **) to retrieve the
180
 * parsed document.
181
 */
182
APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser);
183
184
/**
185
 * Construct a parser.
186
 *
187
 * @param pool Pool used to allocate the parser.
188
 * @param ba bucket allocator used to create bucket brigades
189
 * @param content_type Content-type that this parser can deal with.
190
 * @param pfn The parser function.
191
 * @param brigade_limit the maximum in-memory bytes a brigade may use
192
 * @param temp_dir the directory used by the parser for temporary files
193
 * @param hook Hooks to associate this parser with.
194
 * @param ctx Parser's internal scratch pad.
195
 * @return New parser.
196
 */
197
APREQ_DECLARE(apreq_parser_t *) apreq_parser_make(apr_pool_t *pool,
198
                                                  apr_bucket_alloc_t *ba,
199
                                                  const char *content_type,
200
                                                  apreq_parser_function_t pfn,
201
                                                  apr_size_t brigade_limit,
202
                                                  const char *temp_dir,
203
                                                  apreq_hook_t *hook,
204
                                                  void *ctx);
205
206
/**
207
 * Construct a hook.
208
 *
209
 * @param pool used to allocate the hook.
210
 * @param hook The hook function.
211
 * @param next List of other hooks for this hook to call on.
212
 * @param ctx Hook's internal scratch pad.
213
 * @return New hook.
214
 */
215
APREQ_DECLARE(apreq_hook_t *) apreq_hook_make(apr_pool_t *pool,
216
                                              apreq_hook_function_t hook,
217
                                              apreq_hook_t *next,
218
                                              void *ctx);
219
220
221
/**
222
 * Add a new hook to the end of the parser's hook list.
223
 *
224
 * @param p Parser.
225
 * @param h Hook to append.
226
 */
227
APREQ_DECLARE(apr_status_t) apreq_parser_add_hook(apreq_parser_t *p,
228
                                                  apreq_hook_t *h);
229
230
231
/**
232
 * Fetch the default parser function associated with the given MIME type.
233
 * @param enctype The desired enctype (can also be a full "Content-Type"
234
 *        header).
235
 * @return The parser function, or NULL if the enctype is unrecognized.
236
 */
237
APREQ_DECLARE(apreq_parser_function_t)apreq_parser(const char *enctype);
238
239
240
/**
241
 * Register a new parsing function with a MIME enctype.
242
 * Registered parsers are added to apreq_parser()'s
243
 * internal lookup table.
244
 *
245
 * @param enctype The MIME type.
246
 * @param pfn     The function to use during parsing. Setting
247
 *                parser == NULL will remove an existing parser.
248
 *
249
 * @return APR_SUCCESS or error.
250
 */
251
252
APREQ_DECLARE(apr_status_t) apreq_register_parser(const char *enctype,
253
                                                  apreq_parser_function_t pfn);
254
255
256
/**
257
 * Returns APREQ_ERROR_GENERAL.  Effectively disables mfd parser
258
 * if a file-upload field is present.
259
 *
260
 */
261
APREQ_DECLARE_HOOK(apreq_hook_disable_uploads);
262
263
/**
264
 * Calls apr_brigade_cleanup on the incoming brigade
265
 * after passing the brigade to any subsequent hooks.
266
 */
267
APREQ_DECLARE_HOOK(apreq_hook_discard_brigade);
268
269
/**
270
 * Context struct for the apreq_hook_find_param hook.
271
 */
272
typedef struct apreq_hook_find_param_ctx_t {
273
    const char    *name;
274
    apreq_param_t *param;
275
    apreq_hook_t  *prev;
276
} apreq_hook_find_param_ctx_t;
277
278
279
/**
280
 * Special purpose utility for locating a parameter
281
 * during parsing.  The hook's ctx should be initialized
282
 * to an apreq_hook_find_param_ctx_t *, with the name
283
 * attribute set to the sought parameter name, the param
284
 * attribute set to NULL, and the prev attribute set to
285
 * the address of the previous hook.  The param attribute
286
 * will be reassigned to the first param found, and once
287
 * that happens this hook is immediately removed from the chain.
288
 *
289
 * @remarks When used, this should always be the first hook
290
 * invoked, so add it manually with ctx->prev = &parser->hook
291
 * instead of using apreq_parser_add_hook.
292
 */
293
APREQ_DECLARE_HOOK(apreq_hook_find_param);
294
295
296
#ifdef __cplusplus
297
}
298
299
#endif
300
#endif /* APREQ_PARSERS_H */