From 5224381e4f8226fb6fcbb9cf7b4c2e5b79e2db72 Mon Sep 17 00:00:00 2001 From: Wesley Shields Date: Thu, 23 Apr 2020 06:57:43 -0400 Subject: [PATCH] Support a "is_global" and "is_private" member on Rules. (#130) * Support a "is_global" and "is_private" member on Rules. When writing linters it is currently impossible to know (via rule introspection) if a given rule is private or global. We have banned global rules for our use case and we have to resort to a janky regex against our rules files to know if anyone is about to commit a global rule. I figure exposing these two flags via python will be useful for programatically checking those bits. I'm not very pleased with the name "is_global" - I wanted to go with just "global" and "private" but "global" is a reserved keyword and rule.global breaks the python interpreter. I'm open to changing the member names if you have any suggestions. * Decrement reference counts on global and private. * Update global and private checks after API changes. --- tests.py | 12 ++++++++++++ yara-python.c | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests.py b/tests.py index 05e3576..80babff 100644 --- a/tests.py +++ b/tests.py @@ -1038,6 +1038,18 @@ def testSetConfig(self): yara.set_config(max_strings_per_rule=10000) + def testGlobalPrivate(self): + + rules = """ + global rule a { condition: true } + private rule b { condition: true } + """ + + # Have to convert to a list because Rules are not subscriptable, yet... + r = list(yara.compile(source=rules)) + self.assertTrue(r[0].is_global == True) + self.assertTrue(r[1].is_private == True) + if __name__ == "__main__": unittest.main() diff --git a/yara-python.c b/yara-python.c index 48d000c..b300b8f 100644 --- a/yara-python.c +++ b/yara-python.c @@ -206,6 +206,8 @@ typedef struct PyObject* identifier; PyObject* tags; PyObject* meta; + PyObject* global; + PyObject* private; } Rule; static void Rule_dealloc( @@ -216,6 +218,20 @@ static PyObject* Rule_getattro( PyObject* name); static PyMemberDef Rule_members[] = { + { + "is_global", + T_OBJECT_EX, + offsetof(Rule, global), + READONLY, + "Rule is global" + }, + { + "is_private", + T_OBJECT_EX, + offsetof(Rule, private), + READONLY, + "Rule is private" + }, { "identifier", T_OBJECT_EX, @@ -1240,6 +1256,8 @@ static void Rule_dealloc( Py_XDECREF(object->identifier); Py_XDECREF(object->tags); Py_XDECREF(object->meta); + Py_XDECREF(object->global); + Py_XDECREF(object->private); PyObject_Del(self); } @@ -1326,6 +1344,8 @@ static PyObject* Rules_next( Py_DECREF(object); } + rule->global = PyBool_FromLong(rules->iter_current_rule->flags & RULE_FLAGS_GLOBAL); + rule->private = PyBool_FromLong(rules->iter_current_rule->flags & RULE_FLAGS_PRIVATE); rule->identifier = PY_STRING(rules->iter_current_rule->identifier); rule->tags = tag_list; rule->meta = meta_list;