目录

Configuration Parser: Static Analysis and Fuzzing Lab

A C++17 configuration language implementation for experimenting with static analysis, parser fuzzing, resource limits, and property-based testing. The core library uses only the C++ standard library.

Status

The library, command-line application, unit-test source, and two libFuzzer entry points are present. An earlier version compiled with GCC in WSL. Later additions, including the schema loader, have not been compiled or tested. Execution was stopped at the user’s request. No successful sanitizer, static-analysis, or Fuzz campaign is claimed. The commands below are instructions for a future run.

Features

  • Located tokens with byte offsets, line numbers, and column numbers.
  • Signed 64-bit integers, finite real numbers, booleans, null, and byte strings.
  • Arrays, inline objects, dotted keys, and named sections.
  • Absolute references such as ${server.port}, with cycle detection.
  • Limits on input size, token size, nesting, nodes, and reference expansion.
  • Canonical formatting, document overlays, leaf-path listing, and structural diffs.
  • Schema validation, defaults, custom predicates, and configuration-based schemas.
  • In-memory editing transactions with optional validation before commit.
  • JSON export after reference resolution.

Layout

Location Purpose
include/config/value.hpp Value tree, paths, formatting, and structural utilities
include/config/parser.hpp Lexer, parser, limits, and reference resolution
include/config/schema.hpp Schema rules and diagnostics
include/config/schema_loader.hpp Schema import and export
include/config/document.hpp Document editing and transactions
src/ Library implementation and command-line entry point
tests/test_config.cpp Boundary, regression, and deterministic property tests
fuzz/fuzz_parse.cpp Parsing, reference expansion, and schema validation target
fuzz/fuzz_roundtrip.cpp Canonicalization and roundtrip oracle

The project uses the shared ../cmake/ProjectOptions.cmake. Keep it beside the other projects when copying the source tree.

Build

Requirements: CMake 3.16 or newer, a C++17 compiler, and a build tool. The examples use Linux or WSL and Ninja. Run them from this project’s directory.

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build
ctest --test-dir build --output-on-failure

compile_commands.json is exported into the build directory. Keep normal, sanitizer, Fuzz, and deliberately buggy builds in separate directories.

Configuration Language

Save this example as example.cfg:

name = "demo-service"
default_port = 8080
log_level = "info"

[server]
host = "127.0.0.1"
port = ${default_port}
enabled = true
workers = 4
tags = ["local", "fuzz",]

[server.tls]
enabled = false

Identifiers begin with an ASCII letter or underscore; subsequent characters may also include digits and hyphens. Dots separate object keys. Assignments end at a newline. # and ; introduce comments outside strings. Duplicate assignments and repeated explicit section declarations are rejected.

Double-quoted strings support \n, \r, \t, \b, \f, \\, \", \/, \xHH, and \uHHHH, including valid UTF-16 surrogate pairs. Single-quoted strings are literal. Raw control characters are rejected.

Arrays and inline objects may span lines and have trailing commas:

items = [1, true, null, "text", {nested = [2, 3]}]
settings = {timeout: 30, retry = true}
copy = ${settings}

References are whole values, not string interpolation. Their paths are absolute from the document root. Resolution produces a new tree and rejects missing targets, cycles, and expansion beyond configured limits.

Command-Line Usage

build/config_cli normalize example.cfg
build/config_cli resolve example.cfg
build/config_cli json example.cfg
build/config_cli get example.cfg server.port
build/config_cli set example.cfg server.port 9000
build/config_cli remove example.cfg server.tls
build/config_cli paths example.cfg
build/config_cli stats example.cfg
build/config_cli tokens example.cfg
build/config_cli merge example.cfg overlay.cfg
build/config_cli diff example.cfg other.cfg

Editing commands print the resulting document to standard output; they do not save over the input. get prints the stored value, which may still be a reference. json resolves references first. diff returns 1 when documents differ.

The built-in server schema allows name, server, and log_level; its server properties are host, port, workers, enabled, and tags. The larger example above intentionally includes additional properties and will fail this strict schema. A minimal valid example is:

name = "demo"
server = {port = 8080}
build/config_cli validate minimal.cfg
build/config_cli defaults minimal.cfg
build/config_cli validate example.cfg custom-schema.cfg

A custom schema is itself a configuration document:

type = "object"
allow_unknown = false

[properties.port]
type = "integer"
required = true
minimum = 1
maximum = 65535

[properties.name]
type = "string"
min_size = 1
max_size = 128
default = "demo"

