[v2] Writable objects: owned and borrowed object#378
Conversation
| ddwaf_object_array_add(&array, ddwaf_object_stringl(&tmp, arg.data(), arg.size())); | ||
| } | ||
| auto root = owned_object::make_map(); | ||
| root.emplace("server.request.query", owned_object::make_string(param)); |
There was a problem hiding this comment.
perhaps you could add some syntax sugar like:
#include <string_view>
struct kv;
struct dw_obj {
char _c{};
dw_obj(dw_obj &&) = default;
dw_obj(const dw_obj &) = delete;
dw_obj &operator=(dw_obj &&) = default;
dw_obj &operator=(const dw_obj &) = delete;
~dw_obj() = default;
dw_obj(int i) {} // NOLINT
dw_obj(std::string_view) {} // NOLINT
template<typename Str> requires std::convertible_to<Str, std::string_view>
dw_obj(Str) {} // NOLINT
dw_obj(std::initializer_list<kv>) {} // NOLINT
dw_obj(std::initializer_list<dw_obj>) {} // NOLINT
protected:
dw_obj() = default;
};
struct kv : std::pair<std::string_view, dw_obj> {
using std::pair<std::string_view, dw_obj>::pair;
kv(const std::string_view& sv, dw_obj&& obj) : std::pair<std::string_view, dw_obj>{
sv, std::move(obj)
} {} // NOLINT
};
void test() {
dw_obj map{
kv{"foo", {kv{"bar", "foo"}}},
kv{
"xxx",
{
1,
3,
"yyy",
{{"zzz"}},
{kv{"aaa", "bbb"}}}}};
}Empty arrays/maps need special handling; you could add constants, or you could add dw_obj_array, dw_obj_map objects etc. You could use a similar model to that of nginx: they derive dw_obj, they have may_alias, and you can (behind an optional for safe conversions) convert borrowed dw_obj into dw_obj_map/etc. and unconditionally convert in the other direction.
There was a problem hiding this comment.
Okay I had some thoughts along these lines as well, I'll have a look at what you've done and see if I can introduce anything here as well in the next PR (before I update all tests....)
Benchmarks clang-pgoBenchmark execution time: 2025-03-19 12:12:32 Comparing candidate commit c6d9fbf in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics. |
* Object view: read only abstraction to ddwaf_object (#341) * [v2] Remove mingw builds (#381) * Writable objects: owned and borrowed object and object limits removal (#378, #382) * [v2] Refactor and improve object types (#387) * [v2] Update unit tests to use new abstractions (#389) * [v2] Update `raw_configuration` type to use `object_view` (#390) * [v2] Remove remaining uses of ddwaf_object in `src` and `tests/unit` (#391) * [v2] JWT Decoding Processor (#401) * [v2] First iteration of object layout changes (#394) * Split context data insertion from evaluation (#407) * [v2] Second iteration of object layout changes (#408) * [v2] Add new fingerprint and object view tests (#414) * Reenable attribute collector unit test (#415) * [v2] Container view types (#413) * Exclude assertions from coverage (#416) * [v2] Use allocators internally instead of malloc/free and stop generating zero-terminated strings (#418) * Add memory resource to owned and borrowed objects (#428) * [v2] Propagate allocators from context (#420) * [v2] Update interface and expose allocators (#427) * Refactor evaluation stages out of the context (#442) * Subcontext: replace ephemerals with a new scope with user-defined lifetime derived from the context (#443) * Validator: Add support for testing subcontexts and attributes (#451) * [v2] Pass allocator to context and subcontext eval and add new allocators (#452) * Update logger to avoid dependencies on ddwaf.h (#453) * [v2] Return DDWAF_MATCH when there are events, attributes or actions (#455) * [v2] Cleanup: remove exclusion namespace and some redundant references (#456)
This PR introduces two new object types:
owned_object: as the name suggests, this is an object which owns its own memory. This abstraction ensures that the memory associated with an object is freed on destruction and moved appropriately.borrowed_object: an object type which points to memory owned by a different object, this allows accessing elements from anowned_objectwithout the risk of accidental double-free.In addition, some code from
object_viewhas been refactored to ensure thatowned_objectandborrowed_objectare both writable and readable. More ofobject_viewwill be refactored in the next few PRs.Some quirks on this PR:
ddwaf_object_*still contain a separate implementation, these will be updated to use the new abstractions in a following PR. This code has been moved fromobject.cpptointerface.cppwithout changes.owned_objectandborrowed_objectcurrently don't check for free function compatibility. While incorrect, this shouldn't be an issue at the moment and free functions are being replaced by allocators in a subsequent PR.Remaining work (future PRs):
ddwaf_objectwithin tests withowned_object,borrowed_objectandobject_view.object_viewandobject_converter.raw_configurationin favour ofobject_viewor useobject_viewbehind the scenes.ddwaf_object_*interface to use new types.ddwaf_objectarguments oroptional_ref.emplaceandemplace_back.malloc/free