Skip to content

Commit 291aee6

Browse files
committed
[PyROOT][9632] Fix iteration on std::vector<char>
As part of the implementation of std.vector.__iter__, the vector's data() method is called. In the case of a vector<char>, data() returns a char*, which is converted by cppyy to a Python string. The issue is that the conversion char*->str expects that the sequence of characters to convert is null-terminated, e.g. in Python3 the following function is used for the conversion: https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_FromString In the case of the data pointed by the char* returned by data(), there is no guarantee that the sequence of characters will be null-terminated, and this results in unpredictable and erroneous behaviour. The fix of this commit adds a pythonization for vector<char>::data() that temporarily adds a null character to the vector before calling the actual data(), so that the conversion is done correctly and the returned Python string contains the characters of the vector. This also fixes the vector<char> iteration, which relies on data().
1 parent e3d6a83 commit 291aee6

1 file changed

Lines changed: 17 additions & 1 deletion

File tree

  • bindings/pyroot/pythonizations/python/ROOT/_pythonization

bindings/pyroot/pythonizations/python/ROOT/_pythonization/_stl_vector.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Author: Stefan Wunsch CERN 08/2018
1+
# Author: Stefan Wunsch, Enric Tejedor CERN 08/2018
22

33
################################################################################
44
# Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. #
@@ -11,6 +11,17 @@
1111
from . import pythonization
1212
from ._rvec import add_array_interface_property
1313

14+
def _data_vec_char(self):
15+
# vector<char>::data() returns char*.
16+
# Cppyy attemps to convert char* into Python string, but if the
17+
# character sequence is not null-terminated the conversion fails.
18+
# This is likely to happen with the result of vector<char>::data().
19+
# For the conversion char* -> str to succeed when calling data(),
20+
# temporarily append a null character to the vector<char>.
21+
self.push_back('\0')
22+
d = self._original_data()
23+
self.pop_back()
24+
return d
1425

1526
@pythonization("vector<", ns="std", is_prefix=True)
1627
def pythonize_stl_vector(klass, name):
@@ -21,3 +32,8 @@ def pythonize_stl_vector(klass, name):
2132
# Add numpy array interface
2233
# NOTE: The pythonization is reused from ROOT::VecOps::RVec
2334
add_array_interface_property(klass, name)
35+
36+
# Inject custom vector<char>::data()
37+
if klass.value_type == 'char':
38+
klass._original_data = klass.data
39+
klass.data = _data_vec_char

0 commit comments

Comments
 (0)