[Forensics-changes] [yara] 74/415: Implemented callback abortion in yara-python and fixed some problems with references counting.

Hilko Bengen bengen at moszumanska.debian.org
Thu Apr 3 05:42:46 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch debian
in repository yara.

commit 7029183deae7ff90852f23d7989f47cdb3509d7d
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Sat Feb 19 20:46:10 2011 +0000

    Implemented callback abortion in yara-python and fixed some problems with references counting.
---
 yara-python/yara-python.c | 193 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 135 insertions(+), 58 deletions(-)

diff --git a/yara-python/yara-python.c b/yara-python/yara-python.c
index 691b841..110b5bc 100644
--- a/yara-python/yara-python.c
+++ b/yara-python/yara-python.c
@@ -56,7 +56,6 @@ the rules to your data. This method can receive a file path or a string       \n
 containing the data.                                                          \n\
                                                                               \n\
 matches = rules.match(filepath='/foo/bar/myfile')                             \n\
-                                                                              \n\
 matches = rules.match('/foo/bar/myfile')                                      \n\
                                                                               \n\
 f = fopen('/foo/bar/myfile', 'rb')                                            \n\
@@ -83,7 +82,7 @@ The \"Match\" class have the following attributes:                            \n
 - namespace	                                                                  \n\
 - meta	                                                                      \n\
 - tags	                                                                      \n\
-- string	                                                                  \n\
+- strings	                                                                  \n\
 	                                                                          \n\
 The \"rule\" and \"namespace\" attributes are the names of the matching rule and\n\
 its namespace respectively.                                                   \n\
@@ -438,33 +437,58 @@ static void Rules_dealloc(PyObject *self)
     PyObject_Del(self);
 }
 
-int callback(RULE* rule, void* data)
+
+typedef struct _CALLBACK_DATA {
+
+    PyObject *matches;
+    PyObject *callback;
+    
+} CALLBACK_DATA;
+
+
+int yara_callback(RULE* rule, void* data)
 {
     TAG* tag;
     STRING* string;
     MATCH* m;
     META* meta;
-    PyObject* taglist = NULL;
-    PyObject* stringlist = NULL;
-    PyObject* metalist = NULL;
+    
+    PyObject* tag_list = NULL;
+    PyObject* string_list = NULL;
+    PyObject* meta_list = NULL;
     PyObject* match;
-    PyObject* list = (PyObject*) data;
+    PyObject* callback_dict;
+    PyObject* object;
+    PyObject* matches = ((CALLBACK_DATA*) data)->matches;
+    PyObject* callback = ((CALLBACK_DATA*) data)->callback;
+    PyObject* callback_result;
     
-    if (!(rule->flags & RULE_FLAGS_MATCH))
-        return 0;
-       
-    taglist = PyList_New(0);
-    stringlist = PyList_New(0);
-    metalist = PyDict_New();
+    long result = CALLBACK_CONTINUE;
+    
+    if (!(rule->flags & RULE_FLAGS_MATCH) && callback == NULL)
+        return CALLBACK_CONTINUE;
     
-    if (taglist == NULL || stringlist == NULL || metalist == NULL)
-        return 1; // error!
+    tag_list = PyList_New(0);
+    string_list = PyList_New(0);
+    meta_list = PyDict_New();
+    
+    if (tag_list == NULL || string_list == NULL || meta_list == NULL)
+    {
+        Py_XDECREF(tag_list);
+        Py_XDECREF(string_list);
+        Py_XDECREF(meta_list);
         
+        return CALLBACK_ERROR;
+    }           
+    
     tag = rule->tag_list_head;
     
     while(tag != NULL)
     {
-        PyList_Append(taglist, PyString_FromString(tag->identifier));               
+        object = PyString_FromString(tag->identifier);
+        PyList_Append(tag_list, object);
+        Py_DECREF(object);    
+                   
         tag = tag->next;
     }      
     
@@ -474,23 +498,20 @@ int callback(RULE* rule, void* data)
     {
         if (meta->type == META_TYPE_INTEGER)
         {
-            PyDict_SetItem( metalist, 
-                            PyString_FromString(meta->identifier),
-                            Py_BuildValue("I", meta->integer));  
+            object = Py_BuildValue("I", meta->integer);
         }
         else if (meta->type == META_TYPE_BOOLEAN)
         {
-            PyDict_SetItem( metalist, 
-                            PyString_FromString(meta->identifier),
-                            PyBool_FromLong(meta->boolean));  
+            object = PyBool_FromLong(meta->boolean);
         }
         else
         {
-            PyDict_SetItem( metalist, 
-                            PyString_FromString(meta->identifier),
-                            PyString_FromString(meta->string));    
+            object = PyString_FromString(meta->string);
         }
         
+        PyDict_SetItemString( meta_list, meta->identifier, object);  
+        Py_DECREF(object);
+        
         meta = meta->next;
     } 
     
@@ -504,8 +525,10 @@ int callback(RULE* rule, void* data)
 
             while (m != NULL)
             {
-                PyList_Append(  stringlist, 
-                                Py_BuildValue("(i,s,s#)", m->offset, string->identifier, (char*) m->data, m->length));
+                object = Py_BuildValue("(i,s,s#)", m->offset, string->identifier, (char*) m->data, m->length);
+                PyList_Append(string_list, object);
+                Py_DECREF(object);
+                
                 m = m->next;
             }
         }
