3

I'm getting the following warning from my application that uses gtk+:

(foo:11333): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()

the function that is emitting the warning is the following:

static void show_error(GtkWindow *parent, const gchar *fmt, ...)
{
  GtkWidget *dialog;
  va_list args;

  va_start(args,fmt);
  dialog = gtk_message_dialog_new(parent,
                  GTK_DIALOG_DESTROY_WITH_PARENT,
                  GTK_MESSAGE_ERROR,
                  GTK_BUTTONS_OK,
                  fmt,
                  args);

  (void)gtk_dialog_run(GTK_DIALOG(dialog));

  gtk_widget_destroy(dialog);
  va_end(args);
}

and I'm calling with ui_show_error(window, "error canno't read file %s", filename);

where filename is null-terminatted-string, that works fine to str*() and *printf() functions family.

How to fix this?

Jack
  • 16,276
  • 55
  • 159
  • 284
  • Are you sure that filename is strictly ASCII? Maybe is does contain something that violates UTF-8. As far as I know, printf() does not care about UTF-8, maybe that's why it does not complain – mvp Oct 29 '12 at 04:29
  • Yeah, see `const char *s = "foo"; show_error(NULL, "%s baa", s);` I get same warning message. – Jack Oct 29 '12 at 04:40
  • Maybe it happens before you call show_error() ? You should check all strings you used to create your GTK dialogs to be 100% sure – mvp Oct 29 '12 at 04:50
  • No. It happens at `show_error()` call. I wrote a separate file to debug, I using the same code that I've posted in comments, that is giving same warning. My default language isn't english and contains accents.. is there some relation? – Jack Oct 29 '12 at 04:58
  • Simple things as: `show_error(NULL, "one:%d", 1);` give me negative random values; something like this `one:-1079463944` as if I'm accessing random memory. – Jack Oct 29 '12 at 05:02
  • Ah! That must be a reason. Do you have UTF-8 locale? What does `locale` command show? Also, you should always call `setlocale(LC_CTYPE, "")` at the beginning of your program. – mvp Oct 29 '12 at 05:02
  • yeah, I have. the `setlocale()` didn't difference. Before I had tried to `setlocale(LC_ALL, ""); – Jack Oct 29 '12 at 05:08

3 Answers3

4

It's not possible to chain va_list arguments that way. See this faq entry. What's happening is gtk_message_dialog_new is interpreting the va_list argument (which has some compiler-defined format) as a pointer to a string, so you're getting garbage. Since there's no message dialog function which takes a va_list, your only choice is to build a string using vsprintf or one of the similar glib functions and pass it as one argument to gtk_message_dialog_new with a format like "%s".

To build the string in the face of an unknown format string, usually the technique is use one of the "n" variants, like vsnprintf with a largish buffer, and if truncation occurs, increasing the buffer size and doing it over. However, glib has g_vasprintf(), which allocates the buffer for you. It also has g_printf_string_upper_bound() which can be used to size a buffer based on the format string.

ergosys
  • 47,835
  • 5
  • 49
  • 70
  • A string that is not properly terminated, can also have garbage characters that trigger this warning. – phyatt Jun 14 '16 at 14:50
1

I was with exactly this issue in a Linux From Scratch (LFS) build. The problem was affect the java swing interface text inputs, gdk interface text input, sometimes silently ignoring input like the text field was disabled. The cause is the absence of any UTF8 locale. in my case:

$ locale -a
C
POSIX
pt_BR
pt_BR.iso88591

So, to solve I did define a new locale type utf8 like:

localedef -i pt_BR -f UTF-8 pt_BR.UTF-8

after this, all became useful and no more warnings. at least in my case.

ton
  • 3,827
  • 1
  • 42
  • 40
0

OP did not show the actual string and where is ui_show_error function? What Gtk+ version? By default gtk_message_dialog_new "use-markup" property is FALSE, so is there something missing from post?

You could do somthing like:

msg = g_vasprintf(fmt, args);

if (strstr(msg, "</"))
  msg_has_markup = TRUE;

dialog = g_object_new (GTK_TYPE_MESSAGE_DIALOG,
                       "message-type",         GTK_MESSAGE_ERROR,
                       "text",                 msg,
                       "use-markup",           msg_has_markup,
                       "buttons",              GTK_BUTTONS_OK,
                        NULL);
g_free (msg);

Noting that you would still get the same error message if the file name string is wrapped in "<>", i.e. </home/somebody would cause obnoxious pango message. Either do no use the "<>" or do not use pango.

Wiley
  • 506
  • 5
  • 4