From 10ef118e09435a6fa7815a40829126490d9a7d67 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 21 Sep 2018 21:27:36 +1000 Subject: [PATCH 1/2] Fix pango escaping and refactor escape_markup_text Fixes #2674. The cause of the issue was in get_pango_layout. When we call pango_parse_markup, `text` is the escaped string, and the unescaped string is then computed and written to `buf`. We were then passing the unescaped string to pango_layout_set_markup, but this function needs the escaped string. `buf` is not needed and has been removed. The other part of this PR refactors escape_markup_text to remove the dest_length argument and removes the -1 return value on error. It now assumes that you've allocated dest to the correct length. --- common/pango.c | 57 +++++++++++++++--------------------------------- include/pango.h | 14 +++++------- sway/tree/view.c | 9 ++------ 3 files changed, 24 insertions(+), 56 deletions(-) diff --git a/common/pango.c b/common/pango.c index ea71ac4a8..dd27991b0 100644 --- a/common/pango.c +++ b/common/pango.c @@ -7,66 +7,45 @@ #include #include #include "log.h" +#include "stringop.h" -int escape_markup_text(const char *src, char *dest, int dest_length) { - int length = 0; +size_t escape_markup_text(const char *src, char *dest) { + size_t length = 0; + if (dest) { + dest[0] = '\0'; + } while (src[0]) { switch (src[0]) { case '&': length += 5; - if (dest && dest_length - length >= 0) { - dest += sprintf(dest, "%s", "&"); - } else { - dest_length = -1; - } + lenient_strcat(dest, "&"); break; case '<': length += 4; - if (dest && dest_length - length >= 0) { - dest += sprintf(dest, "%s", "<"); - } else { - dest_length = -1; - } + lenient_strcat(dest, "<"); break; case '>': length += 4; - if (dest && dest_length - length >= 0) { - dest += sprintf(dest, "%s", ">"); - } else { - dest_length = -1; - } + lenient_strcat(dest, ">"); break; case '\'': length += 6; - if (dest && dest_length - length >= 0) { - dest += sprintf(dest, "%s", "'"); - } else { - dest_length = -1; - } + lenient_strcat(dest, "'"); break; case '"': length += 6; - if (dest && dest_length - length >= 0) { - dest += sprintf(dest, "%s", """); - } else { - dest_length = -1; - } + lenient_strcat(dest, """); break; default: - length += 1; - if (dest && dest_length - length >= 0) { - *(dest++) = *src; - } else { - dest_length = -1; + if (dest) { + dest[length] = *src; + dest[length + 1] = '\0'; } + length += 1; } src++; } - // if we could not fit the escaped string in dest, return -1 - if (dest && dest_length == -1) { - return -1; - } return length; } @@ -75,11 +54,9 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, PangoLayout *layout = pango_cairo_create_layout(cairo); PangoAttrList *attrs; if (markup) { - char *buf; GError *error = NULL; - if (pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, &error)) { - pango_layout_set_markup(layout, buf, -1); - free(buf); + if (pango_parse_markup(text, -1, 0, &attrs, NULL, NULL, &error)) { + pango_layout_set_markup(layout, text, -1); } else { wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, error->message); diff --git a/include/pango.h b/include/pango.h index 09a535a50..6ab83c167 100644 --- a/include/pango.h +++ b/include/pango.h @@ -6,17 +6,13 @@ #include #include -/* Utility function which escape characters a & < > ' ". +/** + * 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. + * The function returns the length of the escaped string, optionally writing the + * escaped string to dest if provided. */ -int escape_markup_text(const char *src, char *dest, int dest_length); +size_t escape_markup_text(const char *src, char *dest); PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, double 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 4398f5183..f61f5c847 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -785,14 +785,9 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { } static char *escape_title(char *buffer) { - int length = escape_markup_text(buffer, NULL, 0); + size_t length = escape_markup_text(buffer, NULL); char *escaped_title = calloc(length + 1, sizeof(char)); - int result = escape_markup_text(buffer, escaped_title, length); - if (result != length) { - wlr_log(WLR_ERROR, "Could not escape title: %s", buffer); - free(escaped_title); - return buffer; - } + escape_markup_text(buffer, escaped_title); free(buffer); return escaped_title; } From 2f3650282802a01075f772df0663f170fecca29c Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 22 Sep 2018 18:40:19 +1000 Subject: [PATCH 2/2] Use pango_layout_set_text instead of pango_layout_set_markup --- common/pango.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/pango.c b/common/pango.c index dd27991b0..5afd72d81 100644 --- a/common/pango.c +++ b/common/pango.c @@ -54,9 +54,11 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, PangoLayout *layout = pango_cairo_create_layout(cairo); PangoAttrList *attrs; if (markup) { + char *buf; GError *error = NULL; - if (pango_parse_markup(text, -1, 0, &attrs, NULL, NULL, &error)) { - pango_layout_set_markup(layout, text, -1); + if (pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, &error)) { + pango_layout_set_text(layout, buf, -1); + free(buf); } else { wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, error->message);