diff --git a/README.md b/README.md index 9d3c7ab8d..5676007f4 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,10 @@ It is recommended to use assertions where applicable, and to enable them with The source tree includes a Benchmark tool that can help measure library performance. The tool is located in the `test/benchmark/` directory. The build process also creates the binary here, so you will have the tool after the compilation is finished. +Detailed benchmark test documentation is available in: +* `docs/benchmark-tests.en.md` +* `docs/benchmark-tests.de.md` + To compare the JSON regression suite across both supported JSON backends with separate build directories, run: ```shell @@ -325,7 +329,7 @@ The tool is a straightforward wrapper application that utilizes the library. It Each transaction is an HTTP/1.1 GET request with some GET parameters. Common headers are added, followed by the response headers and an XML body. Between phases, the tool checks whether an intervention has occurred. All transactions are created with the same data. -Note that the tool does not call the last phase (logging). +Note that the tool calls the logging phase (`processLogging()`) for each transaction. Please remember to reset `basic_rules.conf` if you want to try with a different ruleset. diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index 1fbe029c9..dc6cdeec5 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -192,10 +192,22 @@ endfunction() # unit tests file(GLOB unitTestSources ${BASE_DIR}/test/unit/*.cc) + +list(REMOVE_ITEM unitTestSources + ${BASE_DIR}/test/unit/json_backend_depth_tests.cc +) + add_executable(unit_tests ${unitTestSources} ${BASE_DIR}/test/common/custom_debug_log.cc) setTestTargetProperties(unit_tests) target_compile_options(unit_tests PRIVATE /wd4805) +add_executable(json_backend_depth_tests + ${BASE_DIR}/test/unit/json_backend_depth_tests.cc + ${BASE_DIR}/test/common/custom_debug_log.cc +) +setTestTargetProperties(json_backend_depth_tests) +target_compile_options(json_backend_depth_tests PRIVATE /wd4805) + # regression tests file(GLOB regressionTestsSources ${BASE_DIR}/test/regression/*.cc) add_executable(regression_tests ${regressionTestsSources} ${BASE_DIR}/test/common/custom_debug_log.cc) @@ -214,6 +226,12 @@ add_regression_test_capability(WITH_MAXMIND HAVE_MAXMIND) enable_testing() +add_test( + NAME json_backend_depth_tests + COMMAND json_backend_depth_tests + WORKING_DIRECTORY ${BASE_DIR}/test +) + file(READ ${BASE_DIR}/test/test-suite.in TEST_FILES_RAW) string(REPLACE "\n" ";" TEST_FILES ${TEST_FILES_RAW}) @@ -233,15 +251,25 @@ foreach(TEST_FILE ${TEST_FILES}) # test name get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + # json_backend_depth_tests is built as a standalone executable, + # so skip automatic registration through unit_tests + if(TEST_NAME STREQUAL "json_backend_depth_tests") + continue() + endif() + # determine test runner based on test path prefix string(FIND ${TEST_FILE} "test-cases/regression/" is_regression_test) if(is_regression_test EQUAL 0) - set(TEST_RUNNER "regression_tests") + set(TEST_RUNNER "regression_tests") else() - set(TEST_RUNNER "unit_tests") + set(TEST_RUNNER "unit_tests") endif() - add_test(NAME ${TEST_NAME} COMMAND ${TEST_RUNNER} ${TEST_FILE} WORKING_DIRECTORY ${BASE_DIR}/test) + add_test( + NAME ${TEST_NAME} + COMMAND ${TEST_RUNNER} ${TEST_FILE} + WORKING_DIRECTORY ${BASE_DIR}/test + ) endif() endforeach() @@ -253,7 +281,6 @@ setTestTargetProperties(benchmark) add_executable(rules_optimization ${BASE_DIR}/test/optimization/optimization.cc) setTestTargetProperties(rules_optimization) - # examples # diff --git a/docs/benchmark-tests.de.md b/docs/benchmark-tests.de.md new file mode 100644 index 000000000..34f30ed84 --- /dev/null +++ b/docs/benchmark-tests.de.md @@ -0,0 +1,317 @@ +# Benchmark-Tests (ModSecurity) + +## 1. Überblick + +Dieses Repository enthält zwei Benchmark-Programme in `test/benchmark/`: + +1. `benchmark` (`test/benchmark/benchmark.cc`) + - Zweck: wiederholte Ausführung einer ModSecurity-Transaktion in einer Schleife. +2. `json_benchmark` (`test/benchmark/json_benchmark.cc`) + - Zweck: Benchmarking der JSON-Request-Body-Verarbeitung mit festen Szenarien. + +Relevante Dateien: + +- `test/benchmark/benchmark.cc` +- `test/benchmark/json_benchmark.cc` +- `test/benchmark/run-json-benchmarks.sh` +- `test/benchmark/json_benchmark_rules.conf` +- `test/benchmark/basic_rules.conf` +- `test/benchmark/download-owasp-v3-rules.sh` +- `test/benchmark/download-owasp-v4-rules.sh` +- `test/benchmark/Makefile.am` +- `README.md` (Benchmark-Abschnitt) + +--- + +## 2. Voraussetzungen + +### Benötigte Tools + +- POSIX-Shell (`bash`) +- `make` +- C/C++-Toolchain (`gcc`, `g++`) +- Autotools-Bootstrap-Unterstützung aus diesem Repo (`./build.sh`) +- `git` (für Submodule) + +### Benötigte Repository-Vorbereitung + +Der Benchmark-Build benötigt Submodule. + +Verwendete Befehle: + +```bash +./build.sh +git submodule update --init --recursive +./configure +``` + +### Optionale Voraussetzungen + +- `time` für externe Laufzeitmessung von `benchmark` +- Zwei getrennte Build-Verzeichnisse für Backend-Vergleiche mit `run-json-benchmarks.sh` + +### Beobachtete Einschränkungen in dieser Umgebung + +- `./configure` schlug zunächst fehl, bevor Submodule initialisiert wurden. +- Beobachtete Fehlermeldung: + +```text +configure: error: + + libInjection was not found within ModSecurity source directory. + ... + $ git submodule update --init --recursive +``` + +Nach dem Submodule-Update lief `./configure` in dieser Umgebung erfolgreich durch. + +--- + +## 3. Build-Anleitung + +## Standardablauf (so für die Verifikation verwendet) + +```bash +./build.sh +git submodule update --init --recursive +./configure +make -j2 -C others +make -j2 -C src libmodsecurity.la +make -j2 -C test/benchmark benchmark json_benchmark +``` + +## Hinweise + +- `test/benchmark/Makefile.am` definiert beide Binaries (`benchmark`, `json_benchmark`). +- `json_benchmark` benötigt `MSC_JSON_BENCHMARK_RULES_DIR` aus dem Build-System. + +## Typische Prüf-Befehle bei Fehlern + +```bash +git submodule status +ls -l test/benchmark/benchmark test/benchmark/json_benchmark +``` + +--- + +## 4. Ausführung + +## `benchmark` + +```bash +cd test/benchmark +./benchmark +./benchmark 1000 +``` + +Aktuelle Usage aus dem Quelltext: + +```text +Usage: benchmark [num_iterations|-h|-?|--help] +``` + +## `json_benchmark` + +```bash +cd test/benchmark +./json_benchmark --scenario numbers --iterations 100 --target-bytes 1048576 +./json_benchmark --scenario utf8 --iterations 50 --output json +``` + +Aktuelle Usage aus dem Quelltext: + +```text +Usage: json_benchmark --scenario NAME [--iterations N] [--target-bytes N] [--depth N] [--include-invalid] [--output json] +``` + +## Batch-Skript: `run-json-benchmarks.sh` + +```bash +test/benchmark/run-json-benchmarks.sh \ + --simdjson-build /pfad/zum/simdjson-build \ + --jsoncons-build /pfad/zum/jsoncons-build +``` + +Optional: + +```bash +test/benchmark/run-json-benchmarks.sh ... --include-invalid +``` + +Das Skript schreibt JSON-Ausgaben von `json_benchmark` in `json-benchmark-results.jsonl`. + +--- + +## 5. Beispiele + +## Beispiel A: verifizierter Lauf (`benchmark`) + +Ausgeführter Befehl: + +```bash +cd test/benchmark && ./benchmark 10 +``` + +Beobachtete Ausgabe: + +```text +Doing 10 transactions... +Summary: + elapsed_seconds: 0.01 + avg_transaction_ns: 917598.70 + throughput_tx_per_sec: 1089.80 +``` + +## Beispiel B: verifizierter Lauf (`json_benchmark`) + +Ausgeführter Befehl: + +```bash +cd test/benchmark && ./json_benchmark --scenario numbers --iterations 5 --target-bytes 256 +``` + +Beobachtete Ausgabe: + +```text +backend: simdjson +scenario: numbers +iterations: 5 +body_bytes: 223 +append_request_body_ns: 4021 +process_request_body_ns: 288499 +total_transaction_ns: 840357 +parse_success_count: 5 +parse_error_count: 0 +ru_maxrss_kb: 33720 +``` + +Auf anderen Systemen unterscheiden sich die absoluten Werte. + +--- + +## 6. Gemessene Metriken + +## `benchmark` + +Aktuelle Summary-Felder: + +- `elapsed_seconds` +- `avg_transaction_ns` +- `throughput_tx_per_sec` + +Diese Werte werden um die gesamte Loop gemessen und am Ende ausgegeben. + +## `json_benchmark` + +Vom Code ausgegebene Metriken: + +- `append_request_body_ns` +- `process_request_body_ns` +- `total_transaction_ns` +- `parse_success_count` +- `parse_error_count` +- `ru_maxrss_kb` + +Optionale Instrumentierungsmetriken sind verfügbar, wenn mit `--enable-json-audit-instrumentation` gebaut wird. + +--- + +## 7. Testdaten und Szenarien + +## `benchmark` + +- Verwendet feste synthetische Request-/Response-Daten aus dem Quelltext. +- Rule-Datei: `test/benchmark/basic_rules.conf`. +- Optionale CRS-Erweiterungen über: + - `test/benchmark/download-owasp-v3-rules.sh` + - `test/benchmark/download-owasp-v4-rules.sh` + +## `json_benchmark`-Szenarien + +Im Quelltext unterstützte Szenarien: + +- `large-object` +- `deep-nesting` +- `numbers` +- `utf8` +- `truncated` (benötigt `--include-invalid`) +- `malformed` (benötigt `--include-invalid`) + +Rule-Konfigurationsdatei: + +- `test/benchmark/json_benchmark_rules.conf` + +--- + +## 8. Troubleshooting + +## Problem: `./configure` scheitert wegen fehlender eingebetteter Abhängigkeit + +Prüfen: + +```bash +git submodule status +``` + +Beheben: + +```bash +git submodule update --init --recursive +./configure +``` + +## Problem: Benchmark-Binaries fehlen + +Prüfen: + +```bash +ls -l test/benchmark/benchmark test/benchmark/json_benchmark +``` + +Bauen: + +```bash +make -j2 -C src libmodsecurity.la +make -j2 -C test/benchmark benchmark json_benchmark +``` + +## Problem: Skript meldet „missing benchmark binary“ + +Das Skript erwartet: + +- `/test/benchmark/json_benchmark` + +Pfad und Executable-Bit prüfen. + +--- + +## 9. Grenzen der Benchmarks + +Was gemessen wird: + +- Kosten der wiederholten Transaction-Ausführung (`benchmark`). +- JSON-Body-Verarbeitung unter festen synthetischen Szenarien (`json_benchmark`). + +Was nicht direkt gemessen wird: + +- Verteiltes Multi-Node-Load-Verhalten. +- Volle Produktions-Traffic-Diversität. +- Latenz-Perzentile (p95/p99) aus externem Lastgenerator. + +Interpretationshinweis: + +- Ergebnisse hängen von Umgebung ab (CPU, Compiler-Flags, Rule-Umfang, Backend-Auswahl, Systemlast). + +--- + +## 10. Dateien und Referenzen + +- `README.md` — Benchmark-Abschnitt und Schnellbefehle. +- `test/benchmark/benchmark.cc` — allgemeiner Transaction-Benchmark. +- `test/benchmark/json_benchmark.cc` — JSON-Szenario-Benchmark. +- `test/benchmark/run-json-benchmarks.sh` — Hilfsskript für Backend-Vergleiche. +- `test/benchmark/json_benchmark_rules.conf` — Rules für JSON-Benchmark. +- `test/benchmark/basic_rules.conf` — Baseline-Rules für allgemeinen Benchmark. +- `test/benchmark/download-owasp-v3-rules.sh` — lädt CRS v3 und ergänzt Includes. +- `test/benchmark/download-owasp-v4-rules.sh` — lädt CRS v4 und ergänzt Includes. +- `test/benchmark/Makefile.am` — Benchmark-Targets in Automake. diff --git a/docs/benchmark-tests.en.md b/docs/benchmark-tests.en.md new file mode 100644 index 000000000..97789f479 --- /dev/null +++ b/docs/benchmark-tests.en.md @@ -0,0 +1,319 @@ +# Benchmark Tests (ModSecurity) + +## 1. Overview + +This repository contains two benchmark executables in `test/benchmark/`: + +1. `benchmark` (`test/benchmark/benchmark.cc`) + - Purpose: run repeated end-to-end-style ModSecurity transaction processing in a loop. +2. `json_benchmark` (`test/benchmark/json_benchmark.cc`) + - Purpose: benchmark JSON request-body processing with fixed scenarios. + +Relevant files: + +- `test/benchmark/benchmark.cc` +- `test/benchmark/json_benchmark.cc` +- `test/benchmark/run-json-benchmarks.sh` +- `test/benchmark/json_benchmark_rules.conf` +- `test/benchmark/basic_rules.conf` +- `test/benchmark/download-owasp-v3-rules.sh` +- `test/benchmark/download-owasp-v4-rules.sh` +- `test/benchmark/Makefile.am` +- `README.md` (benchmark section) + +--- + +## 2. Prerequisites + +### Required tools + +- POSIX shell (`bash`) +- `make` +- C/C++ toolchain (`gcc`, `g++`) +- Autotools bootstrap support used by this repo (`./build.sh`) +- `git` (required for submodule initialization) + +### Required repository preparation + +The benchmark build requires repository submodules. + +Commands used: + +```bash +./build.sh +git submodule update --init --recursive +./configure +``` + +### Optional prerequisites + +- `time` command for external wall-clock timing of `benchmark` +- Two separate build directories if you want to compare JSON backends with `run-json-benchmarks.sh` + +### Known environment constraints observed during verification + +- Initial `./configure` failed before submodules were initialized. +- Error observed: + +```text +configure: error: + + libInjection was not found within ModSecurity source directory. + ... + $ git submodule update --init --recursive +``` + +After submodule initialization, `./configure` completed successfully in this environment. + +--- + +## 3. Build Instructions + +## Standard build flow used for benchmark verification + +```bash +./build.sh +git submodule update --init --recursive +./configure +make -j2 -C others +make -j2 -C src libmodsecurity.la +make -j2 -C test/benchmark benchmark json_benchmark +``` + +## Notes + +- `test/benchmark/Makefile.am` declares both binaries (`benchmark`, `json_benchmark`). +- `json_benchmark` depends on `MSC_JSON_BENCHMARK_RULES_DIR` provided by the build system. + +## Typical error checks + +If build fails, verify: + +```bash +git submodule status +ls -l test/benchmark/benchmark test/benchmark/json_benchmark +``` + +--- + +## 4. Execution + +## `benchmark` + +```bash +cd test/benchmark +./benchmark +./benchmark 1000 +``` + +Current usage string from source: + +```text +Usage: benchmark [num_iterations|-h|-?|--help] +``` + +## `json_benchmark` + +```bash +cd test/benchmark +./json_benchmark --scenario numbers --iterations 100 --target-bytes 1048576 +./json_benchmark --scenario utf8 --iterations 50 --output json +``` + +Current usage string from source: + +```text +Usage: json_benchmark --scenario NAME [--iterations N] [--target-bytes N] [--depth N] [--include-invalid] [--output json] +``` + +## Batch script: `run-json-benchmarks.sh` + +```bash +test/benchmark/run-json-benchmarks.sh \ + --simdjson-build /path/to/simdjson-build \ + --jsoncons-build /path/to/jsoncons-build +``` + +Optional: + +```bash +test/benchmark/run-json-benchmarks.sh ... --include-invalid +``` + +This script appends JSON output lines from `json_benchmark` into `json-benchmark-results.jsonl`. + +--- + +## 5. Examples + +## Example A: verified local run (`benchmark`) + +Command executed: + +```bash +cd test/benchmark && ./benchmark 10 +``` + +Observed output: + +```text +Doing 10 transactions... +Summary: + elapsed_seconds: 0.01 + avg_transaction_ns: 917598.70 + throughput_tx_per_sec: 1089.80 +``` + +## Example B: verified local run (`json_benchmark`) + +Command executed: + +```bash +cd test/benchmark && ./json_benchmark --scenario numbers --iterations 5 --target-bytes 256 +``` + +Observed output: + +```text +backend: simdjson +scenario: numbers +iterations: 5 +body_bytes: 223 +append_request_body_ns: 4021 +process_request_body_ns: 288499 +total_transaction_ns: 840357 +parse_success_count: 5 +parse_error_count: 0 +ru_maxrss_kb: 33720 +``` + +If you run on another machine, absolute numeric values will differ. + +--- + +## 6. Measured Metrics + +## `benchmark` + +Current human-readable summary fields: + +- `elapsed_seconds` +- `avg_transaction_ns` +- `throughput_tx_per_sec` + +These are measured around the whole loop and printed at the end. + +## `json_benchmark` + +Metrics printed by code: + +- `append_request_body_ns` +- `process_request_body_ns` +- `total_transaction_ns` +- `parse_success_count` +- `parse_error_count` +- `ru_maxrss_kb` + +Optional instrumentation metrics are available when compiled with `--enable-json-audit-instrumentation`. + +--- + +## 7. Test Data and Scenarios + +## `benchmark` + +- Uses fixed synthetic request/response data from source. +- Rule file: `test/benchmark/basic_rules.conf`. +- Optional CRS additions via: + - `test/benchmark/download-owasp-v3-rules.sh` + - `test/benchmark/download-owasp-v4-rules.sh` + +## `json_benchmark` scenarios + +Supported scenario names in source: + +- `large-object` +- `deep-nesting` +- `numbers` +- `utf8` +- `truncated` (requires `--include-invalid`) +- `malformed` (requires `--include-invalid`) + +Rule configuration file: + +- `test/benchmark/json_benchmark_rules.conf` + +--- + +## 8. Troubleshooting + +## Problem: `./configure` fails with missing embedded dependency + +Check: + +```bash +git submodule status +``` + +Fix: + +```bash +git submodule update --init --recursive +./configure +``` + +## Problem: benchmark binaries missing + +Check: + +```bash +ls -l test/benchmark/benchmark test/benchmark/json_benchmark +``` + +Build: + +```bash +make -j2 -C src libmodsecurity.la +make -j2 -C test/benchmark benchmark json_benchmark +``` + +## Problem: JSON benchmark script reports missing binary + +The script expects binaries at: + +- `/test/benchmark/json_benchmark` + +Validate path and executable bit. + +--- + +## 9. Benchmark Limits + +What these benchmarks do measure: + +- Repeated transaction execution path cost (`benchmark`). +- JSON body handling under fixed synthetic scenarios (`json_benchmark`). + +What they do not directly measure: + +- Distributed multi-node load behavior. +- Full production traffic diversity. +- Latency percentiles (p95/p99) across an external load generator. + +Interpretation caution: + +- Results are environment-dependent (CPU, compiler flags, ruleset size, selected backend, system load). + +--- + +## 10. Files and References + +- `README.md` — benchmark section and quick commands. +- `test/benchmark/benchmark.cc` — generic transaction benchmark. +- `test/benchmark/json_benchmark.cc` — JSON scenario benchmark. +- `test/benchmark/run-json-benchmarks.sh` — backend comparison helper script. +- `test/benchmark/json_benchmark_rules.conf` — rules for JSON benchmark. +- `test/benchmark/basic_rules.conf` — baseline rules include for generic benchmark. +- `test/benchmark/download-owasp-v3-rules.sh` — fetch and append CRS v3 includes. +- `test/benchmark/download-owasp-v4-rules.sh` — fetch and append CRS v4 includes. +- `test/benchmark/Makefile.am` — benchmark targets in automake. diff --git a/reports/pr3540_sonar_reanalyse.md b/reports/pr3540_sonar_reanalyse.md new file mode 100644 index 000000000..d4bf60f31 --- /dev/null +++ b/reports/pr3540_sonar_reanalyse.md @@ -0,0 +1,324 @@ +# Aktueller Commit +Analyse basiert auf Commit: `bbde416a92212f1fc4a975361e73a3b07356a526`. + +# Quality Gate +Status: **OK** + +## Measures (Sonar API) +- minor_violations: 17 +- new_minor_violations: 17 +- code_smells: 52 +- new_vulnerabilities: 0 +- violations: 52 +- new_info_violations: 0 +- security_hotspots: 0 +- new_bugs: 0 +- new_code_smells: 52 +- critical_violations: 17 +- new_major_violations: 18 +- blocker_violations: 0 +- bugs: 0 +- info_violations: 0 +- alert_status: OK +- new_security_hotspots: 0 +- new_critical_violations: 17 +- major_violations: 18 +- new_violations: 52 +- new_blocker_violations: 0 +- vulnerabilities: 0 + +# Tabelle: Alle Befunde +| ID | Kategorie | Regelcode | Severity | Status | Datei | Zeile | Nachricht | Codebereich | Behebbar | +|---|---|---|---|---|---|---:|---|---|---| +| GATE-3540 | Gate | quality_gate | OK | OK | - | - | Quality Gate für PR 3540 | Production | Nein | +| AZ2HqeBsWym3B0O6okyS | Issue | cpp:S5952 | MINOR | OPEN | test/benchmark/json_benchmark.cc | 71 | Add a using-declaration to this derived class to inherit the constructors of "runtime_error", and remove the ones you manually duplicated. Note that this may add other constructors to your derived class. | Test | Ja | +| AZ2HqeBsWym3B0O6okyT | Issue | cpp:S6004 | MINOR | OPEN | test/benchmark/json_benchmark.cc | 144 | Use the init-statement to declare "current" inside the if statement. | Test | Ja | +| AZ2DWE24t-zbsGOGdN-_ | Issue | cpp:S3776 | CRITICAL | CLOSED | test/benchmark/json_benchmark.cc | | Refactor this function to reduce its Cognitive Complexity from 33 to the 25 allowed. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_A | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_B | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_C | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_D | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_E | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_F | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_G | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_H | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_I | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_J | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_K | Issue | cpp:S4998 | MAJOR | OPEN | test/benchmark/json_benchmark.cc | 316 | Replace this use of "unique_ptr" by a raw pointer or a reference (possibly const). | Test | Ja | +| AZ2DWE24t-zbsGOGdN_M | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_N | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_O | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DWE24t-zbsGOGdN_P | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ2DVDgODPiZK5yPV1-J | Issue | cpp:S1188 | MAJOR | OPEN | test/regression/regression_test.cc | 235 | This lambda has 23 lines, which is greater than the 20 lines authorized. Split it into several lambdas or functions, or make it a named function. | Test | Ja | +| AZ2DR4Fykud7vHWq_QVC | Issue | cpp:S6009 | MINOR | OPEN | src/request_body_processor/json_adapter.cc | 58 | Replace this const reference to "std::string" by a "std::string_view". | Production | Ja | +| AZ2DR4Fykud7vHWq_QVD | Issue | cpp:S995 | MINOR | OPEN | src/request_body_processor/json_adapter.cc | 59 | Make the type of this parameter a pointer-to-const. The current type of "sink" is "class modsecurity::RequestBodyProcessor::JsonEventSink *". | Production | Ja | +| AZ2DR4Fykud7vHWq_QVE | Issue | cpp:S995 | MINOR | OPEN | src/request_body_processor/json_adapter.cc | 81 | Make the type of this parameter a reference-to-const. The current type of "input" is "std::string &". | Production | Ja | +| AZ2DK9KwXISY38E6wMPS | Issue | cpp:S995 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Make the type of this parameter a pointer-to-const. The current type of "sink" is "class modsecurity::RequestBodyProcessor::JsonEventSink *". | Production | Nein | +| AZ2C_aavSTzC4JOHsQM1 | Issue | cpp:S1121 | MAJOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Extract the assignment from this expression. | Production | Nein | +| AZ2CwcldK0fgB4uOpVKy | Issue | cpp:S995 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Make the type of this parameter a reference-to-const. The current type of "input" is "std::string &". | Production | Nein | +| AZ2CwcldK0fgB4uOpVK0 | Issue | cpp:S995 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Make the type of this parameter a pointer-to-const. The current type of "sink" is "class modsecurity::RequestBodyProcessor::JsonEventSink *". | Production | Nein | +| AZ2CwcldK0fgB4uOpVKz | Issue | cpp:S1172 | MAJOR | CLOSED | src/request_body_processor/json_adapter.cc | | Remove the unused parameter "options", make it unnamed, or declare it "[[maybe_unused]]". | Production | Nein | +| AZ2CwcnoK0fgB4uOpVK1 | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "tail" inside the if statement. | Production | Nein | +| AZ2CwcnoK0fgB4uOpVK2 | Issue | cpp:S1117 | MAJOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Declaration shadows a local variable "result" in the outer scope. | Production | Nein | +| AZ2CwcnoK0fgB4uOpVK3 | Issue | cpp:S1117 | MAJOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Declaration shadows a local variable "result" in the outer scope. | Production | Nein | +| AZ2CwcnoK0fgB4uOpVK4 | Issue | cpp:S5817 | MAJOR | OPEN | src/request_body_processor/json_backend_simdjson.cc | 450 | This function should be declared "const". | Production | Ja | +| AZ2CwcpOK0fgB4uOpVK5 | Issue | cpp:S6004 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use the init-statement to declare "result" inside the if statement. | Test | Nein | +| AZ2CwcpOK0fgB4uOpVK6 | Issue | cpp:S6004 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use the init-statement to declare "result" inside the if statement. | Test | Nein | +| AZ2CdKxRGCkM6OziHCww | Issue | cpp:S6004 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use the init-statement to declare "result" inside the if statement. | Test | Nein | +| AZ2CdKxRGCkM6OziHCwx | Issue | cpp:S5945 | MAJOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use "std::array" or "std::vector" instead of a C-style array. | Test | Nein | +| AZ2CdKxRGCkM6OziHCwy | Issue | cpp:S3628 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Convert this string literal to a raw string literal. | Test | Nein | +| AZ2CBI6Kkud7vHWq0tqj | Issue | cpp:S6022 | MAJOR | OPEN | src/operators/validate_byte_range.cc | 156 | Use "std::byte" for byte-oriented data manipulation. | Production | Ja | +| AZ2CA_0CGCkM6OziEPex | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ2CA_xuGCkM6OziEPet | Issue | cpp:S5812 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Concatenate this namespace with the nested one. | Test | Nein | +| AZ2CA_xuGCkM6OziEPeu | Issue | cpp:S4144 | MAJOR | OPEN | test/unit/json_backend_depth_tests.cc | 50 | Update this method so that its implementation is not identical to on_key. | Test | Ja | +| AZ2CA_xuGCkM6OziEPev | Issue | cpp:S6004 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use the init-statement to declare "result" inside the if statement. | Test | Nein | +| AZ2CA_xuGCkM6OziEPew | Issue | cpp:S6004 | MINOR | CLOSED | test/unit/json_backend_depth_tests.cc | | Use the init-statement to declare "result" inside the if statement. | Test | Nein | +| AZ2BthMEO-njQfcv_7WG | Issue | cpp:S3776 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 362 | Refactor this function to reduce its Cognitive Complexity from 41 to the 25 allowed. | Production | Ja | +| AZ2BthMEO-njQfcv_7WH | Issue | cpp:S1121 | MAJOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Extract the assignment from this expression. | Production | Nein | +| AZ2BthMEO-njQfcv_7WI | Issue | cpp:S1121 | MAJOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Extract the assignment from this expression. | Production | Nein | +| AZ2BthMEO-njQfcv_7WJ | Issue | cpp:S3776 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 426 | Refactor this function to reduce its Cognitive Complexity from 43 to the 25 allowed. | Production | Ja | +| AZ2BthMEO-njQfcv_7WK | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "decoded_number" inside the if statement. | Production | Nein | +| AZ2BthMEO-njQfcv_7WL | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 634 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ2BkKY5XISY38E6k-Ld | Issue | cpp:S1135 | INFO | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Complete the task associated to this "TODO" comment. | Production | Nein | +| AZ1-dn-nXISY38E6Txop | Issue | cpp:S5025 | CRITICAL | OPEN | src/request_body_processor/json.cc | 57 | Rewrite the code so that you no longer need this "delete". | Production | Ja | +| AZ1-dn-nXISY38E6Txoq | Issue | cpp:S5827 | MAJOR | CLOSED | src/request_body_processor/json.cc | | Replace the redundant type with "auto". | Production | Nein | +| AZ1-dn9hXISY38E6Txon | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_instrumentation.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ1-dn9hXISY38E6Txoo | Issue | cpp:S5421 | CRITICAL | OPEN | src/request_body_processor/json_instrumentation.cc | 12 | Global variables should be const. | Production | Ja | +| AZ1-dn9QXISY38E6Txom | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_instrumentation.h | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ1-dn4cXISY38E6Txoh | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | +| AZ1-doCWXISY38E6Txoz | Issue | cpp:S5421 | CRITICAL | CLOSED | test/benchmark/json_benchmark.cc | | Global pointers should be const at every level. | Test | Nein | +| AZ1-doCWXISY38E6Txo0 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo1 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo6 | Issue | cpp:S886 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Refactor this loop so that it is less error-prone. | Test | Nein | +| AZ1-doCWXISY38E6Txo3 | Issue | cpp:S6004 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Use the init-statement to declare "output_format" inside the if statement. | Test | Nein | +| AZ1-doCWXISY38E6Txo4 | Issue | cpp:S6004 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Use the init-statement to declare "is_invalid_scenario" inside the if statement. | Test | Nein | +| AZ1-doCWXISY38E6TxpE | Issue | cpp:S5945 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Use "std::array" or "std::vector" instead of a C-style array. | Test | Nein | +| AZ1-doCWXISY38E6TxpF | Issue | cpp:S5945 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Use "std::array" or "std::vector" instead of a C-style array. | Test | Nein | +| AZ1-doCWXISY38E6TxpG | Issue | cpp:S7127 | CRITICAL | CLOSED | test/benchmark/json_benchmark.cc | | Use "std::size" to get the size of this array. | Test | Nein | +| AZ1-doCWXISY38E6TxpK | Issue | cpp:S6009 | MINOR | OPEN | test/benchmark/json_benchmark.cc | 321 | Replace this const reference to "std::string" by a "std::string_view". | Test | Ja | +| AZ1-doCWXISY38E6TxpM | Issue | cpp:S7121 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Remove this redundant call to "c_str" when initializing a const "std::string" reference parameter. | Test | Nein | +| AZ1-doCWXISY38E6TxpJ | Issue | cpp:S6004 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Use the init-statement to declare "parse_error" inside the if statement. | Test | Nein | +| AZ1-doCWXISY38E6TxpS | Issue | cpp:S3628 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Convert this string literal to a raw string literal. | Test | Nein | +| AZ1-doCWXISY38E6TxpT | Issue | cpp:S3628 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Convert this string literal to a raw string literal. | Test | Nein | +| AZ1-doCWXISY38E6TxpR | Issue | cpp:S6009 | MINOR | OPEN | test/benchmark/json_benchmark.cc | 419 | Replace this const reference to "std::string" by a "std::string_view". | Test | Ja | +| AZ1-doCWXISY38E6TxpV | Issue | cpp:S6004 | MINOR | CLOSED | test/benchmark/json_benchmark.cc | | Use the init-statement to declare "rules_path" inside the if statement. | Test | Nein | +| AZ1-doCWXISY38E6TxpU | Issue | cpp:S6009 | MINOR | OPEN | test/benchmark/json_benchmark.cc | 486 | Replace this const reference to "std::string" by a "std::string_view". | Test | Ja | +| AZ1-doCWXISY38E6Txo2 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo5 | Issue | cpp:S3776 | CRITICAL | CLOSED | test/benchmark/json_benchmark.cc | | Refactor this function to reduce its Cognitive Complexity from 33 to the 25 allowed. | Test | Nein | +| AZ1-doCWXISY38E6Txo7 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo8 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo9 | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo- | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6Txo_ | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpA | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpB | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpC | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpD | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpH | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpI | Issue | cpp:S4998 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Replace this use of "unique_ptr" by a raw pointer or a reference (possibly const). | Test | Nein | +| AZ1-doCWXISY38E6TxpN | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpO | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpP | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCWXISY38E6TxpQ | Issue | cpp:S112 | MAJOR | CLOSED | test/benchmark/json_benchmark.cc | | Define and throw a dedicated exception instead of using a generic one. | Test | Nein | +| AZ1-doCHXISY38E6Txor | Issue | shelldre:S7682 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Add an explicit return statement at the end of the function. | Test | Nein | +| AZ1-doCHXISY38E6Txos | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txot | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txou | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txov | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txow | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txox | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doCHXISY38E6Txoy | Issue | shelldre:S7688 | MAJOR | CLOSED | test/benchmark/run-json-benchmarks.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6TxpW | Issue | shelldre:S7682 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Add an explicit return statement at the end of the function. | Test | Nein | +| AZ1-doDkXISY38E6TxpX | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6TxpY | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6TxpZ | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpa | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpb | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpc | Issue | shelldre:S7682 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Add an explicit return statement at the end of the function. | Test | Nein | +| AZ1-doDkXISY38E6Txpd | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpe | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpf | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpg | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txph | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpi | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpj | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpk | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ1-doDkXISY38E6Txpl | Issue | shelldre:S7688 | MAJOR | CLOSED | test/run-json-backend-matrix.sh | | Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich. | Test | Nein | +| AZ190QEMSTzC4JOHOn9q | Issue | cpp:S6022 | MAJOR | OPEN | src/operators/validate_byte_range.cc | 72 | Use "std::byte" for byte-oriented data manipulation. | Production | Ja | +| AZ190QEMSTzC4JOHOn9r | Issue | cpp:S6004 | MINOR | CLOSED | src/operators/validate_byte_range.cc | | Use the init-statement to declare "token" inside the if statement. | Production | Nein | +| AZ190QGTSTzC4JOHOn-D | Issue | cpp:S3230 | MAJOR | OPEN | src/request_body_processor/json.cc | 79 | Do not use the constructor's initializer list for data member "m_data". Use the in-class initializer instead. | Production | Ja | +| AZ190QGTSTzC4JOHOn-H | Issue | cpp:S3776 | CRITICAL | OPEN | src/request_body_processor/json.cc | 121 | Refactor this function to reduce its Cognitive Complexity from 37 to the 25 allowed. | Production | Ja | +| AZ190QGTSTzC4JOHOn-G | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json.cc | | Use the init-statement to declare "result" inside the if statement. | Production | Nein | +| AZ190QGTSTzC4JOHOn-I | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json.cc | 135 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QGTSTzC4JOHOn-J | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json.cc | 142 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QGTSTzC4JOHOn-K | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json.cc | 149 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QGTSTzC4JOHOn-L | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json.cc | 156 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QGTSTzC4JOHOn-M | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json.cc | 163 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QGTSTzC4JOHOn-E | Issue | cpp:S4144 | MAJOR | CLOSED | src/request_body_processor/json.cc | | Update this method so that its implementation is not identical to on_end_object. | Production | Nein | +| AZ190QGTSTzC4JOHOn-N | Issue | cpp:S1155 | MINOR | CLOSED | src/request_body_processor/json.cc | | Use "empty()" to check whether the container is empty or not. | Production | Nein | +| AZ190QGTSTzC4JOHOn-O | Issue | cpp:S1155 | MINOR | CLOSED | src/request_body_processor/json.cc | | Use "empty()" to check whether the container is empty or not. | Production | Nein | +| AZ190QEtSTzC4JOHOn9t | Issue | cpp:S3624 | CRITICAL | OPEN | src/request_body_processor/json.h | 52 | Customize this class' copy constructor to participate in resource management. Customize or delete its copy assignment operator. Also consider whether move operations should be customized. | Production | Ja | +| AZ190QF1STzC4JOHOn9- | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QF1STzC4JOHOn-A | Issue | cpp:S1172 | MAJOR | CLOSED | src/request_body_processor/json_adapter.cc | | Remove the unused parameter "options", make it unnamed, or declare it "[[maybe_unused]]". | Production | Nein | +| AZ190QF1STzC4JOHOn-B | Issue | cpp:S995 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Make the type of this parameter a pointer-to-const. The current type of "sink" is "class modsecurity::RequestBodyProcessor::JsonEventSink *". | Production | Nein | +| AZ190QF1STzC4JOHOn9_ | Issue | cpp:S6009 | MINOR | CLOSED | src/request_body_processor/json_adapter.cc | | Replace this const reference to "std::string" by a "std::string_view". | Production | Nein | +| AZ190QF8STzC4JOHOn-C | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_adapter.h | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QGbSTzC4JOHOn-P | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_backend.h | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QFsSTzC4JOHOn9v | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QFsSTzC4JOHOn9w | Issue | cpp:S3776 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 106 | Refactor this function to reduce its Cognitive Complexity from 33 to the 25 allowed. | Production | Ja | +| AZ190QFsSTzC4JOHOn9u | Issue | cpp:S3562 | MAJOR | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 202 | 4 enumeration values not handled in switch: 'int64_value', 'uint64_value', 'half_value'... | Production | Ja | +| AZ190QFsSTzC4JOHOn9z | Issue | cpp:S3776 | CRITICAL | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Refactor this function to reduce its Cognitive Complexity from 41 to the 25 allowed. | Production | Nein | +| AZ190QFsSTzC4JOHOn92 | Issue | cpp:S1121 | MAJOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Extract the assignment from this expression. | Production | Nein | +| AZ190QFsSTzC4JOHOn9x | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "current" inside the if statement. | Production | Nein | +| AZ190QFsSTzC4JOHOn93 | Issue | cpp:S1121 | MAJOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Extract the assignment from this expression. | Production | Nein | +| AZ190QFsSTzC4JOHOn94 | Issue | cpp:S3776 | CRITICAL | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Refactor this function to reduce its Cognitive Complexity from 43 to the 25 allowed. | Production | Nein | +| AZ190QFsSTzC4JOHOn90 | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 379 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QFsSTzC4JOHOn9y | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "escaped" inside the if statement. | Production | Nein | +| AZ190QFsSTzC4JOHOn91 | Issue | cpp:S134 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 388 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Production | Ja | +| AZ190QFsSTzC4JOHOn97 | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "sync_detail" inside the if statement. | Production | Nein | +| AZ190QFsSTzC4JOHOn96 | Issue | cpp:S6009 | MINOR | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 546 | Replace this const reference to "std::string" by a "std::string_view". | Production | Ja | +| AZ190QFsSTzC4JOHOn95 | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "end" inside the if statement. | Production | Nein | +| AZ190QFsSTzC4JOHOn98 | Issue | cpp:S3776 | CRITICAL | OPEN | src/request_body_processor/json_backend_jsoncons.cc | 577 | Refactor this function to reduce its Cognitive Complexity from 48 to the 25 allowed. | Production | Ja | +| AZ190QFsSTzC4JOHOn99 | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_jsoncons.cc | | Use the init-statement to declare "result" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-Q | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QGkSTzC4JOHOn-R | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-S | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-T | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-U | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-V | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "result" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-W | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-X | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "result" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-Y | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-Z | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-a | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "result" inside the if statement. | Production | Nein | +| AZ190QGkSTzC4JOHOn-b | Issue | cpp:S6004 | MINOR | CLOSED | src/request_body_processor/json_backend_simdjson.cc | | Use the init-statement to declare "sink_status" inside the if statement. | Production | Nein | +| AZ190QHkSTzC4JOHOn-c | Issue | cpp:S7121 | MAJOR | CLOSED | src/transaction.cc | | Remove this redundant call to "c_str" when initializing a const "std::string" reference parameter. | Production | Nein | +| AZ190QA8STzC4JOHOn9j | Issue | cpp:S5812 | MINOR | CLOSED | src/utils/json_writer.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QA8STzC4JOHOn9h | Issue | cpp:S3230 | MAJOR | CLOSED | src/utils/json_writer.cc | | Remove this use of the constructor's initializer list for data member "m_output". It is redundant with default initialization behavior. | Production | Nein | +| AZ190QA8STzC4JOHOn9i | Issue | cpp:S3230 | MAJOR | CLOSED | src/utils/json_writer.cc | | Remove this use of the constructor's initializer list for data member "m_stack". It is redundant with default initialization behavior. | Production | Nein | +| AZ190QA8STzC4JOHOn9k | Issue | cpp:S5945 | MAJOR | OPEN | src/utils/json_writer.cc | 155 | Use "std::string" instead of a C-style char array. | Production | Ja | +| AZ190QA8STzC4JOHOn9l | Issue | cpp:S3628 | MINOR | CLOSED | src/utils/json_writer.cc | | Convert this string literal to a raw string literal. | Production | Nein | +| AZ190QA8STzC4JOHOn9m | Issue | cpp:S3628 | MINOR | CLOSED | src/utils/json_writer.cc | | Convert this string literal to a raw string literal. | Production | Nein | +| AZ190QA8STzC4JOHOn9n | Issue | cpp:S6022 | MAJOR | OPEN | src/utils/json_writer.cc | 183 | Use "std::byte" for byte-oriented data manipulation. | Production | Ja | +| AZ190QA8STzC4JOHOn9o | Issue | cpp:S6022 | MAJOR | OPEN | src/utils/json_writer.cc | 184 | Use "std::byte" for byte-oriented data manipulation. | Production | Ja | +| AZ190QD4STzC4JOHOn9p | Issue | cpp:S5812 | MINOR | CLOSED | src/utils/json_writer.h | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QIVSTzC4JOHOn-f | Issue | cpp:S5812 | MINOR | CLOSED | test/common/json.h | | Concatenate this namespace with the nested one. | Test | Nein | +| AZ190QIVSTzC4JOHOn-g | Issue | cpp:S2807 | MAJOR | OPEN | test/common/json.h | 78 | Make this member overloaded operator a hidden friend. | Test | Ja | +| AZ190QIVSTzC4JOHOn-h | Issue | cpp:S2807 | MAJOR | OPEN | test/common/json.h | 123 | Make this member overloaded operator a hidden friend. | Test | Ja | +| AZ190QIVSTzC4JOHOn-i | Issue | cpp:S1181 | MAJOR | OPEN | test/common/json.h | 219 | Catch a more specific exception instead of a generic one. | Test | Ja | +| AZ190QIVSTzC4JOHOn-j | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 232 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-k | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 242 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-l | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 252 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-m | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 262 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-n | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 269 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-o | Issue | cpp:S995 | MINOR | OPEN | test/common/json.h | 279 | Make the type of this parameter a pointer-to-const. The current type of "error" is "std::string *". | Test | Ja | +| AZ190QIVSTzC4JOHOn-p | Issue | cpp:S1181 | MAJOR | OPEN | test/common/json.h | 309 | Catch a more specific exception instead of a generic one. | Test | Ja | +| AZ190QIVSTzC4JOHOn-q | Issue | cpp:S1181 | MAJOR | OPEN | test/common/json.h | 321 | Catch a more specific exception instead of a generic one. | Test | Ja | +| AZ190QIVSTzC4JOHOn-r | Issue | cpp:S1181 | MAJOR | OPEN | test/common/json.h | 333 | Catch a more specific exception instead of a generic one. | Test | Ja | +| AZ190QI2STzC4JOHOn-s | Issue | cpp:S134 | CRITICAL | OPEN | test/common/modsecurity_test.cc | 89 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements. | Test | Ja | +| AZ190QKvSTzC4JOHOn-x | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-y | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-z | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-0 | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-1 | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-2 | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-3 | Issue | cpp:S5415 | MAJOR | CLOSED | test/regression/regression_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QKvSTzC4JOHOn-4 | Issue | cpp:S5817 | MAJOR | OPEN | test/regression/regression_test.cc | 431 | This function should be declared "const". | Test | Ja | +| AZ190QKvSTzC4JOHOn-v | Issue | cpp:S5274 | MAJOR | CLOSED | test/regression/regression_test.cc | | moving a temporary object prevents copy elision | Test | Nein | +| AZ190QKvSTzC4JOHOn-w | Issue | cpp:S5274 | MAJOR | CLOSED | test/regression/regression_test.cc | | moving a temporary object prevents copy elision | Test | Nein | +| AZ190QKvSTzC4JOHOn-5 | Issue | cpp:S1481 | MINOR | CLOSED | test/regression/regression_test.cc | | Remove the unused lambda capture "writer". | Test | Nein | +| AZ190QJKSTzC4JOHOn-t | Issue | cpp:S5415 | MAJOR | CLOSED | test/unit/unit_test.cc | | The result of "std::move" should not be passed as a const reference. | Test | Nein | +| AZ190QJYSTzC4JOHOn-u | Issue | cpp:S836 | MAJOR | CLOSED | test/unit/unit_test.h | | Value assigned to field 'ret' in implicit constructor is garbage or undefined | Test | Nein | +| AZ190QIESTzC4JOHOn-d | Issue | cpp:S886 | MINOR | OPEN | src/modsecurity.cc | 232 | Refactor this loop so that it is less error-prone. | Production | Ja | +| AZ190QIESTzC4JOHOn-e | Issue | cpp:S886 | MINOR | OPEN | src/modsecurity.cc | 288 | Refactor this loop so that it is less error-prone. | Production | Ja | +| AZ190QGTSTzC4JOHOn-F | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json.cc | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ190QEtSTzC4JOHOn9s | Issue | cpp:S5812 | MINOR | CLOSED | src/request_body_processor/json.h | | Concatenate this namespace with the nested one. | Production | Nein | +| AZ1-dn4cXISY38E6Txog | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | +| AZ1-dn4cXISY38E6Txoi | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | +| AZ1-dn4cXISY38E6Txoj | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | +| AZ1-dn4cXISY38E6Txok | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | +| AZ1-dn4cXISY38E6Txol | Issue | cpp:S4962 | CRITICAL | CLOSED | src/utils/msc_tree.cc | | Use the "nullptr" literal. | Production | Nein | + +# Tabelle: Nur offene Befunde +| ID | Kategorie | Regelcode | Severity | Datei | Zeile | Kurzbeschreibung | Konkreter Fix (technisch) | Risiko der Änderung | +|---|---|---|---|---|---:|---|---|---| +| AZ2HqeBsWym3B0O6okyS | Issue | cpp:S5952 | MINOR | test/benchmark/json_benchmark.cc | 71 | Add a using-declaration to this derived class to inherit the constructors of "runtime_error", and remove the ones you manually duplicated | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Niedrig | +| AZ2HqeBsWym3B0O6okyT | Issue | cpp:S6004 | MINOR | test/benchmark/json_benchmark.cc | 144 | Use the init-statement to declare "current" inside the if statement | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Niedrig | +| AZ2DWE24t-zbsGOGdN_K | Issue | cpp:S4998 | MAJOR | test/benchmark/json_benchmark.cc | 316 | Replace this use of "unique_ptr" by a raw pointer or a reference (possibly const) | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ2DVDgODPiZK5yPV1-J | Issue | cpp:S1188 | MAJOR | test/regression/regression_test.cc | 235 | This lambda has 23 lines, which is greater than the 20 lines authorized | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ2DR4Fykud7vHWq_QVC | Issue | cpp:S6009 | MINOR | src/request_body_processor/json_adapter.cc | 58 | Replace this const reference to "std::string" by a "std::string_view" | `const std::string&`-Parameter auf `std::string_view` umstellen. | Niedrig | +| AZ2DR4Fykud7vHWq_QVD | Issue | cpp:S995 | MINOR | src/request_body_processor/json_adapter.cc | 59 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ2DR4Fykud7vHWq_QVE | Issue | cpp:S995 | MINOR | src/request_body_processor/json_adapter.cc | 81 | Make the type of this parameter a reference-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ2CwcnoK0fgB4uOpVK4 | Issue | cpp:S5817 | MAJOR | src/request_body_processor/json_backend_simdjson.cc | 450 | This function should be declared "const" | Methode als `const` markieren, wenn Objektzustand nicht geändert wird. | Mittel | +| AZ2CBI6Kkud7vHWq0tqj | Issue | cpp:S6022 | MAJOR | src/operators/validate_byte_range.cc | 156 | Use "std::byte" for byte-oriented data manipulation | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ2CA_xuGCkM6OziEPeu | Issue | cpp:S4144 | MAJOR | test/unit/json_backend_depth_tests.cc | 50 | Update this method so that its implementation is not identical to on_key | Duplizierte Methode entfernen oder Implementierung eindeutig differenzieren. | Mittel | +| AZ2BthMEO-njQfcv_7WG | Issue | cpp:S3776 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 362 | Refactor this function to reduce its Cognitive Complexity from 41 to the 25 allowed | Funktion aufteilen, Guard-Clauses extrahieren, Hilfsfunktionen einführen bis Cognitive Complexity <= 25. | Mittel | +| AZ2BthMEO-njQfcv_7WJ | Issue | cpp:S3776 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 426 | Refactor this function to reduce its Cognitive Complexity from 43 to the 25 allowed | Funktion aufteilen, Guard-Clauses extrahieren, Hilfsfunktionen einführen bis Cognitive Complexity <= 25. | Mittel | +| AZ2BthMEO-njQfcv_7WL | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 634 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ1-dn-nXISY38E6Txop | Issue | cpp:S5025 | CRITICAL | src/request_body_processor/json.cc | 57 | Rewrite the code so that you no longer need this "delete" | Rohes `delete` durch `std::unique_ptr`/RAII ersetzen. | Mittel | +| AZ1-dn9hXISY38E6Txoo | Issue | cpp:S5421 | CRITICAL | src/request_body_processor/json_instrumentation.cc | 12 | Global variables should be const | Globale Variable als `const` oder kapseln (z.B. in Funktion/Singleton) und unveränderlich halten. | Mittel | +| AZ1-doCWXISY38E6TxpK | Issue | cpp:S6009 | MINOR | test/benchmark/json_benchmark.cc | 321 | Replace this const reference to "std::string" by a "std::string_view" | `const std::string&`-Parameter auf `std::string_view` umstellen. | Niedrig | +| AZ1-doCWXISY38E6TxpR | Issue | cpp:S6009 | MINOR | test/benchmark/json_benchmark.cc | 419 | Replace this const reference to "std::string" by a "std::string_view" | `const std::string&`-Parameter auf `std::string_view` umstellen. | Niedrig | +| AZ1-doCWXISY38E6TxpU | Issue | cpp:S6009 | MINOR | test/benchmark/json_benchmark.cc | 486 | Replace this const reference to "std::string" by a "std::string_view" | `const std::string&`-Parameter auf `std::string_view` umstellen. | Niedrig | +| AZ190QEMSTzC4JOHOn9q | Issue | cpp:S6022 | MAJOR | src/operators/validate_byte_range.cc | 72 | Use "std::byte" for byte-oriented data manipulation | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ190QGTSTzC4JOHOn-D | Issue | cpp:S3230 | MAJOR | src/request_body_processor/json.cc | 79 | Do not use the constructor's initializer list for data member "m_data" | Member im Konstruktor-Body initialisieren statt Initializer-Liste für Zuweisung. | Mittel | +| AZ190QGTSTzC4JOHOn-H | Issue | cpp:S3776 | CRITICAL | src/request_body_processor/json.cc | 121 | Refactor this function to reduce its Cognitive Complexity from 37 to the 25 allowed | Funktion aufteilen, Guard-Clauses extrahieren, Hilfsfunktionen einführen bis Cognitive Complexity <= 25. | Mittel | +| AZ190QGTSTzC4JOHOn-I | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json.cc | 135 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QGTSTzC4JOHOn-J | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json.cc | 142 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QGTSTzC4JOHOn-K | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json.cc | 149 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QGTSTzC4JOHOn-L | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json.cc | 156 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QGTSTzC4JOHOn-M | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json.cc | 163 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QEtSTzC4JOHOn9t | Issue | cpp:S3624 | CRITICAL | src/request_body_processor/json.h | 52 | Customize this class' copy constructor to participate in resource management | Copy-/Move-Konstruktor und Assignment gemäß Rule of 5 korrekt definieren oder löschen. | Mittel | +| AZ190QFsSTzC4JOHOn9w | Issue | cpp:S3776 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 106 | Refactor this function to reduce its Cognitive Complexity from 33 to the 25 allowed | Funktion aufteilen, Guard-Clauses extrahieren, Hilfsfunktionen einführen bis Cognitive Complexity <= 25. | Mittel | +| AZ190QFsSTzC4JOHOn9u | Issue | cpp:S3562 | MAJOR | src/request_body_processor/json_backend_jsoncons.cc | 202 | 4 enumeration values not handled in switch: 'int64_value', 'uint64_value', 'half_value' | `switch` um fehlende Enum-Cases ergänzen (int64_value, uint64_value, half_value, byte_string_value). | Mittel | +| AZ190QFsSTzC4JOHOn90 | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 379 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QFsSTzC4JOHOn91 | Issue | cpp:S134 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 388 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QFsSTzC4JOHOn96 | Issue | cpp:S6009 | MINOR | src/request_body_processor/json_backend_jsoncons.cc | 546 | Replace this const reference to "std::string" by a "std::string_view" | `const std::string&`-Parameter auf `std::string_view` umstellen. | Niedrig | +| AZ190QFsSTzC4JOHOn98 | Issue | cpp:S3776 | CRITICAL | src/request_body_processor/json_backend_jsoncons.cc | 577 | Refactor this function to reduce its Cognitive Complexity from 48 to the 25 allowed | Funktion aufteilen, Guard-Clauses extrahieren, Hilfsfunktionen einführen bis Cognitive Complexity <= 25. | Mittel | +| AZ190QA8STzC4JOHOn9k | Issue | cpp:S5945 | MAJOR | src/utils/json_writer.cc | 155 | Use "std::string" instead of a C-style char array | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ190QA8STzC4JOHOn9n | Issue | cpp:S6022 | MAJOR | src/utils/json_writer.cc | 183 | Use "std::byte" for byte-oriented data manipulation | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ190QA8STzC4JOHOn9o | Issue | cpp:S6022 | MAJOR | src/utils/json_writer.cc | 184 | Use "std::byte" for byte-oriented data manipulation | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Mittel | +| AZ190QIVSTzC4JOHOn-g | Issue | cpp:S2807 | MAJOR | test/common/json.h | 78 | Make this member overloaded operator a hidden friend | Operatorüberladung als hidden friend außerhalb der Klasse definieren. | Mittel | +| AZ190QIVSTzC4JOHOn-h | Issue | cpp:S2807 | MAJOR | test/common/json.h | 123 | Make this member overloaded operator a hidden friend | Operatorüberladung als hidden friend außerhalb der Klasse definieren. | Mittel | +| AZ190QIVSTzC4JOHOn-i | Issue | cpp:S1181 | MAJOR | test/common/json.h | 219 | Catch a more specific exception instead of a generic one | Spezifischere Exception-Typen catchen. | Mittel | +| AZ190QIVSTzC4JOHOn-j | Issue | cpp:S995 | MINOR | test/common/json.h | 232 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-k | Issue | cpp:S995 | MINOR | test/common/json.h | 242 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-l | Issue | cpp:S995 | MINOR | test/common/json.h | 252 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-m | Issue | cpp:S995 | MINOR | test/common/json.h | 262 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-n | Issue | cpp:S995 | MINOR | test/common/json.h | 269 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-o | Issue | cpp:S995 | MINOR | test/common/json.h | 279 | Make the type of this parameter a pointer-to-const | Parameter als `const T*` bzw. `const T&` deklarieren. | Niedrig | +| AZ190QIVSTzC4JOHOn-p | Issue | cpp:S1181 | MAJOR | test/common/json.h | 309 | Catch a more specific exception instead of a generic one | Spezifischere Exception-Typen catchen. | Mittel | +| AZ190QIVSTzC4JOHOn-q | Issue | cpp:S1181 | MAJOR | test/common/json.h | 321 | Catch a more specific exception instead of a generic one | Spezifischere Exception-Typen catchen. | Mittel | +| AZ190QIVSTzC4JOHOn-r | Issue | cpp:S1181 | MAJOR | test/common/json.h | 333 | Catch a more specific exception instead of a generic one | Spezifischere Exception-Typen catchen. | Mittel | +| AZ190QI2STzC4JOHOn-s | Issue | cpp:S134 | CRITICAL | test/common/modsecurity_test.cc | 89 | Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Verschachtelung reduzieren: frühzeitige Returns und Hilfsfunktionen. | Mittel | +| AZ190QKvSTzC4JOHOn-4 | Issue | cpp:S5817 | MAJOR | test/regression/regression_test.cc | 431 | This function should be declared "const" | Methode als `const` markieren, wenn Objektzustand nicht geändert wird. | Mittel | +| AZ190QIESTzC4JOHOn-d | Issue | cpp:S886 | MINOR | src/modsecurity.cc | 232 | Refactor this loop so that it is less error-prone | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Niedrig | +| AZ190QIESTzC4JOHOn-e | Issue | cpp:S886 | MINOR | src/modsecurity.cc | 288 | Refactor this loop so that it is less error-prone | Regelspezifische Refaktorierung gemäß Sonar-Regelbeschreibung umsetzen. | Niedrig | + +# Tabelle: JSON-Dateien (nur offene) +| Datei | Anzahl offener Befunde | Regelcodes | Problem | Minimaler Fix | +|---|---:|---|---|---| +| src/request_body_processor/json.cc | 8 | cpp:S134, cpp:S3230, cpp:S3776, cpp:S5025 | Do not use the constructor's initializer list for data member "m_data"; Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Große Parser-Funktionen in kleinere Handler aufteilen. | +| src/request_body_processor/json.h | 1 | cpp:S3624 | Customize this class' copy constructor to participate in resource management | Regelspezifische Minimalanpassung durchführen. | +| src/request_body_processor/json_adapter.cc | 3 | cpp:S6009, cpp:S995 | Make the type of this parameter a pointer-to-const; Make the type of this parameter a reference-to-const | String-Referenzen in `std::string_view` ändern. | +| src/request_body_processor/json_backend_jsoncons.cc | 9 | cpp:S134, cpp:S3562, cpp:S3776, cpp:S6009 | 4 enumeration values not handled in switch: 'int64_value', 'uint64_value', 'half_value'; Refactor this code to not nest more than 3 if\|for\|do\|while\|switch statements | Große Parser-Funktionen in kleinere Handler aufteilen. | +| src/request_body_processor/json_backend_simdjson.cc | 1 | cpp:S5817 | This function should be declared "const" | Regelspezifische Minimalanpassung durchführen. | +| src/request_body_processor/json_instrumentation.cc | 1 | cpp:S5421 | Global variables should be const | Regelspezifische Minimalanpassung durchführen. | +| test/common/json.h | 12 | cpp:S1181, cpp:S2807, cpp:S995 | Catch a more specific exception instead of a generic one; Make the type of this parameter a pointer-to-const | Pointer/Referenzen const-korrekt machen. | +| test/unit/json_backend_depth_tests.cc | 1 | cpp:S4144 | Update this method so that its implementation is not identical to on_key | Regelspezifische Minimalanpassung durchführen. | + +# Summenübersicht +- Gesamtanzahl aller Befunde (Issue + Hotspot + Gate): 208 +- Gesamtanzahl Sonar-Issues: 207 +- Anzahl offene Befunde (Issues+Hotspots): 52 +- Anzahl geschlossene Befunde (Issues+Hotspots): 155 +- Security Hotspots: offen 0, reviewed 0 +- BLOCKER: 0 +- CRITICAL: 29 +- MAJOR: 104 +- MINOR: 73 +- INFO: 1 + +# Grenzen der Analyse +- Sonar-Issues, Quality Gate, Measures und Hotspots wurden live über SonarCloud API mit `pullRequest=3540` abgerufen. +- Eine vollständige Issue-Liste wurde technisch abgerufen (`total=207`, `ps=500`), daher **keine** Teilmengenkennzeichnung nötig. \ No newline at end of file diff --git a/src/request_body_processor/json.cc b/src/request_body_processor/json.cc index f34527682..6f20dacb9 100644 --- a/src/request_body_processor/json.cc +++ b/src/request_body_processor/json.cc @@ -57,8 +57,7 @@ JsonSinkStatus endContainer(std::deque *containers, delete container; if (containers->empty() == false) { - JSONContainerArray *array = dynamic_cast( - containers->back()); + auto *array = dynamic_cast(containers->back()); if (array != nullptr) { array->m_elementCounter++; } diff --git a/src/request_body_processor/json_adapter.cc b/src/request_body_processor/json_adapter.cc index 32d321f4b..9aeb3cc78 100644 --- a/src/request_body_processor/json_adapter.cc +++ b/src/request_body_processor/json_adapter.cc @@ -55,8 +55,9 @@ JsonParseResult normalizeResult(JsonParseResult result) { } // namespace -JsonParseResult JSONAdapter::parse(std::string &input, - JsonEventSink *sink, const JsonBackendParseOptions &options) const { +JsonParseResult JSONAdapter::parseImpl(const std::string &input, + JsonEventSink *sink, + const JsonBackendParseOptions &options [[maybe_unused]]) const { if (sink == nullptr) { return makeResult(JsonParseStatus::InternalError, JsonSinkStatus::InternalError, "JSON event sink is null."); @@ -77,26 +78,16 @@ JsonParseResult JSONAdapter::parse(std::string &input, #endif } -JsonParseResult JSONAdapter::parse(const std::string &input, - JsonEventSink *sink, const JsonBackendParseOptions &options) const { - if (sink == nullptr) { - return makeResult(JsonParseStatus::InternalError, - JsonSinkStatus::InternalError, "JSON event sink is null."); - } - - if (input.empty()) { - return makeResult(JsonParseStatus::Ok); - } +JsonParseResult JSONAdapter::parse(std::string &input, + JsonEventSink *sink, + const JsonBackendParseOptions &options) const { + return parseImpl(input, sink, options); +} -#if defined(MSC_JSON_BACKEND_SIMDJSON) - return normalizeResult(parseDocumentWithSimdjson(input, sink, options)); -#elif defined(MSC_JSON_BACKEND_JSONCONS) - return normalizeResult(parseDocumentWithJsoncons(input, sink, options)); -#else - return makeResult(JsonParseStatus::InternalError, - JsonSinkStatus::InternalError, - "ModSecurity was built without a selected JSON backend."); -#endif +JsonParseResult JSONAdapter::parse(const std::string &input, + JsonEventSink *sink, + const JsonBackendParseOptions &options) const { + return parseImpl(input, sink, options); } } // namespace modsecurity::RequestBodyProcessor diff --git a/src/request_body_processor/json_adapter.h b/src/request_body_processor/json_adapter.h index a260eb629..22a6e87cf 100644 --- a/src/request_body_processor/json_adapter.h +++ b/src/request_body_processor/json_adapter.h @@ -25,10 +25,16 @@ namespace modsecurity::RequestBodyProcessor { class JSONAdapter { public: JsonParseResult parse(std::string &input, JsonEventSink *sink, - const JsonBackendParseOptions &options = JsonBackendParseOptions()) const; + const JsonBackendParseOptions &options [[maybe_unused]] + = JsonBackendParseOptions()) const; JsonParseResult parse(const std::string &input, JsonEventSink *sink, - const JsonBackendParseOptions &options = JsonBackendParseOptions()) const; + const JsonBackendParseOptions &options [[maybe_unused]] + = JsonBackendParseOptions()) const; + + private: + JsonParseResult parseImpl(const std::string &input, JsonEventSink *sink, + const JsonBackendParseOptions &options [[maybe_unused]]) const; }; } // namespace modsecurity::RequestBodyProcessor diff --git a/src/request_body_processor/json_backend_jsoncons.cc b/src/request_body_processor/json_backend_jsoncons.cc index 44399d4c2..2d8d9590d 100644 --- a/src/request_body_processor/json_backend_jsoncons.cc +++ b/src/request_body_processor/json_backend_jsoncons.cc @@ -372,7 +372,8 @@ class RawJsonTokenCursor { (*offset)++; while (*offset < m_input.size()) { - char current = m_input[(*offset)++]; + char current = m_input[*offset]; + (*offset)++; if (current == '\\') { if (*offset >= m_input.size()) { if (detail != nullptr) { @@ -381,7 +382,9 @@ class RawJsonTokenCursor { return false; } - if (char escaped = m_input[(*offset)++]; escaped == 'u') { + char escaped = m_input[*offset]; + (*offset)++; + if (escaped == 'u') { for (int i = 0; i < 4; i++) { if (*offset >= m_input.size() || !isHexDigit(m_input[*offset])) { diff --git a/src/transaction.cc b/src/transaction.cc index 953115db8..935da0246 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -1601,7 +1601,7 @@ std::string Transaction::toJSON(int parts) { m_variableRequestHeaders.resolve(&l); for (auto &h : l) { std::string header_name = - utils::string::toHexIfNeeded(h->getKey().c_str()); + utils::string::toHexIfNeeded(h->getKey()); std::string header_value = utils::string::toHexIfNeeded(h->getValue()); addString(header_name, header_value); diff --git a/src/utils/json_writer.cc b/src/utils/json_writer.cc index dea528dc2..4cd7b1ba5 100644 --- a/src/utils/json_writer.cc +++ b/src/utils/json_writer.cc @@ -21,9 +21,7 @@ namespace modsecurity::utils { JsonWriter::JsonWriter(bool pretty, std::string indent) - : m_output(), - m_stack(), - m_pretty(pretty), + : m_pretty(pretty), m_indent(std::move(indent)) { } void JsonWriter::start_object() { diff --git a/test/benchmark/benchmark.cc b/test/benchmark/benchmark.cc index a502150ea..c4ce4635b 100644 --- a/test/benchmark/benchmark.cc +++ b/test/benchmark/benchmark.cc @@ -16,15 +16,24 @@ #include #include +#include #include #include +#include #include "modsecurity/rules_set.h" #include "modsecurity/modsecurity.h" using modsecurity::Transaction; -char request_uri[] = "/test.pl?param1=test¶2=test2"; +namespace { + +constexpr const char *kRequestUri = "/test.pl?param1=test¶2=test2"; +constexpr const char *kClientIp = "198.51.100.10"; // RFC 5737 documentation range +constexpr const char *kServerIp = "198.51.100.20"; // RFC 5737 documentation range +constexpr const char *kRulesFile = "basic_rules.conf"; + +} // namespace unsigned char response_body[] = "" \ "\n\r" \ @@ -38,10 +47,6 @@ unsigned char response_body[] = "" \ " \n\r" \ "\n\r"; -char ip[] = "200.249.12.31"; - -char rules_file[] = "basic_rules.conf"; - const char* const help_message = "Usage: benchmark [num_iterations|-h|-?|--help]"; int main(int argc, const char *argv[]) { @@ -79,23 +84,26 @@ int main(int argc, const char *argv[]) { " (ModSecurity benchmark utility)"); rules = new modsecurity::RulesSet(); - if (rules->loadFromUri(rules_file) < 0) { + if (rules->loadFromUri(kRulesFile) < 0) { std::cout << "Problems loading the rules..." << std::endl; std::cout << rules->m_parserError.str() << std::endl; return -1; } + // Start timing after one-time setup to measure only transaction processing. + const auto benchmark_start = std::chrono::steady_clock::now(); + for (unsigned long long i = 0; i < NUM_REQUESTS; i++) { //std::cout << "Proceeding with request " << i << std::endl; Transaction *modsecTransaction = new Transaction(modsec, rules, NULL); - modsecTransaction->processConnection(ip, 12345, "127.0.0.1", 80); + modsecTransaction->processConnection(kClientIp, 12345, kServerIp, 80); if (modsecTransaction->intervention(&it)) { std::cout << "There is an intervention" << std::endl; goto next_request; } - modsecTransaction->processURI(request_uri, "GET", "1.1"); + modsecTransaction->processURI(kRequestUri, "GET", "1.1"); if (modsecTransaction->intervention(&it)) { std::cout << "There is an intervention" << std::endl; goto next_request; @@ -173,4 +181,19 @@ int main(int argc, const char *argv[]) { delete rules; delete modsec; + + const auto elapsed = std::chrono::duration_cast( + std::chrono::steady_clock::now() - benchmark_start); + const long double elapsed_seconds = + static_cast(elapsed.count()) / 1000000000.0L; + const long double avg_tx_ns = static_cast(elapsed.count()) + / static_cast(NUM_REQUESTS); + const long double tx_per_sec = static_cast(NUM_REQUESTS) + / elapsed_seconds; + + std::cout << std::fixed << std::setprecision(2); + std::cout << "Summary:\n"; + std::cout << " elapsed_seconds: " << elapsed_seconds << "\n"; + std::cout << " avg_transaction_ns: " << avg_tx_ns << "\n"; + std::cout << " throughput_tx_per_sec: " << tx_per_sec << "\n"; } diff --git a/test/benchmark/json_benchmark.cc b/test/benchmark/json_benchmark.cc index e37f9cb41..286fd13b4 100644 --- a/test/benchmark/json_benchmark.cc +++ b/test/benchmark/json_benchmark.cc @@ -48,6 +48,8 @@ constexpr std::size_t kDefaultTargetBytes = 1048576; constexpr std::size_t kDefaultDepth = 512; constexpr unsigned long long kDefaultIterations = 100; constexpr const char *kRulesFileName = "json_benchmark_rules.conf"; +constexpr const char *kClientIp = "198.51.100.10"; // RFC 5737 documentation range +constexpr const char *kServerIp = "198.51.100.20"; // RFC 5737 documentation range struct Options { std::string scenario; @@ -66,7 +68,13 @@ struct Metrics { unsigned long long parse_error_count{0}; }; -const char *usage_message = +class JsonBenchmarkError : public std::runtime_error { + public: + explicit JsonBenchmarkError(const std::string &message) + : std::runtime_error(message) { } +}; + +const char *const usage_message = "Usage: json_benchmark --scenario NAME [--iterations N] " "[--target-bytes N] [--depth N] [--include-invalid] [--output json]"; @@ -90,85 +98,89 @@ std::uint64_t elapsedNanos(Clock::time_point start_time) { Clock::now() - start_time).count()); } -std::size_t parseSize(const char *value, const char *flag_name) { +unsigned long long parseUnsignedLongLong(const char *value, + const char *flag_name, bool allow_zero) { errno = 0; char *end = nullptr; const unsigned long long parsed = std::strtoull(value, &end, 10); - if (errno != 0 || end == value || *end != '\0') { - throw std::runtime_error(std::string("invalid numeric value for ") + if (errno != 0 || end == value || *end != '\0' + || (!allow_zero && parsed == 0)) { + throw JsonBenchmarkError(std::string("invalid numeric value for ") + flag_name + ": " + value); } + return parsed; +} + +std::size_t parseSize(const char *value, const char *flag_name) { + const unsigned long long parsed = + parseUnsignedLongLong(value, flag_name, true); if (parsed > std::numeric_limits::max()) { - throw std::runtime_error(std::string("value too large for ") + throw JsonBenchmarkError(std::string("value too large for ") + flag_name + ": " + value); } return static_cast(parsed); } unsigned long long parseIterations(const char *value) { - errno = 0; - char *end = nullptr; - const unsigned long long parsed = std::strtoull(value, &end, 10); - if (errno != 0 || end == value || *end != '\0' || parsed == 0) { - throw std::runtime_error(std::string("invalid numeric value for --iterations: ") - + value); + return parseUnsignedLongLong(value, "--iterations", false); +} + +const char *requireOptionValue(int argc, const char *argv[], int *index, + const char *option_name) { + if (*index + 1 >= argc) { + throw JsonBenchmarkError(std::string("missing value for ") + + option_name); } - return parsed; + *index += 1; + return argv[*index]; } Options parseOptions(int argc, const char *argv[]) { Options options; - for (int i = 1; i < argc; i++) { + int i = 1; + while (i < argc) { const std::string current(argv[i]); if (current == "-h" || current == "-?" || current == "--help") { std::cout << usage_message << std::endl; std::exit(0); } else if (current == "--scenario") { - if (i + 1 >= argc) { - throw std::runtime_error("missing value for --scenario"); - } - options.scenario.assign(argv[++i]); + options.scenario.assign( + requireOptionValue(argc, argv, &i, "--scenario")); } else if (current == "--iterations") { - if (i + 1 >= argc) { - throw std::runtime_error("missing value for --iterations"); - } - options.iterations = parseIterations(argv[++i]); + options.iterations = parseIterations( + requireOptionValue(argc, argv, &i, "--iterations")); } else if (current == "--target-bytes") { - if (i + 1 >= argc) { - throw std::runtime_error("missing value for --target-bytes"); - } - options.target_bytes = parseSize(argv[++i], "--target-bytes"); + options.target_bytes = parseSize( + requireOptionValue(argc, argv, &i, "--target-bytes"), + "--target-bytes"); } else if (current == "--depth") { - if (i + 1 >= argc) { - throw std::runtime_error("missing value for --depth"); - } - options.depth = parseSize(argv[++i], "--depth"); + options.depth = parseSize( + requireOptionValue(argc, argv, &i, "--depth"), "--depth"); } else if (current == "--include-invalid") { options.include_invalid = true; } else if (current == "--output") { - if (i + 1 >= argc) { - throw std::runtime_error("missing value for --output"); - } - if (const std::string output_format(argv[++i]); + if (const std::string output_format( + requireOptionValue(argc, argv, &i, "--output")); output_format != "json") { - throw std::runtime_error("unsupported output format: " + throw JsonBenchmarkError("unsupported output format: " + output_format); } options.output_json = true; } else { - throw std::runtime_error("unknown option: " + current); + throw JsonBenchmarkError("unknown option: " + current); } + i++; } if (options.scenario.empty()) { - throw std::runtime_error("missing required --scenario"); + throw JsonBenchmarkError("missing required --scenario"); } if (const bool is_invalid_scenario = options.scenario == "truncated" || options.scenario == "malformed"; is_invalid_scenario && !options.include_invalid) { - throw std::runtime_error( + throw JsonBenchmarkError( "invalid JSON scenarios require --include-invalid"); } @@ -298,7 +310,7 @@ std::string buildScenarioBody(const Options &options) { return body; } - throw std::runtime_error("unsupported scenario: " + options.scenario); + throw JsonBenchmarkError("unsupported scenario: " + options.scenario); } bool isResolvedZero(const std::unique_ptr &value) { @@ -314,15 +326,14 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec, iteration++) { const auto total_start = Clock::now(); modsecurity::Transaction transaction(modsec, rules, nullptr); - transaction.processConnection("200.249.12.31", 12345, - "127.0.0.1", 80); + transaction.processConnection(kClientIp, 12345, kServerIp, 80); transaction.processURI("/json-benchmark", "POST", "1.1"); transaction.addRequestHeader("Host", "localhost"); transaction.addRequestHeader("User-Agent", "ModSecurity-json-benchmark/1.0"); transaction.addRequestHeader("Content-Type", "application/json"); const std::string content_length = std::to_string(body.size()); - transaction.addRequestHeader("Content-Length", content_length.c_str()); + transaction.addRequestHeader("Content-Length", content_length); transaction.processRequestHeaders(); const auto append_start = Clock::now(); @@ -330,13 +341,13 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec, reinterpret_cast(body.data()), body.size()); metrics.append_request_body_ns += elapsedNanos(append_start); if (append_ok == 0) { - throw std::runtime_error( + throw JsonBenchmarkError( "appendRequestBody reported partial body processing"); } const auto process_start = Clock::now(); if (!transaction.processRequestBody()) { - throw std::runtime_error("processRequestBody returned false"); + throw JsonBenchmarkError("processRequestBody returned false"); } metrics.process_request_body_ns += elapsedNanos(process_start); metrics.total_transaction_ns += elapsedNanos(total_start); @@ -347,7 +358,7 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec, transaction.m_variableReqbodyProcessorError.resolveFirst(); if (!reqbody_error || !processor_error) { - throw std::runtime_error( + throw JsonBenchmarkError( "unable to resolve JSON parse outcome variables"); } @@ -356,7 +367,7 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec, if (const bool parse_error = !isResolvedZero(reqbody_error) || !isResolvedZero(processor_error); parse_success == parse_error) { - throw std::runtime_error( + throw JsonBenchmarkError( "ambiguous JSON parse outcome observed in benchmark"); } @@ -378,85 +389,117 @@ long currentMaxRssKb() { return usage.ru_maxrss; } +void printJsonStringField(const char *name, const std::string &value, + bool &first) { + if (!first) { + std::cout << ","; + } + std::cout << "\"" << name << "\":\"" << value << "\""; + first = false; +} + +template +void printJsonNumericField(const char *name, T value, bool &first) { + if (!first) { + std::cout << ","; + } + std::cout << "\"" << name << "\":" << value; + first = false; +} + +void printHumanField(const char *name, const std::string &value) { + std::cout << name << ": " << value << "\n"; +} + +template +void printHumanField(const char *name, T value) { + std::cout << name << ": " << value << "\n"; +} + void printJson(const Options &options, const std::string &body, const Metrics &metrics) { + bool first = true; + std::cout << "{"; - std::cout << R"("backend":")" << benchmarkBackend() << "\","; - std::cout << R"("scenario":")" << options.scenario << "\","; - std::cout << "\"iterations\":" << options.iterations << ","; - std::cout << "\"body_bytes\":" << body.size() << ","; - std::cout << "\"append_request_body_ns\":" - << metrics.append_request_body_ns << ","; - std::cout << "\"process_request_body_ns\":" - << metrics.process_request_body_ns << ","; - std::cout << "\"total_transaction_ns\":" - << metrics.total_transaction_ns << ","; - std::cout << "\"parse_success_count\":" - << metrics.parse_success_count << ","; - std::cout << "\"parse_error_count\":" - << metrics.parse_error_count << ","; - std::cout << "\"ru_maxrss_kb\":" << currentMaxRssKb(); + printJsonStringField("backend", benchmarkBackend(), first); + printJsonStringField("scenario", options.scenario, first); + printJsonNumericField("iterations", options.iterations, first); + printJsonNumericField("body_bytes", body.size(), first); + printJsonNumericField("append_request_body_ns", + metrics.append_request_body_ns, first); + printJsonNumericField("process_request_body_ns", + metrics.process_request_body_ns, first); + printJsonNumericField("total_transaction_ns", + metrics.total_transaction_ns, first); + printJsonNumericField("parse_success_count", + metrics.parse_success_count, first); + printJsonNumericField("parse_error_count", + metrics.parse_error_count, first); + printJsonNumericField("ru_maxrss_kb", currentMaxRssKb(), first); + #ifdef MSC_JSON_AUDIT_INSTRUMENTATION const modsecurity::RequestBodyProcessor::JsonInstrumentationMetrics instrumentation = modsecurity::RequestBodyProcessor::jsonInstrumentationSnapshot(); - std::cout << ",\"request_body_snapshot_count\":" - << instrumentation.request_body_snapshot_count; - std::cout << ",\"request_body_snapshot_bytes\":" - << instrumentation.request_body_snapshot_bytes; - std::cout << ",\"request_body_snapshot_ns\":" - << instrumentation.request_body_snapshot_ns; - std::cout << ",\"json_process_chunk_calls\":" - << instrumentation.json_process_chunk_calls; - std::cout << ",\"json_process_chunk_appended_bytes\":" - << instrumentation.json_process_chunk_appended_bytes; - std::cout << ",\"json_process_chunk_ns\":" - << instrumentation.json_process_chunk_ns; - std::cout << ",\"simdjson_parser_constructions\":" - << instrumentation.simdjson_parser_constructions; - std::cout << ",\"simdjson_parser_construction_ns\":" - << instrumentation.simdjson_parser_construction_ns; - std::cout << ",\"simdjson_padded_copy_bytes\":" - << instrumentation.simdjson_padded_copy_bytes; - std::cout << ",\"simdjson_padded_copy_ns\":" - << instrumentation.simdjson_padded_copy_ns; - std::cout << ",\"simdjson_iterate_ns\":" - << instrumentation.simdjson_iterate_ns; - std::cout << ",\"jsoncons_cursor_constructions\":" - << instrumentation.jsoncons_cursor_constructions; - std::cout << ",\"jsoncons_cursor_init_ns\":" - << instrumentation.jsoncons_cursor_init_ns; - std::cout << ",\"jsoncons_token_cursor_constructions\":" - << instrumentation.jsoncons_token_cursor_constructions; - std::cout << ",\"jsoncons_token_cursor_init_ns\":" - << instrumentation.jsoncons_token_cursor_init_ns; - std::cout << ",\"jsoncons_event_loop_ns\":" - << instrumentation.jsoncons_event_loop_ns; - std::cout << ",\"jsoncons_token_sync_steps\":" - << instrumentation.jsoncons_token_sync_steps; - std::cout << ",\"jsoncons_token_exact_advance_steps\":" - << instrumentation.jsoncons_token_exact_advance_steps; + + printJsonNumericField("request_body_snapshot_count", + instrumentation.request_body_snapshot_count, first); + printJsonNumericField("request_body_snapshot_bytes", + instrumentation.request_body_snapshot_bytes, first); + printJsonNumericField("request_body_snapshot_ns", + instrumentation.request_body_snapshot_ns, first); + printJsonNumericField("json_process_chunk_calls", + instrumentation.json_process_chunk_calls, first); + printJsonNumericField("json_process_chunk_appended_bytes", + instrumentation.json_process_chunk_appended_bytes, first); + printJsonNumericField("json_process_chunk_ns", + instrumentation.json_process_chunk_ns, first); + printJsonNumericField("simdjson_parser_constructions", + instrumentation.simdjson_parser_constructions, first); + printJsonNumericField("simdjson_parser_construction_ns", + instrumentation.simdjson_parser_construction_ns, first); + printJsonNumericField("simdjson_padded_copy_bytes", + instrumentation.simdjson_padded_copy_bytes, first); + printJsonNumericField("simdjson_padded_copy_ns", + instrumentation.simdjson_padded_copy_ns, first); + printJsonNumericField("simdjson_iterate_ns", + instrumentation.simdjson_iterate_ns, first); + printJsonNumericField("jsoncons_cursor_constructions", + instrumentation.jsoncons_cursor_constructions, first); + printJsonNumericField("jsoncons_cursor_init_ns", + instrumentation.jsoncons_cursor_init_ns, first); + printJsonNumericField("jsoncons_token_cursor_constructions", + instrumentation.jsoncons_token_cursor_constructions, first); + printJsonNumericField("jsoncons_token_cursor_init_ns", + instrumentation.jsoncons_token_cursor_init_ns, first); + printJsonNumericField("jsoncons_event_loop_ns", + instrumentation.jsoncons_event_loop_ns, first); + printJsonNumericField("jsoncons_token_sync_steps", + instrumentation.jsoncons_token_sync_steps, first); + printJsonNumericField("jsoncons_token_exact_advance_steps", + instrumentation.jsoncons_token_exact_advance_steps, first); #endif + std::cout << "}" << std::endl; } void printHumanReadable(const Options &options, const std::string &body, const Metrics &metrics) { - std::cout << "backend: " << benchmarkBackend() << "\n"; - std::cout << "scenario: " << options.scenario << "\n"; - std::cout << "iterations: " << options.iterations << "\n"; - std::cout << "body_bytes: " << body.size() << "\n"; - std::cout << "append_request_body_ns: " - << metrics.append_request_body_ns << "\n"; - std::cout << "process_request_body_ns: " - << metrics.process_request_body_ns << "\n"; - std::cout << "total_transaction_ns: " - << metrics.total_transaction_ns << "\n"; - std::cout << "parse_success_count: " - << metrics.parse_success_count << "\n"; - std::cout << "parse_error_count: " - << metrics.parse_error_count << "\n"; - std::cout << "ru_maxrss_kb: " << currentMaxRssKb() << "\n"; + printHumanField("backend", benchmarkBackend()); + printHumanField("scenario", options.scenario); + printHumanField("iterations", options.iterations); + printHumanField("body_bytes", body.size()); + printHumanField("append_request_body_ns", + metrics.append_request_body_ns); + printHumanField("process_request_body_ns", + metrics.process_request_body_ns); + printHumanField("total_transaction_ns", + metrics.total_transaction_ns); + printHumanField("parse_success_count", + metrics.parse_success_count); + printHumanField("parse_error_count", + metrics.parse_error_count); + printHumanField("ru_maxrss_kb", currentMaxRssKb()); } } // namespace diff --git a/test/benchmark/run-json-benchmarks.sh b/test/benchmark/run-json-benchmarks.sh index 1f87e5f79..2bac03bd5 100755 --- a/test/benchmark/run-json-benchmarks.sh +++ b/test/benchmark/run-json-benchmarks.sh @@ -6,6 +6,7 @@ usage() { cat <<'EOF' Usage: test/benchmark/run-json-benchmarks.sh --simdjson-build DIR --jsoncons-build DIR [--include-invalid] EOF + return } simdjson_build="" @@ -74,6 +75,8 @@ run_scenarios() { "${binary}" --scenario "${scenario}" --include-invalid --output json >> "${output_file}" done fi + + return 0 } : > "${output_file}" diff --git a/test/regression/regression_test.cc b/test/regression/regression_test.cc index d0661d7ff..04119c5ea 100644 --- a/test/regression/regression_test.cc +++ b/test/regression/regression_test.cc @@ -76,7 +76,7 @@ std::vector> json_object_to_map( std::string_view key; modsecurity_test::json::JsonValue child; - if (modsecurity_test::json::get(std::move(field_result), &field) + if (modsecurity_test::json::get(field_result, &field) == false) { continue; } @@ -92,6 +92,32 @@ std::vector> json_object_to_map( return values; } +template +void for_each_json_field(modsecurity_test::json::JsonValue value, + Callback callback) { + modsecurity_test::json::JsonObject object; + + if (modsecurity_test::json::get(value.get_object(), &object) == false) { + return; + } + + for (auto field_result : object) { + modsecurity_test::json::JsonField field; + std::string_view key; + modsecurity_test::json::JsonValue child; + + if (modsecurity_test::json::get(field_result, &field) == false) { + continue; + } + if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { + continue; + } + + child = field.value(); + callback(key, child); + } +} + void set_int_from_json(int &dest, std::string_view want_key, std::string_view key, modsecurity_test::json::JsonValue value) { if (key == want_key) { @@ -204,27 +230,10 @@ std::unique_ptr RegressionTest::from_json_document( std::unique_ptr RegressionTest::from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; auto test = make_empty_regression_test(); - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return test; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [&test](std::string_view key, + modsecurity_test::json::JsonValue child) { set_int_from_json(test->enabled, "enabled", key, child); set_int_from_json(test->version_min, "version_min", key, child); set_opt_int_from_json(test->version_max, "version_max", key, child); @@ -246,7 +255,7 @@ std::unique_ptr RegressionTest::from_json_value( } else if (key == "rules") { test->update_rules_from_json_value(child); } - } + }); test->name = test->title; return test; @@ -254,81 +263,27 @@ std::unique_ptr RegressionTest::from_json_value( void RegressionTest::update_client_from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; - - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [this](std::string_view key, + modsecurity_test::json::JsonValue child) { set_string_from_json(clientIp, "ip", key, child); set_int_from_json(clientPort, "port", key, child); - } + }); } void RegressionTest::update_server_from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; - - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [this](std::string_view key, + modsecurity_test::json::JsonValue child) { set_string_from_json(serverIp, "ip", key, child); set_int_from_json(serverPort, "port", key, child); set_string_from_json(hostname, "hostname", key, child); - } + }); } void RegressionTest::update_request_from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; - - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [this](std::string_view key, + modsecurity_test::json::JsonValue child) { set_string_from_json(uri, "uri", key, child); set_string_from_json(method, "method", key, child); if (key == "http_version") { @@ -339,31 +294,13 @@ void RegressionTest::update_request_from_json_value( request_body_lines = json_array_to_vec_string(child); request_body = join_strings(request_body_lines); } - } + }); } void RegressionTest::update_response_from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; - - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [this](std::string_view key, + modsecurity_test::json::JsonValue child) { if (key == "headers") { response_headers = json_object_to_map(child); } else if (key == "body") { @@ -371,38 +308,20 @@ void RegressionTest::update_response_from_json_value( response_body = join_strings(response_body_lines); } set_string_from_json(response_protocol, "protocol", key, child); - } + }); } void RegressionTest::update_expected_from_json_value( modsecurity_test::json::JsonValue value) { - modsecurity_test::json::JsonObject object; - - if (modsecurity_test::json::get(value.get_object(), &object) == false) { - return; - } - - for (auto field_result : object) { - modsecurity_test::json::JsonField field; - std::string_view key; - modsecurity_test::json::JsonValue child; - - if (modsecurity_test::json::get(std::move(field_result), &field) - == false) { - continue; - } - if (modsecurity_test::json::get(field.unescaped_key(), &key) == false) { - continue; - } - child = field.value(); - + for_each_json_field(value, [this](std::string_view key, + modsecurity_test::json::JsonValue child) { set_string_from_json(audit_log, "audit_log", key, child); set_string_from_json(debug_log, "debug_log", key, child); set_string_from_json(error_log, "error_log", key, child); set_int_from_json(http_code, "http_code", key, child); set_string_from_json(redirect_url, "redirect_url", key, child); set_string_from_json(parser_error, "parser_error", key, child); - } + }); } void RegressionTest::update_rules_from_json_value( @@ -417,7 +336,6 @@ void RegressionTest::update_rules_from_json_value( rules = stream.str(); } - constexpr char ascii_tolower(char c) { return 'A' <= c && c <= 'Z' ? (c + ('a' - 'A')) : c; } @@ -430,15 +348,18 @@ bool iequals_ascii(std::string_view a, std::string_view b) { }); } -static bool has_chunked_header(const std::vector> &headers) { +static bool has_chunked_header( + const std::vector> &headers) { return std::any_of(std::begin(headers), std::end(headers), [](const auto &header) { const auto &[name, value]{header}; - return iequals_ascii(name, "Transfer-Encoding") && iequals_ascii(value, "chunked"); + return iequals_ascii(name, "Transfer-Encoding") + && iequals_ascii(value, "chunked"); }); } -static void update_content_length(std::vector> &headers, size_t length) { +static void update_content_length( + std::vector> &headers, size_t length) { if (has_chunked_header(headers)) { return; } @@ -451,7 +372,8 @@ static void update_content_length(std::vector RegressionTests::from_json_value( continue; } tests->tests.emplace_back( - std::move(RegressionTest::from_json_value(test_value))); + RegressionTest::from_json_value(test_value)); } return tests; } if (type == modsecurity_test::json::JsonType::Object) { - tests->tests.emplace_back(std::move(RegressionTest::from_json_value(value))); + tests->tests.emplace_back(RegressionTest::from_json_value(value)); } return tests; } void RegressionTests::update_content_lengths() { - for (auto & test : tests) { + for (auto &test : tests) { test->update_content_lengths(); } } @@ -520,7 +442,7 @@ std::string RegressionTests::toJSON() const { writer.key(key); writer.string(value); }; - const auto addStringIfNonEmpty = [&writer, &addString]( + const auto addStringIfNonEmpty = [&addString]( std::string_view key, const std::string &value) { if (value.empty() == false) { addString(key, value); diff --git a/test/run-json-backend-matrix.sh b/test/run-json-backend-matrix.sh index 431799992..0a9c5f64d 100755 --- a/test/run-json-backend-matrix.sh +++ b/test/run-json-backend-matrix.sh @@ -14,6 +14,7 @@ Exit codes: 13 backend result difference 64 invalid usage EOF + return } repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -76,6 +77,7 @@ extract_summary() { print backend "\t" m[2] "\t" m[3] "\t" m[1]; } ' "${input_log}" > "${output_tsv}" + return } run_backend() { diff --git a/test/unit/unit_test.cc b/test/unit/unit_test.cc index 8cfbb1873..82a7afbc6 100644 --- a/test/unit/unit_test.cc +++ b/test/unit/unit_test.cc @@ -165,7 +165,7 @@ std::unique_ptr UnitTest::from_json_value( std::string_view key; modsecurity_test::json::JsonValue child; - if (modsecurity_test::json::get(std::move(field_result), &field) + if (modsecurity_test::json::get(field_result, &field) == false) { continue; }