3535#include " absl/strings/str_split.h"
3636#include " absl/strings/string_view.h"
3737#include " absl/types/optional.h"
38+ #include " re2/re2.h"
39+
40+ // Pattern for expression [lhs][operator][rhs]
41+ constexpr LazyRE2 kRelationalExpressionRegex = {
42+ " ^(?P<left>[^\\ s<=>!]+)(?:(<=|>=|!=|>|<|=)(?P<right>[^<=>!]+))$" };
3843
3944constexpr std::array<const char *, 6 > kPredicateOperators = {
4045 " <=" , " >=" , " !=" , " >" , " <" , " =" ,
@@ -64,14 +69,19 @@ struct EncodedPredicate {
6469absl::StatusOr<RelationalExpression> EncodeRelationalExpression (
6570 std::string_view expression) {
6671 RelationalExpression relational_expression;
67- for (const std::string predicate_operator : kPredicateOperators ) {
68- auto pos = expression.find (predicate_operator);
69- if (pos == std::string::npos) continue ;
70- RelationalExpression rel_expr;
71- rel_expr.lhs = expression.substr (0 , pos);
72- rel_expr.rel_operator = predicate_operator;
73- rel_expr.rhs = expression.substr (pos + predicate_operator.size ());
74- return rel_expr;
72+
73+ // Regex match the expression. The operator must be a valid relational
74+ // operator and the right hand side must not have spaces or characters
75+ // included in relation operators.
76+ std::string lhs;
77+ std::string op;
78+ std::string rhs;
79+ if (RE2::FullMatch (expression, *kRelationalExpressionRegex , &lhs, &op,
80+ &rhs)) {
81+ relational_expression.lhs = lhs;
82+ relational_expression.rel_operator = op;
83+ relational_expression.rhs = rhs;
84+ return relational_expression;
7585 }
7686 return absl::InvalidArgumentError (" Invalid expression" );
7787}
@@ -83,7 +93,7 @@ absl::StatusOr<RelationalExpression> EncodeRelationalExpression(
8393// expressions = [[lhs: "Prop1", rel_operator: "<=", rhs: "42"],
8494// [lhs: "Prop1", rel_operator: ">", rhs: "84"]
8595// ]
86- EncodedPredicate EncodePredicate (absl::string_view predicate) {
96+ absl::StatusOr< EncodedPredicate> EncodePredicate (absl::string_view predicate) {
8797 // The high level logic of this function is to break down the predicate into
8898 // logical operators (or/and) and the relational expressions (prop>value).
8999 // After breaking them up go through the relational expressions and break them
@@ -120,6 +130,9 @@ EncodedPredicate EncodePredicate(absl::string_view predicate) {
120130 auto encoded_expression = EncodeRelationalExpression (expression);
121131 if (encoded_expression.ok ()) {
122132 encoded_predicate.expressions .push_back (encoded_expression.value ());
133+ } else {
134+ // Invalid expression, return an error
135+ return absl::InvalidArgumentError (encoded_expression.status ().message ());
123136 }
124137 }
125138 return encoded_predicate;
@@ -206,15 +219,29 @@ std::string GenerateFilterString(const EncodedPredicate &predicate_object) {
206219
207220void RedfishQueryParamFilter::BuildFromRedpathPredicate (
208221 absl::string_view predicate) {
209- filter_string_ = GenerateFilterString (EncodePredicate (predicate));
222+ auto encoded_predicate = EncodePredicate (predicate);
223+ if (!encoded_predicate.ok ()) {
224+ // Invalid predicate, set filter_string_ to empty, indicating an invalid
225+ // expression, and return.
226+ filter_string_ = " " ;
227+ return ;
228+ }
229+ filter_string_ = GenerateFilterString (*encoded_predicate);
210230}
211231
212232void RedfishQueryParamFilter::BuildFromRedpathPredicateList (
213233 const std::vector<std::string> &predicates) {
214234 std::vector<std::string> filter_strings;
215235 filter_strings.reserve (predicates.size ());
216236 for (absl::string_view predicate : predicates) {
217- filter_strings.push_back (GenerateFilterString (EncodePredicate (predicate)));
237+ auto encoded_predicate = EncodePredicate (predicate);
238+ if (!encoded_predicate.ok ()) {
239+ // Invalid predicate, set filter_string_ to empty, indicating an invalid
240+ // expression, and return.
241+ filter_string_ = " " ;
242+ return ;
243+ }
244+ filter_strings.push_back (GenerateFilterString (*encoded_predicate));
218245 }
219246 filter_string_ = absl::StrJoin (filter_strings, " %20or%20" );
220247}
0 commit comments