From a7df5240f103c55a1de9ca498e18a9da9d1c6a18 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 19 Mar 2026 23:18:45 +0100 Subject: [PATCH] http-heads: generate as C file to avoid issue with coverage Signed-off-by: Nikos Mavrogiannopoulos --- .gitlab-ci.yml | 4 +- .lcovrc | 13 ++++ dist-script.sh | 6 +- meson.build | 2 +- src/http-heads.gperf | 2 +- src/http-heads.h | 173 +++---------------------------------------- src/meson.build | 21 ++++-- 7 files changed, 42 insertions(+), 179 deletions(-) create mode 100644 .lcovrc diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 010900a1..e203a4f5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -236,7 +236,7 @@ Fedora: - ninja -C build -j$JOBS - COVERAGE=1 VERBOSE=1 meson test -C build --num-processes $JOBS --no-rebuild - ninja -C build coverage - coverage: '/lines[.]+: \d+\.\d+/' + coverage: '/lines[.]+: (\d+\.\d+)/' tags: - saas-linux-medium-amd64 except: @@ -407,7 +407,7 @@ codingstyle/Fedora: stage: preliminaries image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - - find src/ tests/ -name '*.[ch]'| grep -Ev '^(src/http-heads.h|src/ipc.pb-c|src/ctl.pb-c|src/pcl|src/protobuf|src/ccan|src/gnulib|src/inih|src/llhttp)'| xargs -I{} clang-format -style=file --dry-run {} -Werror + - find src/ tests/ -name '*.[ch]'| grep -Ev '^(src/http-heads.c|src/ipc.pb-c|src/ctl.pb-c|src/pcl|src/protobuf|src/ccan|src/gnulib|src/inih|src/llhttp)'| xargs -I{} clang-format -style=file --dry-run {} -Werror tags: - saas-linux-small-amd64 except: diff --git a/.lcovrc b/.lcovrc new file mode 100644 index 00000000..9606c7b5 --- /dev/null +++ b/.lcovrc @@ -0,0 +1,13 @@ +# Exclude gperf source files: gperf #line directives cause http-heads.gperf +# to appear in coverage data, which genhtml cannot annotate meaningfully. +exclude = */http-heads.gperf + +# Exclude generated files in the build directory. With an in-tree meson +# build, both source files (source_root/src/*.c) and generated files +# (build_root/src/*.c) produce paths starting with "src/" after genhtml's +# dual-prefix stripping, which causes genhtml to fail with +# "duplicate merge record src". +exclude = */build/src/* + +ignore_errors = unused +genhtml_ignore_errors = unmapped diff --git a/dist-script.sh b/dist-script.sh index 290a2e94..3d838f8a 100755 --- a/dist-script.sh +++ b/dist-script.sh @@ -24,14 +24,14 @@ else fi # -------------------------------------------------------------------------- -# gperf: http-heads.h +# gperf: http-heads.c # -------------------------------------------------------------------------- if command -v gperf >/dev/null 2>&1; then gperf --global-table -t "$DISTROOT/src/http-heads.gperf" \ - > "$DISTROOT/src/http-heads.h" + --output-file "$DISTROOT/src/http-heads.c" else - echo "dist-script: WARNING: gperf not found, skipping http-heads.h generation" >&2 + echo "dist-script: WARNING: gperf not found, skipping http-heads.c generation" >&2 fi # -------------------------------------------------------------------------- diff --git a/meson.build b/meson.build index fbb08d47..cffca819 100644 --- a/meson.build +++ b/meson.build @@ -32,7 +32,7 @@ add_project_arguments('-D_GNU_SOURCE', language: 'c') # Required tools # -------------------------------------------------------------------------- -gperf = find_program('gperf') +gperf = find_program('gperf', required: false) protoc_c = find_program('protoc-c') ipcalc = find_program(['ipcalc', 'ipcalc-ng'], required: true) diff --git a/src/http-heads.gperf b/src/http-heads.gperf index eb439b29..27dac1b0 100644 --- a/src/http-heads.gperf +++ b/src/http-heads.gperf @@ -1,5 +1,5 @@ %{ -#include "vpn.h" +#include "worker.h" %} %language=ANSI-C %readonly-tables diff --git a/src/http-heads.h b/src/http-heads.h index a83da818..87a91bbb 100644 --- a/src/http-heads.h +++ b/src/http-heads.h @@ -1,168 +1,13 @@ -/* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --global-table -t http-heads.gperf */ -/* Computed positions: -k'3,8' */ +#ifndef HTTP_HEADS_H +#define HTTP_HEADS_H -#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ - && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ - && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ - && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ - && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ - && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ - && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ - && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ - && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ - && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ - && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ - && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ - && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ - && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ - && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ - && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ - && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ - && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ - && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ - && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ - && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ - && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ - && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) -/* The character set is not based on ISO-646. */ -#error "gperf generated tables don't work with this execution character set. Please report a bug to ." -#endif +#include -#line 1 "http-heads.gperf" +struct http_headers_st { + const char *name; + unsigned id; +}; -#include "vpn.h" -#line 6 "http-heads.gperf" -struct http_headers_st { const char *name; unsigned id; }; +const struct http_headers_st *in_word_set(const char *str, size_t len); -#define TOTAL_KEYWORDS 17 -#define MIN_WORD_LENGTH 6 -#define MAX_WORD_LENGTH 34 -#define MIN_HASH_VALUE 6 -#define MAX_HASH_VALUE 40 -/* maximum key range = 35, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static unsigned int -hash (register const char *str, register size_t len) -{ - static const unsigned char asso_values[] = - { - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 15, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 0, 20, 0, 5, 41, - 10, 41, 15, 41, 41, 41, 41, 0, 41, 41, - 41, 41, 41, 5, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 5, 41, 41, 41, 5, 41, 41, 41, 41, - 0, 0, 41, 41, 0, 41, 0, 41, 41, 41, - 41, 41, 0, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41 - }; - register unsigned int hval = len; - - switch (hval) - { - default: - hval += asso_values[(unsigned char)str[7]]; - /*FALLTHROUGH*/ - case 7: - case 6: - case 5: - case 4: - case 3: - hval += asso_values[(unsigned char)str[2]]; - break; - } - return hval; -} - -static const struct http_headers_st wordlist[] = - { - {""}, {""}, {""}, {""}, {""}, {""}, -#line 8 "http-heads.gperf" - {"Cookie", HEADER_COOKIE}, - {""}, {""}, {""}, -#line 17 "http-heads.gperf" - {"X-CSTP-MTU", HEADER_CSTP_MTU}, - {""}, {""}, -#line 24 "http-heads.gperf" - {"Authorization", HEADER_AUTHORIZATION}, - {""}, -#line 12 "http-heads.gperf" - {"Connection", HEADER_CONNECTION}, - {""}, {""}, {""}, -#line 18 "http-heads.gperf" - {"X-CSTP-Address-Type", HEADER_CSTP_ATYPE}, -#line 9 "http-heads.gperf" - {"User-Agent", HEADER_USER_AGENT}, - {""}, -#line 10 "http-heads.gperf" - {"X-CSTP-Accept-Encoding", HEADER_CSTP_ENCODING}, -#line 14 "http-heads.gperf" - {"X-DTLS-CipherSuite", HEADER_DTLS_CIPHERSUITE}, -#line 23 "http-heads.gperf" - {"X-Support-HTTP-Auth", HEADER_SUPPORT_SPNEGO}, -#line 13 "http-heads.gperf" - {"X-DTLS-Master-Secret", HEADER_MASTER_SECRET}, - {""}, -#line 11 "http-heads.gperf" - {"X-DTLS-Accept-Encoding", HEADER_DTLS_ENCODING}, - {""}, {""}, -#line 19 "http-heads.gperf" - {"X-CSTP-Hostname", HEADER_HOSTNAME}, - {""}, -#line 22 "http-heads.gperf" - {"X-AnyConnect-Identifier-Platform", HEADER_PLATFORM}, - {""}, -#line 21 "http-heads.gperf" - {"X-AnyConnect-Identifier-DeviceType", HEADER_DEVICE_TYPE}, -#line 16 "http-heads.gperf" - {"X-CSTP-Base-MTU", HEADER_CSTP_BASE_MTU}, - {""}, -#line 20 "http-heads.gperf" - {"X-CSTP-Full-IPv6-Capability", HEADER_FULL_IPV6}, - {""}, {""}, -#line 15 "http-heads.gperf" - {"X-DTLS12-CipherSuite", HEADER_DTLS12_CIPHERSUITE} - }; - -const struct http_headers_st * -in_word_set (register const char *str, register size_t len) -{ - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) - { - register unsigned int key = hash (str, len); - - if (key <= MAX_HASH_VALUE) - { - register const char *s = wordlist[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return &wordlist[key]; - } - } - return 0; -} +#endif /* HTTP_HEADS_H */ diff --git a/src/meson.build b/src/meson.build index c7707560..f7b75078 100644 --- a/src/meson.build +++ b/src/meson.build @@ -71,12 +71,17 @@ ctl_proto = custom_target('ctl-proto', ) # gperf HTTP header table -http_heads_h = custom_target('http-heads', - input: 'http-heads.gperf', - output: 'http-heads.h', - command: [gperf, '--global-table', '-t', meson.current_source_dir() / 'http-heads.gperf'], - capture: true, -) +if gperf.found() + http_heads_c = custom_target('http-heads', + input: 'http-heads.gperf', + output: 'http-heads.c', + command: [gperf, '--global-table', '-t', '@INPUT@', '--output-file', '@OUTPUT@'], + ) +elif fs.exists('http-heads.c') + http_heads_c = files('http-heads.c') +else + error('gperf not found and no pre-generated http-heads.c present') +endif # ASN.1 (GSSAPI / KKDCP) kkdcp_asn1 = [] @@ -212,7 +217,7 @@ endif # ocserv # -------------------------------------------------------------------------- -ocserv_sources = core_sources + auth_sources + acct_sources + [http_heads_h] + files( +ocserv_sources = core_sources + auth_sources + acct_sources + files( 'main.c', 'main-auth.c', 'main-ban.c', @@ -249,7 +254,7 @@ executable('ocserv', ocserv_sources, # ocserv-worker # -------------------------------------------------------------------------- -worker_sources = core_sources + [http_heads_h] + files( +worker_sources = core_sources + [http_heads_c] + files( 'html.c', 'worker.c', 'worker-auth.c',