]>
Commit | Line | Data |
---|---|---|
0d50f477 | 1 | /* Tests for fortified sprintf with unknown buffer bounds (bug 30039). |
dff8da6b | 2 | Copyright (C) 2023-2024 Free Software Foundation, Inc. |
0d50f477 FW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <printf.h> | |
20 | #include <stdarg.h> | |
21 | #include <stdio.h> | |
22 | #include <string.h> | |
23 | #include <support/check.h> | |
24 | ||
25 | /* This test is not built with _FORTIFY_SOURCE. Instead it calls the | |
26 | appropriate implementation directly. The fortify mode is specified | |
27 | in this variable. */ | |
28 | static int fortify_mode; | |
29 | ||
30 | /* This does not handle long-double redirects etc., but we test only | |
31 | format strings that stay within the confines of the base | |
32 | implementation. */ | |
33 | int __vsprintf_chk (char *s, int flag, size_t slen, const char *format, | |
34 | va_list ap); | |
35 | ||
36 | /* Invoke vsprintf or __vsprintf_chk according to fortify_mode. */ | |
37 | static int | |
38 | my_vsprintf (char *buf, const char *format, va_list ap) | |
39 | { | |
40 | int result; | |
41 | if (fortify_mode == 0) | |
42 | result = vsprintf (buf, format, ap); | |
43 | else | |
44 | /* Call the fortified version with an unspecified length. */ | |
45 | result = __vsprintf_chk (buf, fortify_mode - 1, -1, format, ap); | |
46 | return result; | |
47 | } | |
48 | ||
49 | /* Run one test, with the specified expected output. */ | |
50 | static void __attribute ((format (printf, 2, 3))) | |
51 | do_check (const char *expected, const char *format, ...) | |
52 | { | |
53 | va_list ap; | |
54 | va_start (ap, format); | |
55 | ||
56 | char buf_expected[24]; | |
57 | memset (buf_expected, '@', sizeof (buf_expected)); | |
58 | TEST_VERIFY (strlen (expected) < sizeof (buf_expected)); | |
59 | strcpy (buf_expected, expected); | |
60 | ||
61 | char buf[sizeof (buf_expected)]; | |
62 | memset (buf, '@', sizeof (buf)); | |
63 | ||
64 | int ret = my_vsprintf (buf, format, ap); | |
65 | TEST_COMPARE_BLOB (buf_expected, sizeof (buf_expected), buf, sizeof (buf)); | |
66 | TEST_COMPARE (ret, strlen (expected)); | |
67 | ||
68 | va_end (ap); | |
69 | } | |
70 | ||
71 | /* Run the tests in all fortify modes. */ | |
72 | static void | |
73 | do_tests (void) | |
74 | { | |
75 | for (fortify_mode = 0; fortify_mode <= 3; ++fortify_mode) | |
76 | { | |
77 | do_check ("0", "%d", 0); | |
78 | do_check ("-2147483648", "%d", -2147483647 - 1); | |
79 | do_check ("-9223372036854775808", "%lld", -9223372036854775807LL - 1); | |
80 | do_check ("", "%s", ""); | |
81 | do_check (" ", "%22s", ""); | |
82 | do_check ("XXXXXXXXXXXXXXXXXXXXXX", "%s", "XXXXXXXXXXXXXXXXXXXXXX"); | |
83 | do_check ("1.125000", "%f", 1.125); | |
84 | do_check ("1.125", "%g", 1.125); | |
85 | do_check ("1.125", "%.8g", 1.125); | |
86 | } | |
87 | } | |
88 | ||
89 | /* printf callback that falls back to the glibc-supplied | |
90 | implementation. */ | |
91 | static int | |
92 | dummy_printf_function (FILE *__stream, | |
93 | const struct printf_info *__info, | |
94 | const void *const *__args) | |
95 | { | |
96 | return -2; /* Request fallback. */ | |
97 | } | |
98 | ||
99 | /* Likewise for the type information. */ | |
100 | static int | |
101 | dummy_arginfo_function (const struct printf_info *info, | |
102 | size_t n, int *argtypes, int *size) | |
103 | { | |
104 | return -1; /* Request fallback. */ | |
105 | } | |
106 | ||
107 | static int | |
108 | do_test (void) | |
109 | { | |
110 | do_tests (); | |
111 | ||
112 | /* Activate __printf_function_invoke mode. */ | |
113 | register_printf_specifier ('d', dummy_printf_function, | |
114 | dummy_arginfo_function); | |
115 | register_printf_specifier ('g', dummy_printf_function, | |
116 | dummy_arginfo_function); | |
117 | register_printf_specifier ('s', dummy_printf_function, | |
118 | dummy_arginfo_function); | |
119 | ||
120 | /* Rerun the tests with callback functions. */ | |
121 | do_tests (); | |
122 | ||
123 | return 0; | |
124 | } | |
125 | ||
126 | #include <support/test-driver.c> |