summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2024-05-20 14:48:35 +0200
committerJulien Voisin2024-05-26 20:19:27 +0000
commit1becad43298e74ba73bc66f9d44523e5d121c667 (patch)
tree009d0b1431d11ceb9d3ae1d33d1fd35638365ee9
parent92c611ad8abb146ed548301de8bc011c2b17bccd (diff)
Add vasprintf/asprintf2.3
The only hardening being done here is to set the char** parameter to thos functions to NULL in case of an error, to prevent it from being used should people forget to check return values. This is already done on some BSD, as well as in Rocky Linux.
-rw-r--r--README.md2
-rw-r--r--include/stdio.h42
-rw-r--r--tests/Makefile8
-rw-r--r--tests/test_asprintf.c20
-rw-r--r--tests/test_vasprintf.c36
5 files changed, 105 insertions, 3 deletions
diff --git a/README.md b/README.md
index 9b9a956..f47df41 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,7 @@ At this point, the program will safely crash.
59 59
60- `FD_CLR` 60- `FD_CLR`
61- `FD_SET` 61- `FD_SET`
62- `asprintf`
62- `bcopy` 63- `bcopy`
63- `bzero` 64- `bzero`
64- `calloc` 65- `calloc`
@@ -121,6 +122,7 @@ At this point, the program will safely crash.
121- `umask` 122- `umask`
122- `vfprintf` 123- `vfprintf`
123- `vprintf` 124- `vprintf`
125- `vasprintf`
124- `vsnprintf` 126- `vsnprintf`
125- `vsprintf` 127- `vsprintf`
126- `wcrtomb` 128- `wcrtomb`
diff --git a/include/stdio.h b/include/stdio.h
index c6817fa..abdef6c 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -220,6 +220,26 @@ _FORTIFY_FN(vprintf) int vprintf(const char *__f, __builtin_va_list __v)
220 return __orig_vprintf(__f, __v); 220 return __orig_vprintf(__f, __v);
221#endif 221#endif
222} 222}
223
224#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
225#undef vasprintf
226#if __has_builtin(__builtin_vasprintf)
227__diagnose_as_builtin(__builtin_vasprintf, 1, 2, 3)
228#endif
229_FORTIFY_FN(vasprintf) int vasprintf(char **restrict strp, const char *restrict fmt, __builtin_va_list ap)
230{
231#if __has_builtin(__builtin___vasprintf_chk) && USE_NATIVE_CHK
232 return __builtin___vasprintf_chk(_FORTIFY_SOURCE, strp, fmt, ap);
233#else
234 int ret = __orig_vasprintf(strp, fmt, ap);
235 if (ret < 0)
236 *strp = NULL;
237 return ret;
238#endif
239}
240
241
242#endif // defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
223#endif // __clang__ 243#endif // __clang__
224 244
225 245
@@ -312,6 +332,28 @@ _FORTIFY_FN(fprintf) int fprintf(FILE *__s, const char *__f, ...)
312#endif 332#endif
313} 333}
314 334
335#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
336#ifndef __clang__
337#undef asprintf
338__fh_access(read_only, 2)
339__fh_format(printf, 2, 0)
340#if __has_builtin(__builtin_asprintf)
341__diagnose_as_builtin(__builtin_asprintf, 2, 3)
342#endif
343_FORTIFY_FN(asprintf) int asprintf(char **restrict strp, const char *restrict fmt, ...)
344{
345#if __has_builtin(__builtin___asprintf_chk) && USE_NATIVE_CHK
346 return __builtin___asprintf_chk(_FORTIFY_SOURCE, strp, fmt, __builtin_va_arg_pack());
347#else
348 int ret = __orig_asprintf(strp, fmt, __builtin_va_arg_pack());
349 if (ret<0)
350 *strp = NULL;
351 return ret;
352#endif
353}
354#endif // __clang__
355#endif
356
315#pragma GCC diagnostic pop 357#pragma GCC diagnostic pop
316#endif /* __has_builtin(__builtin_va_arg_pack) */ 358#endif /* __has_builtin(__builtin_va_arg_pack) */
317 359
diff --git a/tests/Makefile b/tests/Makefile
index c18898e..32b17b0 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,4 +1,4 @@
1CFLAGS+=-I../include/ -D_FORTIFY_SOURCE=3 -static -O2 -DPEDANTIC_CHECKS 1CFLAGS+=-I../include/ -D_FORTIFY_SOURCE=3 -static -O2 -DPEDANTIC_CHECKS -Wno-format
2 2
3COMPTIME_TARGETS= \ 3COMPTIME_TARGETS= \
4 test_memcpy_overwrite_under \ 4 test_memcpy_overwrite_under \
@@ -12,6 +12,7 @@ RUNTIME_TARGETS= \
12 test_FD_SET_negative \ 12 test_FD_SET_negative \
13 test_FD_ISSET_SETSIZE \ 13 test_FD_ISSET_SETSIZE \
14 test_FD_ISSET_negative \ 14 test_FD_ISSET_negative \
15 test_asprintf \
15 test_bcopy_dynamic_read \ 16 test_bcopy_dynamic_read \
16 test_bcopy_dynamic_write \ 17 test_bcopy_dynamic_write \
17 test_bcopy_static_read \ 18 test_bcopy_static_read \
@@ -126,11 +127,12 @@ RUNTIME_TARGETS= \
126 test_ttyname_r_dynamic \ 127 test_ttyname_r_dynamic \
127 test_ttyname_r_static \ 128 test_ttyname_r_static \
128 test_umask \ 129 test_umask \
130 test_vasprintf \
131 test_vfprintf \
132 test_vprintf \
129 test_vsnprintf_dynamic \ 133 test_vsnprintf_dynamic \
130 test_vsnprintf_static \ 134 test_vsnprintf_static \
131 test_vsprintf \ 135 test_vsprintf \
132 test_vfprintf \
133 test_vprintf \
134 test_wcscat_static_write \ 136 test_wcscat_static_write \
135 test_wcscpy_static_write \ 137 test_wcscpy_static_write \
136 test_wcsncat_static_write \ 138 test_wcsncat_static_write \
diff --git a/tests/test_asprintf.c b/tests/test_asprintf.c
new file mode 100644
index 0000000..a02d110
--- /dev/null
+++ b/tests/test_asprintf.c
@@ -0,0 +1,20 @@
1#define _GNU_SOURCE
2#include "common.h"
3
4#include <assert.h>
5#include <stdio.h>
6#include <stdlib.h>
7
8int main(int argc, char** argv) {
9 char* buf;
10 asprintf(&buf, "total: %d+%d=%d", 1, 2, 3);
11 puts(buf);
12 free(buf);
13
14#ifndef __clang__
15 asprintf(&buf, "total: %", 1);
16 assert(buf == NULL);
17#endif
18
19 return 0;
20}
diff --git a/tests/test_vasprintf.c b/tests/test_vasprintf.c
new file mode 100644
index 0000000..2f71714
--- /dev/null
+++ b/tests/test_vasprintf.c
@@ -0,0 +1,36 @@
1#define _GNU_SOURCE
2#include "common.h"
3
4#include <assert.h>
5#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h>
8
9void test(const char *fmt, ...)
10{
11 char* buf;
12 va_list args;
13 va_start(args, fmt);
14 vasprintf(&buf, fmt, args);
15 va_end(args);
16 puts(buf);
17 free(buf);
18}
19
20void test2(const char *fmt, ...)
21{
22 char* buf;
23 va_list args;
24 va_start(args, fmt);
25 vasprintf(&buf, fmt, args);
26 va_end(args);
27 assert(buf == NULL);
28}
29
30int main(int argc, char** argv) {
31 test("Total: %d+%d=%d", 1, 2, 3);
32#ifndef __clang__
33 test2("Total: %", 1, 2, 3);
34#endif
35 return 0;
36}