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

refactor(userspace/libsinsp): catch filter field-operator compatibility at compile-time instead of run-time #1857

Merged
merged 8 commits into from
May 16, 2024
2 changes: 1 addition & 1 deletion userspace/libsinsp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ add_library(sinsp
sinsp_filtercheck_tracer.cpp
sinsp_filtercheck_user.cpp
sinsp_filtercheck_utils.cpp
filter_compare.cpp
filter_check_list.cpp
ifinfo.cpp
memmem.cpp
metrics_collector.cpp
logger.cpp
parsers.cpp
Expand Down
93 changes: 13 additions & 80 deletions userspace/libsinsp/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ limitations under the License.
#include <libsinsp/filter/parser.h>
#include <libsinsp/sinsp_filtercheck.h>
#include <libsinsp/plugin_filtercheck.h>
#include <libsinsp/filter_compare.h>

///////////////////////////////////////////////////////////////////////////////
// sinsp_filter_expression implementation
Expand Down Expand Up @@ -304,6 +305,16 @@ void sinsp_filter_compiler::visit(const libsinsp::filter::ast::not_expr* e)
m_filter->pop_expression();
}

static inline void check_op_type_compatibility(sinsp_filter_check& c)
{
std::string err;
auto fi = c.get_transformed_field_info();
if (fi && !flt_is_comparable(c.m_cmpop, fi->m_type, fi->is_list(), err))
{
throw sinsp_exception("filter error: " + err);
}
}

void sinsp_filter_compiler::visit(const libsinsp::filter::ast::unary_check_expr* e)
{
m_pos = e->get_pos();
Expand All @@ -317,6 +328,7 @@ void sinsp_filter_compiler::visit(const libsinsp::filter::ast::unary_check_expr*
auto check = std::move(m_last_node_field);
check->m_cmpop = str_to_cmpop(e->op);
check->m_boolop = m_last_boolop;
check_op_type_compatibility(*check);
m_filter->add_check(std::move(check));
}

Expand Down Expand Up @@ -354,6 +366,7 @@ void sinsp_filter_compiler::visit(const libsinsp::filter::ast::binary_check_expr
auto check = std::move(m_last_node_field);
check->m_cmpop = str_to_cmpop(e->op);
check->m_boolop = m_last_boolop;
check_op_type_compatibility(*check);

// Read the right-hand values of the filtercheck.
m_last_node_field_is_plugin = false;
Expand Down Expand Up @@ -515,86 +528,6 @@ std::unique_ptr<sinsp_filter_check> sinsp_filter_compiler::create_filtercheck(st
return chk;
}

cmpop sinsp_filter_compiler::str_to_cmpop(std::string_view str)
{
if(str == "=" || str == "==")
{
return CO_EQ;
}
else if(str == "!=")
{
return CO_NE;
}
else if(str == "<=")
{
return CO_LE;
}
else if(str == "<")
{
return CO_LT;
}
else if(str == ">=")
{
return CO_GE;
}
else if(str == ">")
{
return CO_GT;
}
else if(str == "contains")
{
return CO_CONTAINS;
}
else if(str == "icontains")
{
return CO_ICONTAINS;
}
else if(str == "bcontains")
{
return CO_BCONTAINS;
}
else if(str == "startswith")
{
return CO_STARTSWITH;
}
else if(str == "bstartswith")
{
return CO_BSTARTSWITH;
}
else if(str == "endswith")
{
return CO_ENDSWITH;
}
else if(str == "in")
{
return CO_IN;
}
else if(str == "intersects")
{
return CO_INTERSECTS;
}
else if(str == "pmatch")
{
return CO_PMATCH;
}
else if(str == "exists")
{
return CO_EXISTS;
}
else if(str == "glob")
{
return CO_GLOB;
}
else if(str == "iglob")
{
return CO_IGLOB;
}
// we are not supposed to get here, as the parser pre-checks this
ASSERT(false);
throw sinsp_exception("filter error: unrecognized comparison operator '" + std::string(str) + "'");
}


sinsp_filter_factory::sinsp_filter_factory(sinsp *inspector,
filter_check_list &available_checks)
: m_inspector(inspector), m_available_checks(available_checks)
Expand Down
1 change: 0 additions & 1 deletion userspace/libsinsp/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ class SINSP_PUBLIC sinsp_filter_compiler:
void visit(const libsinsp::filter::ast::binary_check_expr*) override;
void visit(const libsinsp::filter::ast::field_expr*) override;
void visit(const libsinsp::filter::ast::field_transformer_expr*) override;
cmpop str_to_cmpop(std::string_view);
std::string create_filtercheck_name(const std::string& name, const std::string& arg);
std::unique_ptr<sinsp_filter_check> create_filtercheck(std::string_view field);
void check_value_and_add_warnings(const libsinsp::filter::ast::pos_info& pos, const std::string& v);
Expand Down
Loading
Loading