diff options
author | Simon Feltman <sfeltman@src.gnome.org> | 2013-12-31 13:41:20 -0800 |
---|---|---|
committer | Simon Feltman <sfeltman@src.gnome.org> | 2013-12-31 13:41:20 -0800 |
commit | 2ef59b89311529e34366d4d7aa8f8ae9a8ea6371 (patch) | |
tree | 051255be6885a1d48bf7c5387b8acf62a5b230ae | |
parent | b81f9c9b4e62d8cf589576aba8d9abbac4c80953 (diff) | |
download | pygobject-2ef59b89311529e34366d4d7aa8f8ae9a8ea6371.tar.gz |
gtk-demo: Avoid crash in CSS demos
Avoid a potential crash in the CSS demos where the text editing buffer is
out of sync with the last good CSS parsing buffer. In the case of CSS
warnings, we get a parsing-error callback but no exception is raised.
This would cause the buffers to become out of sync and accessing position
information from the parsing-error section would crash the text editor due
to an out of range iterator being created.
-rw-r--r-- | demos/gtk-demo/demos/Css/css_basics.py | 31 | ||||
-rw-r--r-- | demos/gtk-demo/demos/Css/css_multiplebgs.py | 31 |
2 files changed, 46 insertions, 16 deletions
diff --git a/demos/gtk-demo/demos/Css/css_basics.py b/demos/gtk-demo/demos/Css/css_basics.py index bd3f873b..18c3d12a 100644 --- a/demos/gtk-demo/demos/Css/css_basics.py +++ b/demos/gtk-demo/demos/Css/css_basics.py @@ -32,7 +32,13 @@ from gi.repository import Gtk, Gdk, Pango, Gio, GLib class CSSBasicsApp: def __init__(self, demoapp): self.demoapp = demoapp + #: Store the last successful parsing of the css so we can revert + #: this in case of an error. self.last_good_text = '' + #: Set when we receive a parsing-error callback. This is needed + #: to handle logic after a parsing-error callback which does not raise + #: an exception with provider.load_from_data() + self.last_error_code = 0 self.window = Gtk.Window() self.window.set_title('CSS Basics') @@ -86,12 +92,14 @@ class CSSBasicsApp: end = buffer.get_iter_at_line_index(section.get_end_line(), section.get_end_position()) - if error: - tag_name = "error" - self.infolabel.set_text(error.message) - self.infobar.show_all() - else: + if error.code == Gtk.CssProviderError.DEPRECATED: tag_name = "warning" + else: + tag_name = "error" + self.last_error_code = error.code + + self.infolabel.set_text(error.message) + self.infobar.show_all() buffer.apply_tag_by_name(tag_name, start, end) @@ -106,10 +114,17 @@ class CSSBasicsApp: try: provider.load_from_data(text) except GLib.GError as e: - if e.domain == 'gtk-css-provider-error-quark': - provider.load_from_data(self.last_good_text) - else: + if e.domain != 'gtk-css-provider-error-quark': raise e + + # If the parsing-error callback is ever run (even in the case of warnings) + # load the last good css text that ran without any warnings. Otherwise + # we may have a discrepancy in "last_good_text" vs the current buffer + # causing section.get_start_position() to give back an invalid position + # for the editor buffer. + if self.last_error_code: + provider.load_from_data(self.last_good_text) + self.last_error_code = 0 else: self.last_good_text = text self.infobar.hide() diff --git a/demos/gtk-demo/demos/Css/css_multiplebgs.py b/demos/gtk-demo/demos/Css/css_multiplebgs.py index 803c8532..9e1b0115 100644 --- a/demos/gtk-demo/demos/Css/css_multiplebgs.py +++ b/demos/gtk-demo/demos/Css/css_multiplebgs.py @@ -31,7 +31,13 @@ from gi.repository import Gtk, Gdk, Pango, Gio, GLib class CSSMultiplebgsApp: def __init__(self, demoapp): self.demoapp = demoapp + #: Store the last successful parsing of the css so we can revert + #: this in case of an error. self.last_good_text = '' + #: Set when we receive a parsing-error callback. This is needed + #: to handle logic after a parsing-error callback which does not raise + #: an exception with provider.load_from_data() + self.last_error_code = 0 self.window = Gtk.Window() self.window.set_title('CSS Multiplebgs') @@ -124,12 +130,14 @@ class CSSMultiplebgsApp: end = buffer.get_iter_at_line_index(section.get_end_line(), section.get_end_position()) - if error: - tag_name = "error" - self.infolabel.set_text(error.message) - self.infobar.show_all() - else: + if error.code == Gtk.CssProviderError.DEPRECATED: tag_name = "warning" + else: + tag_name = "error" + self.last_error_code = error.code + + self.infolabel.set_text(error.message) + self.infobar.show_all() buffer.apply_tag_by_name(tag_name, start, end) @@ -144,10 +152,17 @@ class CSSMultiplebgsApp: try: provider.load_from_data(text) except GLib.GError as e: - if e.domain == 'gtk-css-provider-error-quark': - provider.load_from_data(self.last_good_text) - else: + if e.domain != 'gtk-css-provider-error-quark': raise e + + # If the parsing-error callback is ever run (even in the case of warnings) + # load the last good css text that ran without any warnings. Otherwise + # we may have a discrepancy in "last_good_text" vs the current buffer + # causing section.get_start_position() to give back an invalid position + # for the editor buffer. + if self.last_error_code: + provider.load_from_data(self.last_good_text) + self.last_error_code = 0 else: self.last_good_text = text self.infobar.hide() |