Skip to content

Commit

Permalink
Add separate nullable optional_object_view and change object_view to …
Browse files Browse the repository at this point in the history
…be nonnull
  • Loading branch information
Anilm3 committed Oct 7, 2024
1 parent 2eb548e commit 8a4923a
Show file tree
Hide file tree
Showing 14 changed files with 389 additions and 603 deletions.
2 changes: 1 addition & 1 deletion src/condition/lfi_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ lfi_result lfi_impl(std::string_view path, const ddwaf_object &params,
lfi_fn = &lfi_impl_windows;
}

kv_iterator it(&params, {}, objects_excluded, limits);
kv_iterator it(params, {}, objects_excluded, limits);
for (; it; ++it) {
if (deadline.expired()) {
throw ddwaf::timeout_exception();
Expand Down
2 changes: 1 addition & 1 deletion src/condition/match_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ template <std::size_t MinLength = 2, typename Iterator = kv_iterator> class matc
public:
static constexpr std::size_t npos = std::string_view::npos;

explicit match_iterator(std::string_view resource, const ddwaf_object *obj,
explicit match_iterator(std::string_view resource, const ddwaf_object &obj,
const exclusion::object_set_ref &exclude, const object_limits &limits = object_limits())
: resource_(resource), it_(obj, {}, exclude, limits)
{
Expand Down
8 changes: 4 additions & 4 deletions src/condition/scalar_condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ eval_result scalar_condition::eval(condition_cache &cache, const object_store &s
std::optional<condition_match> match;
// TODO: iterators could be cached to avoid reinitialisation
if (target.source == data_source::keys) {
key_iterator it(object, target.key_path, objects_excluded, limits_);
key_iterator it(*object, target.key_path, objects_excluded, limits_);
match = eval_target<std::optional<condition_match>>(
it, target.name, ephemeral, *matcher, target.transformers, limits_, deadline);
} else {
value_iterator it(object, target.key_path, objects_excluded, limits_);
value_iterator it(*object, target.key_path, objects_excluded, limits_);
match = eval_target<std::optional<condition_match>>(
it, target.name, ephemeral, *matcher, target.transformers, limits_, deadline);
}
Expand Down Expand Up @@ -212,11 +212,11 @@ eval_result scalar_negated_condition::eval(condition_cache &cache, const object_

bool match = false;
if (target_.source == data_source::keys) {
key_iterator it(object, target_.key_path, objects_excluded, limits_);
key_iterator it(*object, target_.key_path, objects_excluded, limits_);
match = eval_target<bool>(
it, target_.name, ephemeral, *matcher, target_.transformers, limits_, deadline);
} else {
value_iterator it(object, target_.key_path, objects_excluded, limits_);
value_iterator it(*object, target_.key_path, objects_excluded, limits_);
match = eval_target<bool>(
it, target_.name, ephemeral, *matcher, target_.transformers, limits_, deadline);
}
Expand Down
2 changes: 1 addition & 1 deletion src/condition/shi_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ std::optional<shi_result> shi_string_impl(std::string_view resource,
const exclusion::object_set_ref &objects_excluded, const object_limits &limits,
ddwaf::timer &deadline)
{
match_iterator it(resource, &params, objects_excluded, limits);
match_iterator it(resource, params, objects_excluded, limits);
for (; it; ++it) {
if (deadline.expired()) {
throw ddwaf::timeout_exception();
Expand Down
2 changes: 1 addition & 1 deletion src/condition/sqli_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ sqli_result sqli_impl(std::string_view resource, std::vector<sql_token> &resourc
{
static constexpr std::size_t min_str_len = 3;

match_iterator<min_str_len> it(resource, &params, objects_excluded, limits);
match_iterator<min_str_len> it(resource, params, objects_excluded, limits);
for (; it; ++it) {
if (deadline.expired()) {
throw ddwaf::timeout_exception();
Expand Down
2 changes: 1 addition & 1 deletion src/condition/ssrf_detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ ssrf_result ssrf_impl(const uri_decomposed &uri, const ddwaf_object &params,

std::optional<ssrf_result> parameter_injection;

match_iterator<min_str_len> it{uri.raw, &params, objects_excluded, limits};
match_iterator<min_str_len> it{uri.raw, params, objects_excluded, limits};
for (; it; ++it) {
if (deadline.expired()) {
throw ddwaf::timeout_exception();
Expand Down
50 changes: 31 additions & 19 deletions src/iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void value_iterator::initialise_cursor_with_path(
const std::string_view key = path[i];
auto &parent_it = stack_.back();

std::pair<std::string_view, object_view> child;
std::pair<std::string_view, optional_object_view> child;
if (parent_it.container_type() == object_type::map) {
for (; parent_it; ++parent_it) {
auto possible_child = *parent_it;
Expand All @@ -146,21 +146,25 @@ void value_iterator::initialise_cursor_with_path(
}
}

if (!child.second.has_value()) {
return;
}

// If we find a scalar and it's the last element,
// we found a valid element within the path.
if (child.second.is_scalar() && (i + 1) == path.size()) {
if (child.second->is_scalar() && (i + 1) == path.size()) {
current_ = child;
// We want to keep the stack pointing to the container
// in the last key of the key path, since the last element
// of the key path is a scalar, we clear the stack.
stack_.clear();
} else if (child.second.is_container()) {
} else if (child.second->is_container()) {
if ((i + 1) == limits_.max_container_depth) {
break;
}

// Replace the stack top
stack_.back() = child.second.begin(limits_);
stack_.back() = child.second->begin(limits_);

if ((i + 1) < path.size()) {
continue;
Expand Down Expand Up @@ -199,16 +203,16 @@ void value_iterator::set_cursor_to_next_object()
continue;
}

if (child.is_container()) {
if (child->is_container()) {
if (depth() < limits_.max_container_depth) {
++parent_it;
// Push can invalidate the current references to the parent
// so we increment the index before a potential reallocation
// and prevent any further use of the references.
stack_.emplace_back(child.begin(limits_));
stack_.emplace_back(child->begin(limits_));
continue;
}
} else if (child.is_scalar()) {
} else if (child->is_scalar()) {
current_.first = parent_it.key();
current_.second = child;
}
Expand Down Expand Up @@ -258,7 +262,7 @@ void key_iterator::initialise_cursor_with_path(
const std::string_view key = path[i];
auto &parent_it = stack_.back();

std::pair<std::string_view, object_view> child;
std::pair<std::string_view, optional_object_view> child;
if (parent_it.container_type() == object_type::map) {
for (; parent_it; ++parent_it) {
auto possible_child = *parent_it;
Expand All @@ -277,8 +281,12 @@ void key_iterator::initialise_cursor_with_path(
}
}

if (child.second.is_container()) {
stack_.back() = child.second.begin(limits_);
if (!child.second.has_value()) {
return;
}

if (child.second->is_container()) {
stack_.back() = child.second->begin(limits_);

if ((i + 1) < path.size()) {
continue;
Expand Down Expand Up @@ -317,7 +325,7 @@ void key_iterator::set_cursor_to_next_object()
continue;
}

if (child.second.is_container()) {
if (child.second->is_container()) {
if (previous.second != child.second && !child.first.empty()) {
current_ = child;
// Break to ensure the index isn't increased and this container
Expand All @@ -330,7 +338,7 @@ void key_iterator::set_cursor_to_next_object()
// so we increment the index before a potential reallocation
// and prevent any further use of the references.
++parent_it;
stack_.emplace_back(child.second.begin(limits_));
stack_.emplace_back(child.second->begin(limits_));
continue;
}
} else if (!child.first.empty()) {
Expand Down Expand Up @@ -390,7 +398,7 @@ void kv_iterator::initialise_cursor_with_path(
const std::string_view key = path[i];
auto &parent_it = stack_.back();

std::pair<std::string_view, object_view> child;
std::pair<std::string_view, optional_object_view> child;
if (parent_it.container_type() == object_type::map) {
for (; parent_it; ++parent_it) {
auto possible_child = *parent_it;
Expand All @@ -409,22 +417,26 @@ void kv_iterator::initialise_cursor_with_path(
}
}

if (!child.second.has_value()) {
return;
}

// If we find a scalar and it's the last element,
// we found a valid element within the path.
if (child.second.is_scalar() && (i + 1) == path.size()) {
if (child.second->is_scalar() && (i + 1) == path.size()) {
current_ = child;
scalar_value_ = true;
// We want to keep the stack pointing to the container
// in the last key of the key path, since the last element
// of the key path is a scalar, we clear the stack.
stack_.clear();
} else if (child.second.is_container()) {
} else if (child.second->is_container()) {
if ((i + 1) == limits_.max_container_depth) {
break;
}

// Replace the stack top
stack_.back() = child.second.begin(limits_);
stack_.back() = child.second->begin(limits_);

if ((i + 1) < path.size()) {
continue;
Expand Down Expand Up @@ -464,7 +476,7 @@ void kv_iterator::set_cursor_to_next_object()
continue;
}

if (child.second.is_container()) {
if (child.second->is_container()) {
if (previous.second != child.second && !child.first.empty()) {
current_ = child;
scalar_value_ = false;
Expand All @@ -478,10 +490,10 @@ void kv_iterator::set_cursor_to_next_object()
// so we increment the index before a potential reallocation
// and prevent any further use of the references.
++parent_it;
stack_.emplace_back(child.second.begin(limits_));
stack_.emplace_back(child.second->begin(limits_));
continue;
}
} else if (child.second.is_scalar()) {
} else if (child.second->is_scalar()) {
if (previous.second != child.second) {
current_ = child;
if (current_.first.empty()) {
Expand Down
14 changes: 7 additions & 7 deletions src/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ template <typename T> class iterator_base {
[[nodiscard]] explicit operator bool() const { return current_.second.has_value(); }
[[nodiscard]] size_t depth() { return stack_.size() + path_.size(); }
[[nodiscard]] std::vector<std::string> get_current_path() const;
[[nodiscard]] object_view get_underlying_object() { return current_.second; }
[[nodiscard]] optional_object_view get_underlying_object() { return current_.second; }

protected:
static constexpr std::size_t initial_stack_size = 32;
Expand All @@ -51,7 +51,7 @@ template <typename T> class iterator_base {
std::vector<std::string> path_;

std::vector<object_view::iterator> stack_;
std::pair<std::string_view, object_view> current_;
std::pair<std::string_view, optional_object_view> current_;

const exclusion::object_set_ref &excluded_;
};
Expand All @@ -69,9 +69,9 @@ class value_iterator : public iterator_base<value_iterator> {
value_iterator &operator=(const value_iterator &) = delete;
value_iterator &operator=(value_iterator &&) = delete;

[[nodiscard]] object_view operator*() { return current_.second; }
[[nodiscard]] optional_object_view operator*() { return current_.second; }

[[nodiscard]] object_type type() const { return current_.second.type(); }
[[nodiscard]] object_type type() const { return current_.second->type(); }

protected:
void initialise_cursor(object_view obj, const std::span<const std::string> &path);
Expand Down Expand Up @@ -100,7 +100,7 @@ class key_iterator : public iterator_base<key_iterator> {
return !current_.first.empty() ? object_type::string : object_type::invalid;
}

[[nodiscard]] object_view operator*()
[[nodiscard]] optional_object_view operator*()
{
if (current_.first.empty()) {
return {};
Expand Down Expand Up @@ -136,7 +136,7 @@ class kv_iterator : public iterator_base<kv_iterator> {
{
if (current_.second.has_value()) {
if (scalar_value_) {
return current_.second.type_unchecked();
return current_.second->type();
}

if (!current_.first.empty()) {
Expand All @@ -146,7 +146,7 @@ class kv_iterator : public iterator_base<kv_iterator> {
return object_type::invalid;
}

[[nodiscard]] object_view operator*()
[[nodiscard]] optional_object_view operator*()
{
if (current_.second.has_value()) {
if (scalar_value_) {
Expand Down
Loading

0 comments on commit 8a4923a

Please sign in to comment.