Unverified Commit 10cfee08 by secDre4mer Committed by GitHub

fix: Use YR_SCANNER object for scanning (#190)

rules.Match currently has an innate race condition when using
external variables. To avoid this, use a YR_SCANNER.
parent e58af70e
...@@ -1232,7 +1232,7 @@ int process_compile_externals( ...@@ -1232,7 +1232,7 @@ int process_compile_externals(
int process_match_externals( int process_match_externals(
PyObject* externals, PyObject* externals,
YR_RULES* rules) YR_SCANNER* scanner)
{ {
PyObject* key; PyObject* key;
PyObject* value; PyObject* value;
...@@ -1247,8 +1247,8 @@ int process_match_externals( ...@@ -1247,8 +1247,8 @@ int process_match_externals(
if (PyBool_Check(value)) if (PyBool_Check(value))
{ {
result = yr_rules_define_boolean_variable( result = yr_scanner_define_boolean_variable(
rules, scanner,
identifier, identifier,
PyObject_IsTrue(value)); PyObject_IsTrue(value));
} }
...@@ -1258,15 +1258,15 @@ int process_match_externals( ...@@ -1258,15 +1258,15 @@ int process_match_externals(
else if (PyLong_Check(value) || PyInt_Check(value)) else if (PyLong_Check(value) || PyInt_Check(value))
#endif #endif
{ {
result = yr_rules_define_integer_variable( result = yr_scanner_define_integer_variable(
rules, scanner,
identifier, identifier,
PyLong_AsLongLong(value)); PyLong_AsLongLong(value));
} }
else if (PyFloat_Check(value)) else if (PyFloat_Check(value))
{ {
result = yr_rules_define_float_variable( result = yr_scanner_define_float_variable(
rules, scanner,
identifier, identifier,
PyFloat_AsDouble(value)); PyFloat_AsDouble(value));
} }
...@@ -1277,8 +1277,8 @@ int process_match_externals( ...@@ -1277,8 +1277,8 @@ int process_match_externals(
if (str == NULL) if (str == NULL)
return ERROR_INVALID_ARGUMENT; return ERROR_INVALID_ARGUMENT;
result = yr_rules_define_string_variable( result = yr_scanner_define_string_variable(
rules, identifier, str); scanner, identifier, str);
} }
else else
{ {
...@@ -1289,7 +1289,7 @@ int process_match_externals( ...@@ -1289,7 +1289,7 @@ int process_match_externals(
return ERROR_INVALID_ARGUMENT; return ERROR_INVALID_ARGUMENT;
} }
// yr_rules_define_xxx_variable returns ERROR_INVALID_ARGUMENT if the // yr_scanner_define_xxx_variable returns ERROR_INVALID_ARGUMENT if the
// variable wasn't previously defined in the compilation phase. Ignore // variable wasn't previously defined in the compilation phase. Ignore
// those errors because we don't want the "scan" method being aborted // those errors because we don't want the "scan" method being aborted
// because of the "externals" dictionary having more keys than those used // because of the "externals" dictionary having more keys than those used
...@@ -1644,46 +1644,49 @@ static PyObject* Rules_match( ...@@ -1644,46 +1644,49 @@ static PyObject* Rules_match(
} }
} }
YR_SCANNER* scanner;
if (yr_scanner_create(object->rules, &scanner) != 0) {
return PyErr_Format(
PyExc_Exception,
"could not create scanner");
}
if (externals != NULL && externals != Py_None) if (externals != NULL && externals != Py_None)
{ {
if (PyDict_Check(externals)) if (PyDict_Check(externals))
{ {
if (process_match_externals(externals, object->rules) != ERROR_SUCCESS) if (process_match_externals(externals, scanner) != ERROR_SUCCESS)
{ {
// Restore original externals provided during compiling.
process_match_externals(object->externals, object->rules);
PyBuffer_Release(&data); PyBuffer_Release(&data);
yr_scanner_destroy(scanner);
return NULL; return NULL;
} }
} }
else else
{ {
PyBuffer_Release(&data); PyBuffer_Release(&data);
yr_scanner_destroy(scanner);
return PyErr_Format( return PyErr_Format(
PyExc_TypeError, PyExc_TypeError,
"'externals' must be a dictionary"); "'externals' must be a dictionary");
} }
} }
if (fast != NULL) if (fast != NULL && PyObject_IsTrue(fast) == 1)
{ {
fast_mode = (PyObject_IsTrue(fast) == 1); yr_scanner_set_flags(scanner, SCAN_FLAGS_FAST_MODE);
} }
yr_scanner_set_timeout(scanner, timeout);
yr_scanner_set_callback(scanner, yara_callback, &callback_data);
if (filepath != NULL) if (filepath != NULL)
{ {
callback_data.matches = PyList_New(0); callback_data.matches = PyList_New(0);
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
error = yr_rules_scan_file( error = yr_scanner_scan_file(scanner, filepath);
object->rules,
filepath,
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
yara_callback,
&callback_data,
timeout);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
...@@ -1693,14 +1696,10 @@ static PyObject* Rules_match( ...@@ -1693,14 +1696,10 @@ static PyObject* Rules_match(
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
error = yr_rules_scan_mem( error = yr_scanner_scan_mem(
object->rules, scanner,
(unsigned char*) data.buf, (unsigned char*) data.buf,
(size_t) data.len, (size_t) data.len);
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
yara_callback,
&callback_data,
timeout);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
...@@ -1710,29 +1709,13 @@ static PyObject* Rules_match( ...@@ -1710,29 +1709,13 @@ static PyObject* Rules_match(
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
error = yr_rules_scan_proc( error = yr_scanner_scan_proc(scanner, pid);
object->rules,
pid,
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
yara_callback,
&callback_data,
timeout);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
PyBuffer_Release(&data); PyBuffer_Release(&data);
yr_scanner_destroy(scanner);
// Restore original externals provided during compiling.
if (object->externals != NULL)
{
if (process_match_externals(
object->externals, object->rules) != ERROR_SUCCESS)
{
Py_DECREF(callback_data.matches);
return NULL;
}
}
if (error != ERROR_SUCCESS) if (error != ERROR_SUCCESS)
{ {
......
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