Commit 95702bb3 by Victor M. Alvarez

Refactor yara_callback.

This function has grown too much, so it was split in multiple functions in order to make it easier to understand.
parent a8011dd0
...@@ -519,8 +519,6 @@ PyObject* convert_structure_to_python( ...@@ -519,8 +519,6 @@ PyObject* convert_structure_to_python(
PyObject* convert_array_to_python( PyObject* convert_array_to_python(
YR_OBJECT_ARRAY* array) YR_OBJECT_ARRAY* array)
{ {
int i;
PyObject* py_object; PyObject* py_object;
PyObject* py_list = PyList_New(0); PyObject* py_list = PyList_New(0);
...@@ -531,7 +529,7 @@ PyObject* convert_array_to_python( ...@@ -531,7 +529,7 @@ PyObject* convert_array_to_python(
if (array->items == NULL) if (array->items == NULL)
return py_list; return py_list;
for (i = 0; i < array->items->length; i++) for (int i = 0; i < array->items->length; i++)
{ {
py_object = convert_object_to_python(array->items->objects[i]); py_object = convert_object_to_python(array->items->objects[i]);
...@@ -549,8 +547,6 @@ PyObject* convert_array_to_python( ...@@ -549,8 +547,6 @@ PyObject* convert_array_to_python(
PyObject* convert_dictionary_to_python( PyObject* convert_dictionary_to_python(
YR_OBJECT_DICTIONARY* dictionary) YR_OBJECT_DICTIONARY* dictionary)
{ {
int i;
PyObject* py_object; PyObject* py_object;
PyObject* py_dict = PyDict_New(); PyObject* py_dict = PyDict_New();
...@@ -561,7 +557,7 @@ PyObject* convert_dictionary_to_python( ...@@ -561,7 +557,7 @@ PyObject* convert_dictionary_to_python(
if (dictionary->items == NULL) if (dictionary->items == NULL)
return py_dict; return py_dict;
for (i = 0; i < dictionary->items->used; i++) for (int i = 0; i < dictionary->items->used; i++)
{ {
py_object = convert_object_to_python(dictionary->items->objects[i].obj); py_object = convert_object_to_python(dictionary->items->objects[i].obj);
...@@ -580,71 +576,17 @@ PyObject* convert_dictionary_to_python( ...@@ -580,71 +576,17 @@ PyObject* convert_dictionary_to_python(
} }
#define CALLBACK_MATCHES 0x01 static int handle_import_module(
#define CALLBACK_NON_MATCHES 0x02 YR_MODULE_IMPORT* module_import,
#define CALLBACK_ALL CALLBACK_MATCHES | CALLBACK_NON_MATCHES CALLBACK_DATA* data)
int yara_callback(
YR_SCAN_CONTEXT* context,
int message,
void* message_data,
void* user_data)
{ {
YR_STRING* string; if (data->modules_data == NULL)
YR_MATCH* m;
YR_META* meta;
YR_RULE* rule;
YR_MODULE_IMPORT* module_import;
const char* tag;
PyObject* tag_list = NULL;
PyObject* string_list = NULL;
PyObject* meta_list = NULL;
PyObject* match;
PyObject* callback_dict;
PyObject* object;
PyObject* tuple;
PyObject* matches = ((CALLBACK_DATA*) user_data)->matches;
PyObject* callback = ((CALLBACK_DATA*) user_data)->callback;
PyObject* modules_data = ((CALLBACK_DATA*) user_data)->modules_data;
PyObject* modules_callback = ((CALLBACK_DATA*) user_data)->modules_callback;
PyObject* warning_callback = ((CALLBACK_DATA*) user_data)->warning_callback;
PyObject* module_data;
PyObject* callback_result;
PyObject* module_info_dict;
PyObject* identifier;
PyObject* warning_type;
int which = ((CALLBACK_DATA*) user_data)->which;
Py_ssize_t data_size;
PyGILState_STATE gil_state;
int result = CALLBACK_CONTINUE;
// If the rule doesn't match and the user has not specified that they want to
// see non-matches then nothing to do here.
if (message == CALLBACK_MSG_RULE_NOT_MATCHING && callback != NULL &&
(which & CALLBACK_NON_MATCHES) != CALLBACK_NON_MATCHES)
return CALLBACK_CONTINUE;
if (message == CALLBACK_MSG_SCAN_FINISHED)
return CALLBACK_CONTINUE;
if (message == CALLBACK_MSG_IMPORT_MODULE && modules_data == NULL)
return CALLBACK_CONTINUE;
if (message == CALLBACK_MSG_MODULE_IMPORTED && modules_callback == NULL)
return CALLBACK_CONTINUE; return CALLBACK_CONTINUE;
if (message == CALLBACK_MSG_IMPORT_MODULE) PyGILState_STATE gil_state = PyGILState_Ensure();
{
gil_state = PyGILState_Ensure();
module_import = (YR_MODULE_IMPORT*) message_data;
module_data = PyDict_GetItemString( PyObject* module_data = PyDict_GetItemString(
modules_data, data->modules_data,
module_import->module_name); module_import->module_name);
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -653,6 +595,8 @@ int yara_callback( ...@@ -653,6 +595,8 @@ int yara_callback(
if (module_data != NULL && PyString_Check(module_data)) if (module_data != NULL && PyString_Check(module_data))
#endif #endif
{ {
Py_ssize_t data_size;
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
PyBytes_AsStringAndSize( PyBytes_AsStringAndSize(
module_data, module_data,
...@@ -669,30 +613,42 @@ int yara_callback( ...@@ -669,30 +613,42 @@ int yara_callback(
} }
PyGILState_Release(gil_state); PyGILState_Release(gil_state);
return CALLBACK_CONTINUE; return CALLBACK_CONTINUE;
} }
if (message == CALLBACK_MSG_MODULE_IMPORTED)
{
gil_state = PyGILState_Ensure();
module_info_dict = convert_structure_to_python( static int handle_module_imported(
void* message_data,
CALLBACK_DATA* data)
{
if (data->modules_callback == NULL)
return CALLBACK_CONTINUE;
PyGILState_STATE gil_state = PyGILState_Ensure();
PyObject* module_info_dict = convert_structure_to_python(
object_as_structure(message_data)); object_as_structure(message_data));
if (module_info_dict == NULL) if (module_info_dict == NULL)
{
PyGILState_Release(gil_state);
return CALLBACK_CONTINUE; return CALLBACK_CONTINUE;
}
object = PY_STRING(object_as_structure(message_data)->identifier); PyObject* object = PY_STRING(object_as_structure(message_data)->identifier);
PyDict_SetItemString(module_info_dict, "module", object); PyDict_SetItemString(module_info_dict, "module", object);
Py_DECREF(object); Py_DECREF(object);
Py_INCREF(modules_callback); Py_INCREF(data->modules_callback);
callback_result = PyObject_CallFunctionObjArgs( PyObject* callback_result = PyObject_CallFunctionObjArgs(
modules_callback, data->modules_callback,
module_info_dict, module_info_dict,
NULL); NULL);
int result = CALLBACK_CONTINUE;
if (callback_result != NULL) if (callback_result != NULL)
{ {
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -703,31 +659,38 @@ int yara_callback( ...@@ -703,31 +659,38 @@ int yara_callback(
{ {
result = (int) PyLong_AsLong(callback_result); result = (int) PyLong_AsLong(callback_result);
} }
Py_DECREF(callback_result);
} }
else else
{ {
result = CALLBACK_ERROR; result = CALLBACK_ERROR;
} }
Py_XDECREF(callback_result);
Py_DECREF(module_info_dict); Py_DECREF(module_info_dict);
Py_DECREF(modules_callback); Py_DECREF(data->modules_callback);
PyGILState_Release(gil_state); PyGILState_Release(gil_state);
return result; return result;
} }
if (message == CALLBACK_MSG_TOO_MANY_MATCHES)
{
gil_state = PyGILState_Ensure();
if (warning_callback == NULL) static int handle_too_many_matches(
YR_SCAN_CONTEXT* context,
YR_STRING* string,
CALLBACK_DATA* data)
{
PyGILState_STATE gil_state = PyGILState_Ensure();
PyObject* warning_type = NULL;
PyObject* identifier = NULL;
int result = CALLBACK_CONTINUE;
if (data->warning_callback == NULL)
{ {
char message[200]; char message[200];
string = (YR_STRING*) message_data;
snprintf( snprintf(
message, message,
sizeof(message), sizeof(message),
...@@ -735,38 +698,31 @@ int yara_callback( ...@@ -735,38 +698,31 @@ int yara_callback(
string->identifier, string->identifier,
context->rules->rules_table[string->rule_idx].identifier); context->rules->rules_table[string->rule_idx].identifier);
result = PyErr_WarnEx(PyExc_RuntimeWarning, message, 1); if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1) == -1)
if (result == -1)
result = CALLBACK_ERROR; result = CALLBACK_ERROR;
else
result = CALLBACK_CONTINUE;
PyGILState_Release(gil_state);
return result;
} }
else else
{ {
identifier = PyBytes_FromString(((YR_STRING*) message_data)->identifier); Py_INCREF(data->warning_callback);
identifier = PyBytes_FromString(string->identifier);
if (identifier == NULL) if (identifier == NULL)
{ {
PyGILState_Release(gil_state); result = CALLBACK_ERROR;
return CALLBACK_ERROR; goto _exit;
} }
warning_type = PyLong_FromLong(CALLBACK_MSG_TOO_MANY_MATCHES); warning_type = PyLong_FromLong(CALLBACK_MSG_TOO_MANY_MATCHES);
if (warning_type == NULL) if (warning_type == NULL)
{ {
Py_DECREF(identifier); result = CALLBACK_ERROR;
PyGILState_Release(gil_state); goto _exit;
return CALLBACK_ERROR;
} }
Py_INCREF(warning_callback); PyObject* callback_result = PyObject_CallFunctionObjArgs(
data->warning_callback,
callback_result = PyObject_CallFunctionObjArgs(
warning_callback,
warning_type, warning_type,
identifier, identifier,
NULL); NULL);
...@@ -781,21 +737,77 @@ int yara_callback( ...@@ -781,21 +737,77 @@ int yara_callback(
{ {
result = (int) PyLong_AsLong(callback_result); result = (int) PyLong_AsLong(callback_result);
} }
Py_DECREF(callback_result);
} }
else else
{ {
result = CALLBACK_ERROR; result = CALLBACK_ERROR;
} }
Py_DECREF(identifier); Py_XDECREF(callback_result);
Py_DECREF(warning_type); }
Py_DECREF(warning_callback);
_exit:
Py_XDECREF(identifier);
Py_XDECREF(warning_type);
Py_XDECREF(data->warning_callback);
PyGILState_Release(gil_state); PyGILState_Release(gil_state);
return result;
}
#define CALLBACK_MATCHES 0x01
#define CALLBACK_NON_MATCHES 0x02
#define CALLBACK_ALL CALLBACK_MATCHES | CALLBACK_NON_MATCHES
int yara_callback(
YR_SCAN_CONTEXT* context,
int message,
void* message_data,
void* user_data)
{
YR_STRING* string;
YR_MATCH* m;
YR_META* meta;
YR_RULE* rule;
const char* tag;
PyObject* tag_list = NULL;
PyObject* string_list = NULL;
PyObject* meta_list = NULL;
PyObject* match;
PyObject* callback_dict;
PyObject* object;
PyObject* tuple;
PyObject* matches = ((CALLBACK_DATA*) user_data)->matches;
PyObject* callback = ((CALLBACK_DATA*) user_data)->callback;
PyObject* callback_result;
int which = ((CALLBACK_DATA*) user_data)->which;
// If the rule doesn't match and the user has not specified that they want to
// see non-matches then nothing to do here.
if (message == CALLBACK_MSG_RULE_NOT_MATCHING && callback != NULL &&
(which & CALLBACK_NON_MATCHES) != CALLBACK_NON_MATCHES)
return CALLBACK_CONTINUE;
switch(message)
{
case CALLBACK_MSG_IMPORT_MODULE:
return handle_import_module(message_data, user_data);
case CALLBACK_MSG_MODULE_IMPORTED:
return handle_module_imported(message_data, user_data);
case CALLBACK_MSG_TOO_MANY_MATCHES:
return handle_too_many_matches(context, message_data, user_data);
case CALLBACK_MSG_SCAN_FINISHED:
return CALLBACK_CONTINUE; return CALLBACK_CONTINUE;
}
} }
// At this point we have handled all the other cases of when this callback // At this point we have handled all the other cases of when this callback
...@@ -807,9 +819,12 @@ int yara_callback( ...@@ -807,9 +819,12 @@ int yara_callback(
// //
// In both cases, we need to create the data that will be either passed back // In both cases, we need to create the data that will be either passed back
// to the python callback or stored in the matches list. // to the python callback or stored in the matches list.
int result = CALLBACK_CONTINUE;
rule = (YR_RULE*) message_data; rule = (YR_RULE*) message_data;
gil_state = PyGILState_Ensure(); PyGILState_STATE gil_state = PyGILState_Ensure();
tag_list = PyList_New(0); tag_list = PyList_New(0);
string_list = PyList_New(0); string_list = PyList_New(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment