Coverage Report

Created: 2026-08-31 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mod_auth_openidc/test/fuzz/fuzz_cookie.c
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  Licensed under the Apache License,
4
 * Version 2.0 (the "License"); you may not use this file except in
5
 * compliance with the License.  You may obtain a copy of the License at
6
 *
7
 *   http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Copyright (C) 2017-2026 ZmartZone Holding BV - hans.zandbelt@openidc.com
10
 *
11
 * Fuzz target for the raw browser-supplied Cookie request header -- as
12
 * directly attacker-controlled as input gets, any client sets it -- and the
13
 * three consumers the module runs over it:
14
 *
15
 *   - oidc_http_get_cookie(): the header tokenizer, per cookie name;
16
 *   - oidc_http_get_chunked_cookie(): the reassembly of a session cookie that
17
 *     was split over "<name>_chunks" plus "<name>_0".."<name>_N" cookies, i.e.
18
 *     a browser-supplied chunk count driving a lookup loop (this is where a
19
 *     missing-chunk truncation bug was fixed, see commit "fix: return NULL
20
 *     when a chunked cookie is missing a chunk");
21
 *   - oidc_state_cookies_clean_expired(): the sweep over every cookie in the
22
 *     header that decrypts each "mod_auth_openidc_state_*" value, drops the
23
 *     expired ones and enforces OIDCStateMaxNumberOfCookies -- it runs on
24
 *     every authentication request and every authorization response.
25
 */
26
27
#include "fuzz.h"
28
/* util.h pulls in const.h before any Apache header does, so config.h's
29
 * PACKAGE_* defines win the race against Apache's own (empty) ones in
30
 * ap_config_auto.h; keep it ahead of http.h, see cfg/cfg.h's own ordering
31
 * (clang-format's include sorting would undo exactly that, hence the guard) */
32
/* clang-format off */
33
#include "util.h"  /* test fixture */
34
#include "http.h"  /* oidc_http_get_cookie, oidc_http_get_chunked_cookie */
35
#include "state.h" /* oidc_state_cookies_clean_expired */
36
/* clang-format on */
37
38
#include <apr_pools.h>
39
#include <apr_strings.h>
40
#include <apr_tables.h>
41
42
static int g_ready = 0;
43
44
/* engine-called one-time init, pre-forkserver on AFL++: see fuzz.h */
45
34
int LLVMFuzzerInitialize(int *argc, char ***argv) {
46
34
  (void)argc;
47
34
  (void)argv;
48
34
  if (!g_ready) {
49
34
    oidc_test_setup();
50
34
    g_ready = 1;
51
34
  }
52
34
  return 0;
53
34
}
54
55
6.63k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
56
6.63k
  if (!g_ready)
57
0
    LLVMFuzzerInitialize(NULL, NULL);
58
59
6.63k
  apr_pool_t *pool = NULL;
60
6.63k
  apr_pool_create(&pool, oidc_test_pool_get());
61
62
  /* shallow-copy the fixture request and give it a per-input pool, plus a
63
   * fresh headers_in table so the fuzzed Cookie value never touches the
64
   * shared fixture's table (which would otherwise leak across inputs), and
65
   * fresh output tables for the Set-Cookie deletions the sweep emits */
66
6.63k
  request_rec r = *oidc_test_request_get();
67
6.63k
  r.pool = pool;
68
6.63k
  r.headers_in = apr_table_make(pool, 1);
69
6.63k
  r.headers_out = apr_table_make(pool, 8);
70
6.63k
  r.err_headers_out = apr_table_make(pool, 8);
71
6.63k
  apr_table_set(r.headers_in, "Cookie", apr_pstrmemdup(pool, (const char *)data, size));
72
73
6.63k
  oidc_http_get_cookie(&r, "mod_auth_openidc_session");
74
  /* the chunk size only decides whether reassembly is attempted at all */
75
6.63k
  oidc_http_get_chunked_cookie(&r, "mod_auth_openidc_session", 4000);
76
6.63k
  oidc_state_cookies_clean_expired(&r, oidc_test_cfg_get(), NULL, 1);
77
78
6.63k
  apr_pool_destroy(pool);
79
6.63k
  return 0;
80
6.63k
}