[pygobject/pygobject-3-30] overrides: Fix length parameter when passing non-ascii strings to Gtk.Builder.add_from_string/add_ob



commit fd9e17a958f631df795b4709ed3303286fd2054f
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Thu Oct 4 17:32:17 2018 +0200

    overrides: Fix length parameter when passing non-ascii strings to 
Gtk.Builder.add_from_string/add_objects_from_string
    
    It was passing the codepoint count instead of the length in bytes which lead to things
    reading past the provided memory and crashes.
    
    Also use the same code for Gtk.UIManager.add_ui_from_string()
    
    Fixes #255

 gi/overrides/Gtk.py         | 14 +++++++++++---
 tests/test_overrides_gtk.py | 24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 3 deletions(-)
---
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index 05da18aa..0a0714d7 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -412,7 +412,7 @@ if Gtk._version in ("2.0", "3.0"):
             if not isinstance(buffer, string_types):
                 raise TypeError('buffer must be a string')
 
-            length = len(buffer.encode('UTF-8'))
+            length = _get_utf8_length(buffer)
 
             return Gtk.UIManager.add_ui_from_string(self, buffer, length)
 
@@ -462,6 +462,14 @@ MenuItem = override(MenuItem)
 __all__.append('MenuItem')
 
 
+def _get_utf8_length(string):
+    if not isinstance(string, string_types):
+        raise TypeError('must be a string')
+    if not isinstance(string, bytes):
+        string = string.encode("utf-8")
+    return len(string)
+
+
 class Builder(Gtk.Builder):
     def connect_signals(self, obj_or_map):
         """Connect signals specified by this builder to a name, handler mapping.
@@ -481,7 +489,7 @@ class Builder(Gtk.Builder):
         if not isinstance(buffer, string_types):
             raise TypeError('buffer must be a string')
 
-        length = len(buffer)
+        length = _get_utf8_length(buffer)
 
         return Gtk.Builder.add_from_string(self, buffer, length)
 
@@ -489,7 +497,7 @@ class Builder(Gtk.Builder):
         if not isinstance(buffer, string_types):
             raise TypeError('buffer must be a string')
 
-        length = len(buffer)
+        length = _get_utf8_length(buffer)
 
         return Gtk.Builder.add_objects_from_string(self, buffer, length, object_ids)
 
diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py
index 1e365525..c515e513 100644
--- a/tests/test_overrides_gtk.py
+++ b/tests/test_overrides_gtk.py
@@ -822,6 +822,30 @@ class TestBuilder(unittest.TestCase):
                             []),
         }
 
+    def test_add_from_string(self):
+        builder = Gtk.Builder()
+        builder.add_from_string(u"")
+        builder.add_from_string("")
+
+        def get_example(string):
+            return u"""\
+<interface>
+  <menu id="appmenu">
+    <section>
+      <item>
+        <attribute name="label">%s</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>""" % string
+
+        builder.add_from_string(get_example(u"ä" * 1000))
+
+        builder = Gtk.Builder()
+        builder.add_objects_from_string(u"", [''])
+        builder.add_objects_from_string("", [''])
+        builder.add_objects_from_string(get_example(u"ä" * 1000), [''])
+
     def test_extract_handler_and_args_object(self):
         class Obj():
             pass


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]