[glibmm/wip/dboles/ustring-sprintf: 1/4] ustring: Fix warning/errors if sprintf("fmt only")
- From: Daniel Boles <dboles src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm/wip/dboles/ustring-sprintf: 1/4] ustring: Fix warning/errors if sprintf("fmt only")
- Date: Fri, 21 Jun 2019 18:05:08 +0000 (UTC)
commit 99eb3b14751b01b03420736f60337eb6df3b2ccf
Author: Daniel Boles <dboles src gnome org>
Date: Fri Jun 21 18:16:25 2019 +0100
ustring: Fix warning/errors if sprintf("fmt only")
If no args to be substituted are given, there is nothing to do, so the
fmt string is returned as-is without substitution. This is an obvious
case of mismatched format/args that we can check. Not doing so causes
warnings/errors with common compiler options, as it is a security risk.
For instance, -Wformat-security causes GCC to complain thusly:
> format not a string literal and no format arguments
Not passing arguments but passing a variable string that might contain
placeholders and thus instruct the compiler to try grabbing random
unrelated things off the stacks is obviously not something we want to do
– nor do we want to do it any *other* time, but this is the one case we
can obviously catch ourselves, rather than hoping any compiler does.
The argument for not just static_assert()ing that sizeof...(args) >= 1
is that this might conceivably be used in generic code where doing the
former would be annoying, and it's easy enough to make that work anyway.
https://gitlab.gnome.org/GNOME/glibmm/issues/21#note_537551
glib/glibmm/ustring.h | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
---
diff --git a/glib/glibmm/ustring.h b/glib/glibmm/ustring.h
index 0c1fa015..4fe58aff 100644
--- a/glib/glibmm/ustring.h
+++ b/glib/glibmm/ustring.h
@@ -724,11 +724,13 @@ public:
*
* Note: You must pass the correct number/types/order of arguments to match
* the format string, as when calling <tt>printf()</tt> directly. glibmm does
- * not check this for you. Breaking this contract invokes undefined behavior.
+ * not check this for you. Breaking this contract invokes undefined behavior
+ * and is a security risk.
*
* The exception is that glibmm special-cases std::string and Glib::ustring,
* so you can pass them in positions corresponding to <tt>%s</tt> placeholders
* without having to call their .c_str() functions; glibmm does that for you.
+ * glibmm also overloads sprintf() with @p fmt but no @p args to avoid risks.
*
* Said restriction also makes sprintf() unsuitable for translatable strings,
* as translators cannot reorder the placeholders to suit their language. If
@@ -762,6 +764,20 @@ public:
template <class... Ts>
static inline ustring sprintf(const ustring& fmt, const Ts&... args);
+ /*! Overload of sprintf() for a format string only, which returns it unchanged.
+ *
+ * If no @p args to be substituted are given, there is nothing to do, so the
+ * @p fmt string is returned as-is without substitution. This is an obvious
+ * case of mismatched format/args that we can check. Not doing so causes
+ * warnings/errors with common compiler options, as it is a security risk.
+ *
+ * @param fmt The string
+ * @return The same string.
+ *
+ * @newin{2,62}
+ */
+ static inline ustring sprintf(const ustring& fmt);
+
//! @}
private:
@@ -1265,6 +1281,13 @@ inline // static
return ustr;
}
+inline // static
+ ustring
+ ustring::sprintf(const ustring& fmt)
+{
+ return fmt;
+}
+
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
/** @relates Glib::ustring */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]