aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremersion <contact@emersion.fr>2018-05-13 16:16:16 +0100
committerGitHub <noreply@github.com>2018-05-13 16:16:16 +0100
commit4dfb0529f865e9af327ea0740ae97f3d3e4da6f1 (patch)
tree417eb755118e7dedae3badeeaa7d713f204994e2
parent61aa0937a75d23c0f2a00a8cea52c08bf69164dd (diff)
parent789a877b379cd35c350610be62b971ae00feb542 (diff)
Merge pull request #1935 from heghe/heghe/fix-pango-markup-crash
Fix crash when using pango markup font
-rw-r--r--common/pango.c73
-rw-r--r--include/pango.h11
-rw-r--r--sway/tree/view.c21
3 files changed, 99 insertions, 6 deletions
diff --git a/common/pango.c b/common/pango.c
index 658d2876..9437c60d 100644
--- a/common/pango.c
+++ b/common/pango.c
@@ -8,6 +8,68 @@
#include <string.h>
#include "log.h"
+int escape_markup_text(const char *src, char *dest, int dest_length) {
+ int length = 0;
+
+ while (src[0]) {
+ switch (src[0]) {
+ case '&':
+ length += 5;
+ if (dest && dest_length - length >= 0) {
+ dest += sprintf(dest, "%s", "&amp;");
+ } else {
+ dest_length = -1;
+ }
+ break;
+ case '<':
+ length += 4;
+ if (dest && dest_length - length >= 0) {
+ dest += sprintf(dest, "%s", "&lt;");
+ } else {
+ dest_length = -1;
+ }
+ break;
+ case '>':
+ length += 4;
+ if (dest && dest_length - length >= 0) {
+ dest += sprintf(dest, "%s", "&gt;");
+ } else {
+ dest_length = -1;
+ }
+ break;
+ case '\'':
+ length += 6;
+ if (dest && dest_length - length >= 0) {
+ dest += sprintf(dest, "%s", "&apos;");
+ } else {
+ dest_length = -1;
+ }
+ break;
+ case '"':
+ length += 6;
+ if (dest && dest_length - length >= 0) {
+ dest += sprintf(dest, "%s", "&quot;");
+ } else {
+ dest_length = -1;
+ }
+ break;
+ default:
+ length += 1;
+ if (dest && dest_length - length >= 0) {
+ *(dest++) = *src;
+ } else {
+ dest_length = -1;
+ }
+ }
+ src++;
+ }
+ // if we could not fit the escaped string in dest, return -1
+ if (dest && dest_length == -1) {
+ return -1;
+ }
+ return length;
+}
+
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
const char *text, int32_t scale, bool markup) {
PangoLayout *layout = pango_cairo_create_layout(cairo);
@@ -15,13 +77,14 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
if (markup) {
char *buf;
GError *error = NULL;
- if (!sway_assert(pango_parse_markup(
- text, -1, 0, &attrs, &buf, NULL, &error),
- "pango_parse_markup '%s' -> error %s", text,
- error ? error->message : NULL)) {
+ bool result = pango_parse_markup(text, -1, 0, &attrs, &buf,
+ NULL, &error);
+ if (result) {
+ wlr_log(L_ERROR, "pango_parse_markup '%s' -> error %s", text,
+ error->message);
return NULL;
}
- pango_layout_set_markup(layout, buf, -1);
+ pango_layout_set_markup(layout, text, -1);
free(buf);
} else {
attrs = pango_attr_list_new();
diff --git a/include/pango.h b/include/pango.h
index f6325f28..d8263f9e 100644
--- a/include/pango.h
+++ b/include/pango.h
@@ -6,6 +6,17 @@
#include <cairo/cairo.h>
#include <pango/pangocairo.h>
+/* Utility function which escape characters a & < > ' ".
+ *
+ * If the dest parameter is NULL, then the function returns the length of
+ * of the escaped src string. The dest_length doesn't matter.
+ *
+ * If the dest parameter is not NULL then the fuction escapes the src string
+ * an puts the escaped string in dest and returns the lenght of the escaped string.
+ * The dest_length parameter is the size of dest array. If the size of dest is not
+ * enough, then the function returns -1.
+ */
+int escape_markup_text(const char *src, char *dest, int dest_length);
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
const char *text, int32_t scale, bool markup);
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
diff --git a/sway/tree/view.c b/sway/tree/view.c
index e2cb8a7a..9bdc5198 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -14,6 +14,8 @@
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
+#include "sway/config.h"
+#include "pango.h"
void view_init(struct sway_view *view, enum sway_view_type type,
const struct sway_view_impl *impl) {
@@ -612,6 +614,19 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
return len;
}
+static char *escape_title(char *buffer) {
+ int length = escape_markup_text(buffer, NULL, 0);
+ char *escaped_title = calloc(length + 1, sizeof(char));
+ int result = escape_markup_text(buffer, escaped_title, length);
+ if (result != length) {
+ wlr_log(L_ERROR, "Could not escape title: %s", buffer);
+ free(escaped_title);
+ return buffer;
+ }
+ free(buffer);
+ return escaped_title;
+}
+
void view_update_title(struct sway_view *view, bool force) {
if (!view->swayc) {
return;
@@ -631,11 +646,15 @@ void view_update_title(struct sway_view *view, bool force) {
free(view->swayc->formatted_title);
if (title) {
size_t len = parse_title_format(view, NULL);
- char *buffer = calloc(len + 1, 1);
+ char *buffer = calloc(len + 1, sizeof(char));
if (!sway_assert(buffer, "Unable to allocate title string")) {
return;
}
parse_title_format(view, buffer);
+ // now we have the title, but needs to be escaped when using pango markup
+ if (config->pango_markup) {
+ buffer = escape_title(buffer);
+ }
view->swayc->name = strdup(title);
view->swayc->formatted_title = buffer;