Skip to content

Commit 10cfee0

Browse files
authored
fix: Use YR_SCANNER object for scanning (VirusTotal#190)
rules.Match currently has an innate race condition when using external variables. To avoid this, use a YR_SCANNER.
1 parent e58af70 commit 10cfee0

File tree

1 file changed

+31
-48
lines changed

1 file changed

+31
-48
lines changed

yara-python.c

Lines changed: 31 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ int process_compile_externals(
12321232

12331233
int process_match_externals(
12341234
PyObject* externals,
1235-
YR_RULES* rules)
1235+
YR_SCANNER* scanner)
12361236
{
12371237
PyObject* key;
12381238
PyObject* value;
@@ -1247,8 +1247,8 @@ int process_match_externals(
12471247

12481248
if (PyBool_Check(value))
12491249
{
1250-
result = yr_rules_define_boolean_variable(
1251-
rules,
1250+
result = yr_scanner_define_boolean_variable(
1251+
scanner,
12521252
identifier,
12531253
PyObject_IsTrue(value));
12541254
}
@@ -1258,15 +1258,15 @@ int process_match_externals(
12581258
else if (PyLong_Check(value) || PyInt_Check(value))
12591259
#endif
12601260
{
1261-
result = yr_rules_define_integer_variable(
1262-
rules,
1261+
result = yr_scanner_define_integer_variable(
1262+
scanner,
12631263
identifier,
12641264
PyLong_AsLongLong(value));
12651265
}
12661266
else if (PyFloat_Check(value))
12671267
{
1268-
result = yr_rules_define_float_variable(
1269-
rules,
1268+
result = yr_scanner_define_float_variable(
1269+
scanner,
12701270
identifier,
12711271
PyFloat_AsDouble(value));
12721272
}
@@ -1277,8 +1277,8 @@ int process_match_externals(
12771277
if (str == NULL)
12781278
return ERROR_INVALID_ARGUMENT;
12791279

1280-
result = yr_rules_define_string_variable(
1281-
rules, identifier, str);
1280+
result = yr_scanner_define_string_variable(
1281+
scanner, identifier, str);
12821282
}
12831283
else
12841284
{
@@ -1289,7 +1289,7 @@ int process_match_externals(
12891289
return ERROR_INVALID_ARGUMENT;
12901290
}
12911291

1292-
// yr_rules_define_xxx_variable returns ERROR_INVALID_ARGUMENT if the
1292+
// yr_scanner_define_xxx_variable returns ERROR_INVALID_ARGUMENT if the
12931293
// variable wasn't previously defined in the compilation phase. Ignore
12941294
// those errors because we don't want the "scan" method being aborted
12951295
// because of the "externals" dictionary having more keys than those used
@@ -1644,46 +1644,49 @@ static PyObject* Rules_match(
16441644
}
16451645
}
16461646

1647+
YR_SCANNER* scanner;
1648+
if (yr_scanner_create(object->rules, &scanner) != 0) {
1649+
return PyErr_Format(
1650+
PyExc_Exception,
1651+
"could not create scanner");
1652+
}
1653+
16471654
if (externals != NULL && externals != Py_None)
16481655
{
16491656
if (PyDict_Check(externals))
16501657
{
1651-
if (process_match_externals(externals, object->rules) != ERROR_SUCCESS)
1658+
if (process_match_externals(externals, scanner) != ERROR_SUCCESS)
16521659
{
1653-
// Restore original externals provided during compiling.
1654-
process_match_externals(object->externals, object->rules);
1655-
16561660
PyBuffer_Release(&data);
1661+
yr_scanner_destroy(scanner);
16571662
return NULL;
16581663
}
16591664
}
16601665
else
16611666
{
16621667
PyBuffer_Release(&data);
1668+
yr_scanner_destroy(scanner);
16631669
return PyErr_Format(
16641670
PyExc_TypeError,
16651671
"'externals' must be a dictionary");
16661672
}
16671673
}
16681674

1669-
if (fast != NULL)
1675+
if (fast != NULL && PyObject_IsTrue(fast) == 1)
16701676
{
1671-
fast_mode = (PyObject_IsTrue(fast) == 1);
1677+
yr_scanner_set_flags(scanner, SCAN_FLAGS_FAST_MODE);
16721678
}
16731679

1680+
yr_scanner_set_timeout(scanner, timeout);
1681+
yr_scanner_set_callback(scanner, yara_callback, &callback_data);
1682+
16741683
if (filepath != NULL)
16751684
{
16761685
callback_data.matches = PyList_New(0);
16771686

16781687
Py_BEGIN_ALLOW_THREADS
16791688

1680-
error = yr_rules_scan_file(
1681-
object->rules,
1682-
filepath,
1683-
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
1684-
yara_callback,
1685-
&callback_data,
1686-
timeout);
1689+
error = yr_scanner_scan_file(scanner, filepath);
16871690

16881691
Py_END_ALLOW_THREADS
16891692
}
@@ -1693,14 +1696,10 @@ static PyObject* Rules_match(
16931696

16941697
Py_BEGIN_ALLOW_THREADS
16951698

1696-
error = yr_rules_scan_mem(
1697-
object->rules,
1699+
error = yr_scanner_scan_mem(
1700+
scanner,
16981701
(unsigned char*) data.buf,
1699-
(size_t) data.len,
1700-
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
1701-
yara_callback,
1702-
&callback_data,
1703-
timeout);
1702+
(size_t) data.len);
17041703

17051704
Py_END_ALLOW_THREADS
17061705
}
@@ -1710,29 +1709,13 @@ static PyObject* Rules_match(
17101709

17111710
Py_BEGIN_ALLOW_THREADS
17121711

1713-
error = yr_rules_scan_proc(
1714-
object->rules,
1715-
pid,
1716-
fast_mode ? SCAN_FLAGS_FAST_MODE : 0,
1717-
yara_callback,
1718-
&callback_data,
1719-
timeout);
1712+
error = yr_scanner_scan_proc(scanner, pid);
17201713

17211714
Py_END_ALLOW_THREADS
17221715
}
17231716

17241717
PyBuffer_Release(&data);
1725-
1726-
// Restore original externals provided during compiling.
1727-
if (object->externals != NULL)
1728-
{
1729-
if (process_match_externals(
1730-
object->externals, object->rules) != ERROR_SUCCESS)
1731-
{
1732-
Py_DECREF(callback_data.matches);
1733-
return NULL;
1734-
}
1735-
}
1718+
yr_scanner_destroy(scanner);
17361719

17371720
if (error != ERROR_SUCCESS)
17381721
{

0 commit comments

Comments
 (0)