Skip to content

Commit 70eea4c

Browse files
authored
Don't abort scan on non-UTF-8 module dictionary keys (#280)
convert_dictionary_to_python used PyDict_SetItemString, which decodes the key as strict UTF-8. YARA module dictionary keys are SIZED_STRING values holding arbitrary bytes (for instance pe.version_info keys read straight from the binary), so a non-UTF-8 key raised UnicodeDecodeError. That exception propagated out of the modules_callback as a SystemError and aborted the whole scan. Build the key explicitly with a tolerant decoder (PyUnicode_DecodeUTF8 with the 'replace' handler) and use the key length so embedded NULs are handled too. Keys stay str, so this is not a breaking change: valid keys are unchanged and invalid bytes become U+FFFD instead of aborting. Fixes #273 Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
1 parent fb240bc commit 70eea4c

1 file changed

Lines changed: 19 additions & 4 deletions

File tree

yara-python.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -818,10 +818,25 @@ PyObject* convert_dictionary_to_python(
818818

819819
if (py_object != NULL)
820820
{
821-
PyDict_SetItemString(
822-
py_dict,
823-
dictionary->items->objects[i].key->c_string,
824-
py_object);
821+
// Dictionary keys are SIZED_STRING values holding arbitrary bytes (for
822+
// example the pe.version_info keys come straight from the binary), so
823+
// they are not guaranteed to be valid UTF-8. PyDict_SetItemString would
824+
// decode strictly and raise UnicodeDecodeError on a non-UTF-8 key, which
825+
// aborts the whole scan (see issue #273). Build the key tolerantly and
826+
// use its length so embedded NULs are handled too.
827+
SIZED_STRING* key = dictionary->items->objects[i].key;
828+
829+
#if PY_MAJOR_VERSION >= 3
830+
PyObject* py_key = PyUnicode_DecodeUTF8(key->c_string, key->length, "replace");
831+
#else
832+
PyObject* py_key = PyString_FromStringAndSize(key->c_string, key->length);
833+
#endif
834+
835+
if (py_key != NULL)
836+
{
837+
PyDict_SetItem(py_dict, py_key, py_object);
838+
Py_DECREF(py_key);
839+
}
825840

826841
Py_DECREF(py_object);
827842
}

0 commit comments

Comments
 (0)