Simon Josefsson wrote:
> Bruno Haible via Gnulib discussion list <[email protected]> writes:
>
> > - The security of the translations is guaranteed through the workflow
> > (xgettext marks the string with '#, c-format', then 'msgfmt -c' verifies
> > the compatibility of the format string directives in the translation).
>
> Is that protection really complete? Consider a
>
> printf (_("foo"));
>
> expression, and a maliciously crafted translation. Could that crash?
For printf (string) to crash, string must be NULL — which cannot occur as
the result of gettext() — or string must contain at least one format
directive that consumes an argument — but 'msgfmt -c' prevents that.
> I suppose the protection then is that translation files ought to be as
> well protected as the binary itself
Yes, unless some environment variable is specified (LANGUAGE or NLSPATH).
But anyone who sets an environment variable can also change the PATH
and thus cause a different program to be invoked than the intended one.
> and that the code that loads the
> translations are carefully written to never load anything that is
> outside of a trusted installation.
This is glibc code since 1998 or so.
> But that seems a bit fragile.
Please come up with an attack that is not defended against.
> Some defense in depth against translation message confusion doesn't seem
> entirely unreasonable IMHO, and the cost of changing the calls into
>
> printf ("%s", _("foo"));
Many format strings take arguments:
printf (_("foo %d bar"), i);
and you can't change these easily. So, what do you gain by changing the
printf calls with 0 arguments after the format string? Nothing. You have
silenced a silly clang warning, and because this warning carries the
word "security" in it, you think you have made your program more secure.
But in fact, you have only been fooled into thinking that.
> How do gcc avoid warning for this? Is there a special exception for
> translation messages or gettext.h somehow?
gcc has built-in knowledge about the gettext, dgettext, dcgettext functions.
Bruno