summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2013-12-31 13:41:20 -0800
committerSimon Feltman <sfeltman@src.gnome.org>2013-12-31 13:41:20 -0800
commit2ef59b89311529e34366d4d7aa8f8ae9a8ea6371 (patch)
tree051255be6885a1d48bf7c5387b8acf62a5b230ae
parentb81f9c9b4e62d8cf589576aba8d9abbac4c80953 (diff)
downloadpygobject-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.py31
-rw-r--r--demos/gtk-demo/demos/Css/css_multiplebgs.py31
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()