Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Float and null type support #197

Merged
merged 10 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion fuzzing/src/object_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ uint64_t popUnsignedInteger(Data *data)
return result;
}

double popDouble(Data *data)
{
double result = 0;

popBytes(data, &result, 8);

return result;
}

int64_t popInteger(Data *data)
{
int64_t result = 0;
Expand Down Expand Up @@ -159,9 +168,18 @@ void build_array(Data *data, ddwaf_object *object, size_t deep)
ddwaf_object create_object(Data *data, size_t deep)
{
ddwaf_object result;
uint8_t selector = popSelector(data, 6);
uint8_t selector = popSelector(data, 9);

switch (selector) {
case 8:
ddwaf_object_invalid(&result);
break;
case 7:
ddwaf_object_null(&result);
break;
case 6:
ddwaf_object_float(&result, popDouble(data));
break;
case 5:
ddwaf_object_bool(&result, popBoolean(data));
break;
Expand Down
72 changes: 56 additions & 16 deletions include/ddwaf.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,22 @@ extern "C"
typedef enum
{
DDWAF_OBJ_INVALID = 0,
/** Value shall be decoded as a int64_t (or int32_t on 32bits platforms). **/
// 64-bit signed integer type
DDWAF_OBJ_SIGNED = 1 << 0,
/** Value shall be decoded as a uint64_t (or uint32_t on 32bits platforms). **/
// 64-bit unsigned integer type
DDWAF_OBJ_UNSIGNED = 1 << 1,
/** Value shall be decoded as a UTF-8 string of length nbEntries. **/
// UTF-8 string of length nbEntries
DDWAF_OBJ_STRING = 1 << 2,
/** Value shall be decoded as an array of ddwaf_object of length nbEntries, each item having no parameterName. **/
// Array of ddwaf_object of length nbEntries, each item having no parameterName
DDWAF_OBJ_ARRAY = 1 << 3,
/** Value shall be decoded as an array of ddwaf_object of length nbEntries, each item having a parameterName. **/
// Array of ddwaf_object of length nbEntries, each item having a parameterName
DDWAF_OBJ_MAP = 1 << 4,

// Boolean type
DDWAF_OBJ_BOOL = 1 << 5,
// 64-bit float (or double) type
DDWAF_OBJ_FLOAT = 1 << 6,
// Null type, only used for its semantical value
DDWAF_OBJ_NULL = 1 << 7,
} DDWAF_OBJ_TYPE;

/**
Expand Down Expand Up @@ -104,6 +108,7 @@ struct _ddwaf_object
int64_t intValue;
ddwaf_object* array;
bool boolean;
double f64;
};
uint64_t nbEntries;
DDWAF_OBJ_TYPE type;
Expand Down Expand Up @@ -315,6 +320,19 @@ void ddwaf_result_free(ddwaf_result *result);
**/
ddwaf_object* ddwaf_object_invalid(ddwaf_object *object);

/**
* ddwaf_object_null
*
* Creates an null object. Provides a different semantical value to invalid as
* it can be used to signify that a value is null rather than of an unknown type.
*
* @param object Object to perform the operation on. (nonnull)
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_null(ddwaf_object *object);


/**
* ddwaf_object_string
*
Expand Down Expand Up @@ -356,32 +374,30 @@ ddwaf_object* ddwaf_object_stringl(ddwaf_object *object, const char *string, siz
ddwaf_object* ddwaf_object_stringl_nc(ddwaf_object *object, const char *string, size_t length);

/**
* ddwaf_object_unsigned
* ddwaf_object_string_from_unsigned
*
* Creates an object using an unsigned integer (64-bit). The resulting object
* will contain a string created using the integer provided. This is the
* preferred method for passing an unsigned integer to the WAF.
* will contain a string created using the integer provided.
*
* @param object Object to perform the operation on. (nonnull)
* @param value Integer to initialise the object with.
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_unsigned(ddwaf_object *object, uint64_t value);
ddwaf_object* ddwaf_object_string_from_unsigned(ddwaf_object *object, uint64_t value);

/**
* ddwaf_object_signed
* ddwaf_object_string_from_signed
*
* Creates an object using a signed integer (64-bit). The resulting object
* will contain a string created using the integer provided. This is the
* preferred method for passing a signed integer to the WAF.
* will contain a string created using the integer provided.
*
* @param object Object to perform the operation on. (nonnull)
* @param value Integer to initialise the object with.
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_signed(ddwaf_object *object, int64_t value);
ddwaf_object* ddwaf_object_string_from_signed(ddwaf_object *object, int64_t value);

/**
* ddwaf_object_unsigned_force
Expand All @@ -394,7 +410,7 @@ ddwaf_object* ddwaf_object_signed(ddwaf_object *object, int64_t value);
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_unsigned_force(ddwaf_object *object, uint64_t value);
ddwaf_object* ddwaf_object_unsigned(ddwaf_object *object, uint64_t value);

/**
* ddwaf_object_signed_force
Expand All @@ -407,7 +423,7 @@ ddwaf_object* ddwaf_object_unsigned_force(ddwaf_object *object, uint64_t value);
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_signed_force(ddwaf_object *object, int64_t value);
ddwaf_object* ddwaf_object_signed(ddwaf_object *object, int64_t value);

/**
* ddwaf_object_bool
Expand All @@ -422,6 +438,19 @@ ddwaf_object* ddwaf_object_signed_force(ddwaf_object *object, int64_t value);
**/
ddwaf_object* ddwaf_object_bool(ddwaf_object *object, bool value);

/**
* ddwaf_object_float
*
* Creates an object using a double, the resulting object will contain a
* double as opposed to a string.
*
* @param object Object to perform the operation on. (nonnull)
* @param value Double to initialise the object with.
*
* @return A pointer to the passed object or NULL if the operation failed.
**/
ddwaf_object* ddwaf_object_float(ddwaf_object *object, double value);

/**
* ddwaf_object_array
*
Expand Down Expand Up @@ -580,6 +609,17 @@ uint64_t ddwaf_object_get_unsigned(const ddwaf_object *object);
**/
int64_t ddwaf_object_get_signed(const ddwaf_object *object);

/**
* ddwaf_object_get_float
*
* Returns the float64 (double) contained within the object.
*
* @param object The object from which to get the float.
*
* @return The float or 0.0 if the object is not a float.
**/
double ddwaf_object_get_float(const ddwaf_object *object);

/**
* ddwaf_object_get_bool
*
Expand Down
7 changes: 5 additions & 2 deletions libddwaf.def
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ EXPORTS
ddwaf_context_destroy
ddwaf_result_free
ddwaf_object_invalid
ddwaf_object_null
ddwaf_object_string
ddwaf_object_stringl
ddwaf_object_stringl_nc
ddwaf_object_string_from_unsigned
ddwaf_object_string_from_signed
ddwaf_object_unsigned
ddwaf_object_signed
ddwaf_object_unsigned_force
ddwaf_object_signed_force
ddwaf_object_bool
ddwaf_object_float
ddwaf_object_array
ddwaf_object_map
ddwaf_object_array_add
Expand All @@ -30,6 +32,7 @@ EXPORTS
ddwaf_object_get_string
ddwaf_object_get_unsigned
ddwaf_object_get_signed
ddwaf_object_get_float
ddwaf_object_get_index
ddwaf_object_get_bool
ddwaf_object_free
Expand Down
4 changes: 4 additions & 0 deletions src/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ memory::string object_to_string(const ddwaf_object &object)
return to_string<memory::string>(object.uintValue);
}

if (object.type == DDWAF_OBJ_FLOAT) {
return to_string<memory::string>(object.f64);
}

return {};
}

Expand Down
1 change: 1 addition & 0 deletions src/iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ void value_iterator::initialise_cursor_with_path(
set_cursor_to_next_object();
}

// If null or invalid, we ignore it
break;
}

Expand Down
6 changes: 6 additions & 0 deletions src/matcher/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ template <typename T> class base_impl : public base {
}
}

if constexpr (T::supported_type_impl() == DDWAF_OBJ_FLOAT) {
if (obj.type == DDWAF_OBJ_FLOAT) {
return ptr->match_impl(obj.f64);
}
}

return {false, {}};
}
};
Expand Down
34 changes: 31 additions & 3 deletions src/matcher/equals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@
#include <clock.hpp>
#include <matcher/base.hpp>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <utils.hpp>

namespace ddwaf::matcher {

template <typename T> class equals : public base_impl<equals<T>> {
public:
using rule_data_type = std::vector<std::pair<std::string_view, uint64_t>>;

explicit equals(T expected) : expected_(std::move(expected)) {}
explicit equals(T expected)
requires(!std::is_floating_point_v<T>)
: expected_(std::move(expected))
{}
~equals() override = default;
equals(const equals &) = default;
equals(equals &&) noexcept = default;
Expand Down Expand Up @@ -64,4 +66,30 @@ template <typename T> class equals : public base_impl<equals<T>> {
friend class base_impl<equals<T>>;
};

template <> class equals<double> : public base_impl<equals<double>> {
public:
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
equals(double expected, double delta) : expected_(expected), delta_(delta) {}
~equals() override = default;
equals(const equals &) = default;
equals(equals &&) noexcept = default;
equals &operator=(const equals &) = default;
equals &operator=(equals &&) noexcept = default;

protected:
static constexpr std::string_view to_string_impl() { return ""; }
static constexpr std::string_view name_impl() { return "equals"; }
static constexpr DDWAF_OBJ_TYPE supported_type_impl() { return DDWAF_OBJ_FLOAT; }

[[nodiscard]] std::pair<bool, memory::string> match_impl(double obtained) const
{
return {std::abs(expected_ - obtained) < delta_, {}};
}

double expected_;
double delta_;

friend class base_impl<equals<double>>;
};

} // namespace ddwaf::matcher
Loading