@@ -513,29 +536,68 @@ int callback(RULE* rule, void* data)
         string = string->next;
     }
     
-    PyList_Sort(stringlist);
-       
-    match = Match_NEW(rule->identifier, rule->ns->name, taglist, metalist, stringlist);
+    PyList_Sort(string_list);
     
-    if (match != NULL)
-    {       
-        PyList_Append(list, match);
-    }
-    else
+    if (rule->flags & RULE_FLAGS_MATCH)
     {
-        Py_DECREF(taglist);
-        Py_DECREF(stringlist);
-        Py_DECREF(metalist);
-        return 1;
+        match = Match_NEW(rule->identifier, rule->ns->name, tag_list, meta_list, string_list);
+
+        if (match != NULL)
+        {       
+            PyList_Append(matches, match);
+            Py_DECREF(match);
+        }
+        else
+        {
+            Py_DECREF(tag_list);
+            Py_DECREF(string_list);
+            Py_DECREF(meta_list);
+    
+            return CALLBACK_ERROR;
+        }
     }
     
-    return 0;
+    if (callback != NULL)
+	{
+	    Py_INCREF(callback); 
+	    
+	    callback_dict = PyDict_New();
+	    
+	    object = PyBool_FromLong(rule->flags & RULE_FLAGS_MATCH);
+        PyDict_SetItemString(callback_dict, "matches", object);
+        Py_DECREF(object);
+	    
+        object = PyString_FromString(rule->identifier);        
+        PyDict_SetItemString(callback_dict, "rule", object);
+        Py_DECREF(object);
+        
+        object = PyString_FromString(rule->ns->name);
+        PyDict_SetItemString(callback_dict, "namespace", object);
+        Py_DECREF(object);
+        
+	    PyDict_SetItemString(callback_dict, "tags", tag_list);
+	    PyDict_SetItemString(callback_dict, "meta", meta_list);
+	    PyDict_SetItemString(callback_dict, "strings", string_list);
+
+		callback_result = PyObject_CallFunction(callback, "O", callback_dict);
+		
+		if (PyInt_Check(callback_result))
+		{
+		    result = PyInt_AsLong(callback_result);
+		}
+    
+        Py_DECREF(callback_dict);
+		Py_DECREF(callback_result);
+		Py_DECREF(callback); 
+	}
+    
+    return result;
 
 }
 
 PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
 {
-    static char *kwlist[] = {"filepath", "pid", "data", "externals", NULL};
+    static char *kwlist[] = {"filepath", "pid", "data", "externals", "callback", NULL};
     
     char* filepath = NULL;
     char* data = NULL;
@@ -544,12 +606,16 @@ PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
     int length;
     int result;
     
-    PyObject *matches = NULL;
     PyObject *externals = NULL;
-       
+    
+    CALLBACK_DATA callback_data;
+    
+    callback_data.matches = NULL;
+    callback_data.callback = NULL;
+    
     Rules* object = (Rules*) self;
     
-    if (PyArg_ParseTupleAndKeywords(args, keywords, "|sis#O", kwlist, &filepath, &pid, &data, &length, &externals))
+    if (PyArg_ParseTupleAndKeywords(args, keywords, "|sis#OO", kwlist, &filepath, &pid, &data, &length, &externals, &callback_data.callback))
     {
         if (externals != NULL)
         {
@@ -566,15 +632,23 @@ PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
 			}
         }
              
+        if (callback_data.callback != NULL)
+        {
+            if (!PyCallable_Check(callback_data.callback)) 
+            {
+                return PyErr_Format(YaraError, "callback must be callable");
+            }
+        }
+             
         if (filepath != NULL)
         {    
-            matches = PyList_New(0);
+            callback_data.matches = PyList_New(0);
         
-            result = yr_scan_file(filepath, object->context, callback, matches);
+            result = yr_scan_file(filepath, object->context, yara_callback, &callback_data);
 
             if (result != ERROR_SUCCESS)
             {
-                Py_DECREF(matches);
+                Py_DECREF(callback_data.matches);
 
                 switch(result)
                 {
@@ -591,25 +665,25 @@ PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
         }
         else if (data != NULL)
         {
-            matches = PyList_New(0);
+            callback_data.matches = PyList_New(0);
         
-			result = yr_scan_mem((unsigned char*) data, (unsigned int) length, object->context, callback, matches);
+			result = yr_scan_mem((unsigned char*) data, (unsigned int) length, object->context, yara_callback, &callback_data);
 
             if (result != ERROR_SUCCESS)
             {
-               Py_DECREF(matches);
+               Py_DECREF(callback_data.matches);
                return PyErr_Format(PyExc_Exception, "internal error"); 
             }
         }
         else if (pid != 0)
         {
-            matches = PyList_New(0);
+            callback_data.matches = PyList_New(0);
             
-            result = yr_scan_proc(pid, object->context, callback, matches);
+            result = yr_scan_proc(pid, object->context, yara_callback, &callback_data);
             
             if (result != ERROR_SUCCESS)
             {
-               Py_DECREF(matches);
+               Py_DECREF(callback_data.matches);
                
                switch(result)
                {
@@ -628,7 +702,7 @@ PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
         }
     }
     
-    return matches;
+    return callback_data.matches;
 }
 
 static PyObject * Rules_getattro(PyObject *self, PyObject *name)
@@ -812,14 +886,16 @@ static PyMethodDef methods[] = {
 
 void inityara(void)
 { 
-    PyObject *m, *d;
+    PyObject *m;
     
     yr_init();
  
     m = Py_InitModule3("yara", methods, module_doc);
-    d = PyModule_GetDict(m);
     
     /* initialize module variables/constants */
+    
+    PyModule_AddIntConstant(m, "CALLBACK_CONTINUE", 0);
+    PyModule_AddIntConstant(m, "CALLBACK_ABORT", 1);
 
 #if PYTHON_API_VERSION >= 1007
     YaraError = PyErr_NewException("yara.Error", PyExc_StandardError, NULL);
@@ -828,6 +904,7 @@ void inityara(void)
     YaraError = Py_BuildValue("s", "yara.Error");
     YaraSyntaxError = Py_BuildValue("s", "yara.SyntaxError");
 #endif
-    PyDict_SetItemString(d, "Error", YaraError);
-    PyDict_SetItemString(d, "SyntaxError", YaraSyntaxError);
+
+    PyModule_AddObject(m, "Error", YaraError);
+    PyModule_AddObject(m, "SyntaxError", YaraSyntaxError);
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list