Schema options include nullable, choices, min_size, max_size, items, and nested properties. Custom C++ predicates cannot be serialized. Numeric schema bounds use doubles; exact constraints near the int64 extremes require a custom predicate.

Static Analysis

For a single implementation file:

mkdir -p reports
clang++ --analyze -std=c++17 -Iinclude src/parser.cpp \
  -Xanalyzer -analyzer-output=plist -o reports/parser.plist

For compilation-database analysis with a separately installed CodeChecker:

CodeChecker analyze build/compile_commands.json -o reports/codechecker
CodeChecker parse reports/codechecker
CodeChecker analyze build/compile_commands.json --ctu -o reports/ctu

CTU requires compatible Clang and CodeChecker tooling, including the external definition mapping tool. Diagnostic coverage depends on the installed toolchain; the project does not assert that every demonstration defect is found statically.

Sanitizers and Fuzzing

cmake -S . -B build-asan -G Ninja -DCMAKE_BUILD_TYPE=Debug \
  -DENABLE_SANITIZERS=ON
cmake --build build-asan
ctest --test-dir build-asan --output-on-failure

cmake -S . -B build-fuzz -G Ninja -DCMAKE_CXX_COMPILER=clang++ \
  -DCMAKE_BUILD_TYPE=Debug -DENABLE_FUZZING=ON
cmake --build build-fuzz
mkdir -p corpus/parse corpus/roundtrip artifacts
printf 'name="demo"\nserver={port=8080}\n' > corpus/parse/server.cfg
printf 'items=[1,2,3]\n' > corpus/roundtrip/array.cfg
build-fuzz/config_fuzz_parse corpus/parse -max_total_time=60 -max_len=65536 \
  -artifact_prefix=artifacts/
build-fuzz/config_fuzz_roundtrip corpus/roundtrip -max_total_time=60 -max_len=65536 \
  -artifact_prefix=artifacts/

Fuzz builds enable ASan and UBSan as well as libFuzzer. Parsing failures are expected; a successful parse followed by an inconsistent roundtrip aborts. Replay a finding by passing its file to the corresponding Fuzz executable. Seed directories and artifacts are created by the commands above.

Optional Demonstration Defects

All three defects are disabled by default. Enable them only in a separate build:

cmake -S . -B build-bugs -G Ninja -DCMAKE_CXX_COMPILER=clang++ \
  -DCMAKE_BUILD_TYPE=Debug -DENABLE_FUZZING=ON -DENABLE_DEMO_BUGS=ON
cmake --build build-bugs
ID Location Trigger Expected detector Repair
CFG-001 src/lexer.cpp, Lexer::string_token A string starting with LEGACY: and exceeding the 16-byte destination ASan; static buffer diagnostics may vary Preserve the std::string; remove the fixed buffer and strcpy
CFG-002 src/parser.cpp, Parser::assignment Root key legacy_missing UBSan/ASan; null-dereference analysis Check optional lookup results before access
CFG-003 src/parser.cpp, normalize Any nonempty top-level array Roundtrip property oracle Preserve all array elements during formatting
printf 'x="LEGACY:abcdefghijklmnopqrstuvwxyz"\n' > cfg-001.cfg
printf 'legacy_missing=1\n' > cfg-002.cfg
printf 'items=[1,2,3]\n' > cfg-003.cfg
build-bugs/config_fuzz_parse cfg-001.cfg
build-bugs/config_fuzz_parse cfg-002.cfg
build-bugs/config_fuzz_roundtrip cfg-003.cfg

Run these cases individually: sanitizer failures and oracle failures terminate the process. Normal CTest registration is disabled in demonstration builds.

Tests and Limits

Test source covers scalar types, all byte values, Unicode escapes, malformed containers, duplicate keys, source positions, integer boundaries, nested sections, reference cycles, expansion budgets, schemas, transaction isolation, file I/O, truncated input, and deterministic random roundtrips.

Strings are byte sequences. JSON export maps non-ASCII bytes to \u00HH; this is a byte-preserving convention, not semantic UTF-8-to-Unicode JSON conversion. The language is an educational custom format, not TOML, YAML, or JSON. There is no file inclusion, environment-variable expansion, networking, or concurrent transaction isolation. Document::save writes directly and is not crash-atomic.

The shared source-line counter is available for a later manual check:

python3 ../tools/count_loc.py --check

It excludes blank lines, comments, documentation, and build output. A final 3000–5000-line acceptance check has not been executed for this source snapshot.

关于
59.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号