### Custom Counting Allocator Example in C Source: https://context7.com/datadog/libddwaf/llms.txt Demonstrates how to implement and use a custom counting allocator in C to track memory allocations and deallocations. This example shows the setup for a user-defined allocator and its integration with libddwaf functions. ```c #include "ddwaf.h" #include // Custom counting allocator for tracking allocations typedef struct { unsigned alloc_count; unsigned free_count; ddwaf_allocator upstream; } counting_allocator_data; void* counting_alloc(void* udata, size_t bytes, size_t alignment) { counting_allocator_data* data = (counting_allocator_data*)udata; data->alloc_count++; return ddwaf_allocator_alloc(data->upstream, bytes, alignment); } void counting_free(void* udata, void* p, size_t bytes, size_t alignment) { counting_allocator_data* data = (counting_allocator_data*)udata; data->free_count++; ddwaf_allocator_free(data->upstream, p, bytes, alignment); } void allocator_examples(ddwaf_handle handle) { // Default allocator - uses standard new/delete ddwaf_allocator default_alloc = ddwaf_get_default_allocator(); // Synchronized pool allocator - thread-safe, good for concurrent contexts ddwaf_allocator pool_alloc = ddwaf_synchronized_pool_allocator_init(); // Unsynchronized pool allocator - faster, single-thread only ddwaf_allocator fast_pool = ddwaf_unsynchronized_pool_allocator_init(); // Monotonic allocator - fastest, memory freed only on destroy ddwaf_allocator mono_alloc = ddwaf_monotonic_allocator_init(); // Custom user allocator with tracking counting_allocator_data counter = {0, 0, ddwaf_get_default_allocator()}; ddwaf_allocator counting_alloc_handle = ddwaf_user_allocator_init( counting_alloc, counting_free, &counter, NULL); // Create context with pool allocator for output ddwaf_context ctx = ddwaf_context_init(handle, pool_alloc); // Build input using monotonic allocator (fast allocation, batch free) ddwaf_object input; ddwaf_object_set_map(&input, 1, mono_alloc); ddwaf_object* val = ddwaf_object_insert_key(&input, "test", 4, mono_alloc); ddwaf_object_set_string(val, "value", 5, mono_alloc); // Evaluate ddwaf_object result; ddwaf_context_eval(ctx, &input, mono_alloc, &result, 1000000); // Cleanup ddwaf_object_destroy(&result, pool_alloc); ddwaf_context_destroy(ctx); printf("Allocations: %u, Frees: %u\n", counter.alloc_count, counter.free_count); // Destroy allocators (except default, which is a no-op) ddwaf_allocator_destroy(pool_alloc); ddwaf_allocator_destroy(fast_pool); ddwaf_allocator_destroy(mono_alloc); ddwaf_allocator_destroy(counting_alloc_handle); } ``` -------------------------------- ### DDWAF C++ Example Source: https://github.com/datadog/libddwaf/blob/master/README.md This snippet demonstrates initializing DDWAF, loading rules, and evaluating data. Ensure DDWAF and yaml-cpp are correctly set up. ```cpp #include #include "ddwaf.h" constexpr std::string_view waf_rule = R"( version: "2.1" rules: - id: "1" name: rule 1 tags: type: flow1 category: test conditions: - operator: match_regex parameters: inputs: - address: arg1 regex: .* - operator: match_regex parameters: inputs: - address: arg2 regex: .* on_match: [ block ] )"; int main() { auto alloc = ddwaf_get_default_allocator(); YAML::Node doc = YAML::Load(waf_rule.data()); auto rule = doc.as(); ddwaf_builder builder = ddwaf_builder_init(); ddwaf_object diagnostics; bool success = ddwaf_builder_add_or_update_config(builder, "config", 6, &rule, &diagnostics); ddwaf_object_destroy(&rule, alloc); ddwaf_object_destroy(&diagnostics, alloc); if (!success) { ddwaf_builder_destroy(builder); return EXIT_FAILURE; } ddwaf_handle handle = ddwaf_builder_build_instance(builder); ddwaf_builder_destroy(builder); if (handle == nullptr) { return EXIT_FAILURE; } ddwaf_context context = ddwaf_context_init(handle, alloc); if (context == nullptr) { ddwaf_destroy(handle); return EXIT_FAILURE; } ddwaf_object root; ddwaf_object_set_map(&root, 2, alloc); ddwaf_object *arg1 = ddwaf_object_insert_literal_key(&root, "arg1", 4, alloc); ddwaf_object_set_string_literal(arg1, "string 1", 8); ddwaf_object *arg2 = ddwaf_object_insert_literal_key(&root, "arg2", 4, alloc); ddwaf_object_set_string_literal(arg2, "string 2", 8); ddwaf_object ret; auto code = ddwaf_context_eval(context, &root, alloc, &ret, 1000000 /* microseconds */); std::cout << "Output second run: " << code << '\n'; if (code == DDWAF_MATCH) { YAML::Emitter out(std::cout); out.SetIndent(2); out.SetMapFormat(YAML::Block); out.SetSeqFormat(YAML::Block); out << object_to_yaml(ret); } ddwaf_object_destroy(&ret, alloc); ddwaf_context_destroy(context); ddwaf_destroy(handle); return EXIT_SUCCESS; } ``` -------------------------------- ### Build Example Sources with CMake Source: https://github.com/datadog/libddwaf/blob/master/examples/CMakeLists.txt This CMake script iterates through all .cpp files in the LIBDDWAF_EXAMPLE_SOURCE directory, compiles each as a separate executable, and links them against libddwaf_objects, lib_yamlcpp, and lib_rapidjson. It also sets up private include directories. ```cmake file(GLOB LIBDDWAF_EXAMPLE_SOURCE *.cpp) foreach(EXAMPLE ${LIBDDWAF_EXAMPLE_SOURCE}) get_filename_component(EXAMPLE_NAME ${EXAMPLE} NAME_WLE) add_executable(${EXAMPLE_NAME} ${EXAMPLE}) target_link_libraries(${EXAMPLE_NAME} PRIVATE libddwaf_objects lib_yamlcpp lib_rapidjson) target_include_directories(${EXAMPLE_NAME} PRIVATE ${LIBDDWAF_PRIVATE_INCLUDES}) endforeach() ``` -------------------------------- ### Build and Run Fuzzer Manually Source: https://github.com/datadog/libddwaf/blob/master/fuzzer/global/README.md This method requires LLVM to be installed. First, build the fuzzer executable, then run the fuzzing session. ```bash ./fuzzing/build.sh # build fuzzing/fuzzer executable ./fuzzing/run.sh # starts a fuzzing session ``` -------------------------------- ### Rule with Min/Max Version Constraints Source: https://github.com/datadog/libddwaf/blob/master/docs/changelog/CHANGELOG-v1.x.md This example demonstrates how to use `min_version` and `max_version` to control the compatibility of a rule with specific libddwaf versions. Ensure the rule's version requirements align with the libddwaf version being used. ```yaml - id: rsp-930-004 name: SHi Exploit detection tags: type: shi category: exploit_detection module: rasp min_version: 1.19.0 max_version 1.19.999 conditions: - parameters: resource: - address: server.sys.shell.cmd params: - address: server.request.query operator: shi_detector ``` -------------------------------- ### Migrate ddwaf_run usage from ddwaf_result to ddwaf_object Source: https://github.com/datadog/libddwaf/blob/master/docs/upgrading/UPGRADING-v1.x.md Example demonstrating the migration from using ddwaf_result to ddwaf_object for handling results from ddwaf_run. It shows how to access events. ```c++ ddwaf_result ret; auto code = ddwaf_run(context, &root, nullptr, &ret, LONG_TIME); if (code == DDWAF_MATCH) { cout << object_to_yaml(&ret.events); } ddwaf_result_free(&ret); ``` ```c++ ddwaf_object ret; auto code = ddwaf_run(context, &root, nullptr, &ret, LONG_TIME); if (code == DDWAF_MATCH) { const ddwaf_object *events = ddwaf_object_find(&ret, "events", sizeof("events") - 1); cout << object_to_yaml(events); } ddwaf_object_free(&ret); ``` -------------------------------- ### Build libddwaf with Specific Targets and Test Suite Source: https://github.com/datadog/libddwaf/blob/master/README.md Builds libddwaf with specific configurations (RelWithDebInfo, custom install prefix) and targets, including shared and static libraries, and the test suite. It then navigates to the tests directory and runs the WAF test executable. ```bash cmake -E make_directory build packages cd build cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=.. -DCPACK_PACKAGE_DIRECTORY=../packages .. cmake --build . --config RelWithDebInfo --verbose --target libddwaf_shared --target libddwaf_static --target waf_test -j cd ../tests ../build/tests/waf_test ``` -------------------------------- ### Iterating Old Actions Array Source: https://github.com/datadog/libddwaf/blob/master/docs/upgrading/UPGRADING-v1.x.md Example of how to iterate through the actions array in the older DD WAF result structure. ```c ddwaf_result res; for (unsigned i = 0; i < res.actions.size; ++i) { printf("%s", res.actions.array[i]); } ``` -------------------------------- ### Get All Loaded Configuration Paths in libddwaf Source: https://github.com/datadog/libddwaf/blob/master/docs/changelog/CHANGELOG-v1.x.md Use this function to retrieve all currently loaded configuration paths from the WAF builder. Ensure the builder is initialized and configurations are added before calling. ```c ddwaf_builder builder = ddwaf_builder_init(nullptr); ddwaf_builder_add_or_update_config(builder, LSTRARG("ASM_DD/default"), &default_config, nullptr); ddwaf_object_free(&default_config); ddwaf_object paths; uint32_t count = ddwaf_builder_get_config_paths(builder, &paths, nullptr, 0); // count: 1 // paths: [ "ASM_DD/default" ] ``` -------------------------------- ### Create and Match with Aho-Corasick Lua Module Source: https://github.com/datadog/libddwaf/blob/master/src/vendor/lua-aho-corasick/README.md Example of how to create an Aho-Corasick instance with a dictionary and perform a match against a given string using the Lua module. ```lua local ac = require "ahocorasick" local dict = {"string1", "string", "etc"} local acinst = ac.create(dict) local r = ac.match(acinst, "mystring") ``` -------------------------------- ### Legacy Linux Build Package Naming Convention Source: https://github.com/datadog/libddwaf/blob/master/docs/upgrading/UPGRADING-v1.x.md Provides examples of legacy Linux build package names for comparison with the new standardized format. These packages do not include the architecture or environment details in the same way. ```text libddwaf-1.13.0-linux-x86_64.tar.gz libddwaf-1.13.0-linux-aarch64.tar.gz ``` -------------------------------- ### Traversing Diagnostics Object for Root Span Source: https://github.com/datadog/libddwaf/blob/master/docs/upgrading/UPGRADING-v1.x.md This example demonstrates a mechanism to traverse the new diagnostics object to report rule metrics and errors to the root span, ensuring backward compatibility. ```cpp ddwaf_object diagnostics; ddwaf_handle handle = ddwaf_init(&rule, nullptr, &diagnostics); ddwaf_object_free(&rule); ddwaf_destroy(handle); const auto *rules = find_object(&diagnostics, "rules"); if (rules != nullptr) { size_t index = 0; const ddwaf_object *node = nullptr; while ((node = ddwaf_object_get_index(rules, index++)) != nullptr) { std::string_view node_key = ddwaf_object_get_key(node, nullptr); if (node_key == "loaded") { root_span.metrics["_dd.appsec.event_rules.loaded"] = ddwaf_object_size(node); } else if (node_key =="failed") { root_span.metrics["_dd.appsec.event_rules.error_count"] = ddwaf_object_size(node); } else if (node_key == "errors") { root_span.meta["_dd.appsec.event_rules.errors"] = object_to_yaml(*node); } else if (node_key == "ruleset_version") { root_span.meta["_dd.appsec.event_rules.version"] = ddwaf_object_get_string(node, nullptr); } } } ddwaf_object_free(&diagnostics); ``` -------------------------------- ### Generate Stack Action with Stack ID Source: https://github.com/datadog/libddwaf/blob/master/docs/upgrading/UPGRADING-v1.x.md This example shows the structure for the `generate_stack` action type when triggered. It includes the `stack_id` parameter, which is essential for associating the generated stack trace with the correct event. ```json { "generate_stack": { "stack_id": "b4c7aff3-8fb0-4f6a-1bc7-582700c46abe" } } ``` -------------------------------- ### DDWAF Rule Example and Result Source: https://github.com/datadog/libddwaf/blob/master/README.md This YAML demonstrates a sample DDWAF rule designed to detect script tags and its corresponding output when applied to a specific input value. It shows how rule conditions and matches are represented. ```yaml version: 2.1 rules: - id: crs-042-001 name: Detect a script tag tags: category: attack_attempt type: xss conditions: - operator: match_regex parameters: regex: "^