aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-11-26 15:21:46 +0100
committerMattias Andrée <maandree@operamail.com>2015-11-26 15:21:46 +0100
commitf533c3b2a4f5b0c71c3c432ef5c5d133be8acb20 (patch)
treebaaa5c41d28fa2c2efa32be0caa0ea97d19bf14a
parentupdate todo (diff)
downloadslibc-f533c3b2a4f5b0c71c3c432ef5c5d133be8acb20.tar.gz
slibc-f533c3b2a4f5b0c71c3c432ef5c5d133be8acb20.tar.bz2
slibc-f533c3b2a4f5b0c71c3c432ef5c5d133be8acb20.tar.xz
sprintf considered safer
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--include/stdio.h30
-rw-r--r--src/stdio/printf.c30
2 files changed, 60 insertions, 0 deletions
diff --git a/include/stdio.h b/include/stdio.h
index c1b4a09..5c2f6ca 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -184,6 +184,36 @@ int sockprintf(int, int, const char* restrict, ...)
* This is identical to `snprintf` with
* `SIZE_MAX` as the second argument.
*
+ * `sprintf` is(!) safe to use. As long as you allocate
+ * the a large enough buffer. One way to do this is
+ * by measuring the length of the result first.
+ *
+ * ssize_t n;
+ * char* buffer = NULL;
+ * snprintf(NULL, 0, "%zu%zn", your_value, &n);
+ * buffer = malloc((size_t)n * sizeof(char));
+ * if (buffer == NULL) goto fail;
+ * sprintf(buffer, "%zu", your_value);
+ *
+ * If you don't care about portability, you can use
+ * `asprintf`, `asprintfa` or `bprintf`. However, you
+ * often do not need to measure the result with `snprintf`.
+ * A maximum possible length can often be determined
+ * at compile-time or only using `strlen'.
+ *
+ * char buffer[3 * sizeof(ssize_t) + 2]; // A very poor, but still safe,
+ * // approximation to log₁₀.
+ * spritnf(buffer, "%zi", your_signed_value);
+ *
+ * These techniques guarantees that all of the string is
+ * written, and is therefore preferable over replacing
+ * `sprintf` with `snprintf`. Because of this, slibc
+ * does not consider `sprintf` unsafe like some of the
+ * more hokey C standard library implementations. This
+ * is C damn it!
+ *
+ * “Almost anything can be unsafe if you don't use it properly.”
+ *
* @param buffer The output buffer.
* @param format The formatting-string.
* @param ... The formatting-arguments.
diff --git a/src/stdio/printf.c b/src/stdio/printf.c
index 4c5bae9..53be281 100644
--- a/src/stdio/printf.c
+++ b/src/stdio/printf.c
@@ -495,6 +495,36 @@ int sockprintf(int fd, int flags, const char* format restrict, ...)
* This is identical to `snprintf` with
* `SIZE_MAX` as the second argument.
*
+ * `sprintf` is(!) safe to use. As long as you allocate
+ * the a large enough buffer. One way to do this is
+ * by measuring the length of the result first.
+ *
+ * ssize_t n;
+ * char* buffer = NULL;
+ * snprintf(NULL, 0, "%zu%zn", your_value, &n);
+ * buffer = malloc((size_t)n * sizeof(char));
+ * if (buffer == NULL) goto fail;
+ * sprintf(buffer, "%zu", your_value);
+ *
+ * If you don't care about portability, you can use
+ * `asprintf`, `asprintfa` or `bprintf`. However, you
+ * often do not need to measure the result with `snprintf`.
+ * A maximum possible length can often be determined
+ * at compile-time or only using `strlen'.
+ *
+ * char buffer[3 * sizeof(ssize_t) + 2]; // A very poor, but still safe,
+ * // approximation to log₁₀.
+ * spritnf(buffer, "%zi", your_signed_value);
+ *
+ * These techniques guarantees that all of the string is
+ * written, and is therefore preferable over replacing
+ * `sprintf` with `snprintf`. Because of this, slibc
+ * does not consider `sprintf` unsafe like some of the
+ * more hokey C standard library implementations. This
+ * is C damn it!
+ *
+ * “Almost anything can be unsafe if you don't use it properly.”
+ *
* @param buffer The output buffer.
* @param format The formatting-string.
* @param ... The formatting-arguments.