summaryrefslogtreecommitdiffstats
path: root/src/util/safe-format-string.h
diff options
context:
space:
mode:
authorStef Walter <stefw@redhat.com>2014-01-07 14:44:11 +0100
committerJakub Hrozek <jhrozek@redhat.com>2014-01-12 15:24:26 +0100
commitb9d8c6172e48a2633ebe196b2e88bebdf9523c20 (patch)
tree3ea801f4dbba0a859cbe44f8c3e1affe5fb108ba /src/util/safe-format-string.h
parent4b8021779e4db2a212a8214c17e778e843ae2b3a (diff)
downloadsssd-b9d8c6172e48a2633ebe196b2e88bebdf9523c20.tar.gz
sssd-b9d8c6172e48a2633ebe196b2e88bebdf9523c20.tar.xz
sssd-b9d8c6172e48a2633ebe196b2e88bebdf9523c20.zip
util: A safe printf for user provided format strings
Since the default printf(3) implementation cannot safely be used on user (or admin) provided input, this is a safe implementation. This will be used in later patches by the full_name_format option The implementation came from realmd, but only has libc dependencies. The number of fields is pre-defined, and safe printf fails if an invalid field is accessed. Only string fields are supported, and only flags relevant to string fields are supported. Width and precision work as expected, but precision cannot read from a field. Tests are included, and ported to the check based testing that sssd uses.
Diffstat (limited to 'src/util/safe-format-string.h')
-rw-r--r--src/util/safe-format-string.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/util/safe-format-string.h b/src/util/safe-format-string.h
new file mode 100644
index 000000000..2f4796de7
--- /dev/null
+++ b/src/util/safe-format-string.h
@@ -0,0 +1,81 @@
+/*
+ * This file originated in the realmd project
+ *
+ * Copyright 2013 Red Hat Inc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#ifndef __SAFE_FORMAT_STRING_H__
+#define __SAFE_FORMAT_STRING_H__
+
+#include <stdlib.h>
+
+/*
+ * This is a neutered printf variant that can be used with user-provided
+ * format strings.
+ *
+ * Not only are the normal printf functions not safe to use on user-provided
+ * input (ie: can crash, be abused, etc), they're also very brittle with
+ * regards to positional arguments: one must consume them all or printf will
+ * just abort(). This is because arguments of different sizes are accepted
+ * in the varargs. So obviously the positional code cannot know the offset
+ * of the relevant varargs if some are not consumed (ie: tagged with a
+ * field type).
+ *
+ * Thus the only accepted field type here is 's'. It's all we need.
+ *
+ * In general new code should use a better syntax than printf format strings
+ * for configuration options. This code is here to facilitate robust processing
+ * of the full_name_format syntax we already have, which has been documented as
+ * "printf(3) compatible".
+ *
+ * Features:
+ * - Only string 's' fields are supported
+ * - All the varargs should be strings, followed by a NULL argument
+ * - Both positional '%$1s' and non-positional '%s' are supported
+ * - Field widths '%8s' work as expected
+ * - Precision '%.8s' works, but precision cannot be read from a field
+ * - Left alignment flag is supported '%-8s'.
+ * - The space flag '% 8s' has no effect (it's the default for string fields).
+ * - No more than six digits are supported for widths, precisions, etc.
+ * - Percent signs are to be escaped as usual '%%'
+ *
+ * Use of other flags or field types will cause the relevant printf call to
+ * return -1. Using too many arguments or incorrect positional arguments
+ * will also cause the call to fail.
+ *
+ * Functions return -1 on failure and set errno. Otherwise they return
+ * the full length of the string that would be formatted, with the same
+ * semantics as snprintf().
+ */
+
+#ifndef GNUC_NULL_TERMINATED
+#if __GNUC__ >= 4
+#define GNUC_NULL_TERMINATED __attribute__((__sentinel__))
+#else
+#define GNUC_NULL_TERMINATED
+#endif
+#endif
+
+int safe_format_string (char *str,
+ size_t len,
+ const char *format,
+ ...) GNUC_NULL_TERMINATED;
+
+int safe_format_string_cb (void (* callback) (void *data, const char *piece, size_t len),
+ void *data,
+ const char *format,
+ const char * const args[],
+ int num_args);
+
+#endif /* __SAFE_FORMAT_STRING_H__ */