The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
strerror.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /** Support functions to allow libraries to provide errors to their callers
19  *
20  * @file src/lib/util/strerror.h
21  *
22  * @copyright 2017-2020 The FreeRADIUS server project
23  * @copyright 2017-2020 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  */
25 RCSIDH(strerror_h, "$Id: afd4f63b86929d168e75a856ce630790ddc8d2a5 $")
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <freeradius-devel/build.h>
32 #include <freeradius-devel/missing.h>
33 #include <string.h>
34 #include <stdarg.h>
35 
36 /** @name Add an error string to the thread local error stack
37  *
38  * @note printf functions should not be used in decoder libraries as an
39  * attacker may be able to exploit them to consume excessive amounts
40  * of CPU time. Use fr_strerror_const_* functions instead.
41  *
42  * @{
43  */
44 #define fr_strerror_vprintf(_fmt, _ap) _fr_strerror_vprintf(__FILE__, __LINE__, _fmt, _ap)
45 /** @hidecallergraph */
46 void _fr_strerror_vprintf(char const *file, int line, char const *fmt, va_list ap);
47 
48 #define fr_strerror_vprintf_push(_fmt, _ap) _fr_strerror_vprintf_push(__FILE__, __LINE, _fmt, _ap)
49 /** @hidecallergraph */
50 void _fr_strerror_vprintf_push(char const *file, int line, char const *fmt, va_list ap);
51 
52 #define fr_strerror_vprintf_push_head(_fmt, _ap) _fr_strerror_vprintf_push_head(__FILE__, __LINE__, _fmt, _ap)
53 /** @hidecallergraph */
54 void _fr_strerror_vprintf_push_head(char const *file, int line, char const *fmt, va_list ap);
55 
56 /** Log to thread local error buffer
57  *
58  * @param[in] _fmt printf style format string.
59  * If NULL clears any existing messages.
60  * @param[in] ... Arguments for the format string.
61  *
62  * @hidecallergraph
63  */
64 #define fr_strerror_printf(_fmt, ...) \
65  _fr_strerror_printf(__FILE__, __LINE__, _fmt, ##__VA_ARGS__)
66 
67 static inline CC_HINT(nonnull) CC_HINT(format (printf, 3, 4))
68 void _fr_strerror_printf(char const *file, int line, char const *fmt, ...)
69 {
70  va_list ap;
71 
72  va_start(ap, fmt);
74  va_end(ap);
75 }
76 
77 /** Add a message to an existing stack of messages at the tail
78  *
79  * @param[in] _fmt printf style format string.
80  * @param[in] ... Arguments for the format string.
81  *
82  * @hidecallergraph
83  */
84 #define fr_strerror_printf_push(_fmt, ...) \
85  _fr_strerror_printf_push(__FILE__, __LINE__, _fmt, ##__VA_ARGS__)
86 
87 static inline CC_HINT(nonnull) CC_HINT(format (printf, 3, 4))
88 void _fr_strerror_printf_push(char const *file, int line, char const *fmt, ...)
89 {
90  va_list ap;
91 
92  va_start(ap, fmt);
94  va_end(ap);
95 }
96 
97 /** Add a message to an existing stack of messages at the head
98  *
99  * @param[in] _fmt printf style format string.
100  * @param[in] ... Arguments for the format string.
101  *
102  * @hidecallergraph
103  */
104 #define fr_strerror_printf_push_head(_fmt, ...) \
105  _fr_strerror_printf_push_head(__FILE__, __LINE__, _fmt, ##__VA_ARGS__)
106 
107 static inline CC_HINT(nonnull) CC_HINT(format (printf, 3, 4))
108 void _fr_strerror_printf_push_head(char const *file, int line, char const *fmt, ...)
109 {
110  va_list ap;
111 
112  va_start(ap, fmt);
114  va_end(ap);
115 }
116 /** @} */
117 
118 /** @name Add an error string with marker to the thread local error stack
119  *
120  * @note printf functions should not be used in decoder libraries as an
121  * attacker may be able to exploit them to consume excessive amounts
122  * of CPU time. Use fr_strerror_const_* functions instead.
123  *
124  * @{
125  */
126 #define fr_strerror_marker_vprintf(_subject, _offset, _fmt, _ap) \
127  _fr_strerror_marker_vprintf(__FILE__, __LINE__, _subject, _offset, _fmt, _ap)
128 /** @hidecallergraph */
129 void _fr_strerror_marker_vprintf(char const *file, int line,
130  char const *subject, size_t offset, char const *fmt, va_list ap);
131 
132 #define fr_strerror_marker_vprintf_push(_subject, _offset, _fmt, _ap) \
133  _fr_strerror_marker_vprintf_push(__FILE__, __LINE__, _subject, _offset, _fmt, _ap)
134 /** @hidecallergraph */
135 void _fr_strerror_marker_vprintf_push(char const *file, int line,
136  char const *subject, size_t offset, char const *fmt, va_list ap);
137 
138 #define fr_strerror_marker_vprintf_push_head(_subject, _offset, _fmt, _ap) \
139  _fr_strerror_marker_vprintf_push_head(__FILE__, __LINE__, _subject, _offset, _fmt, _ap)
140 /** @hidecallergraph */
141 void _fr_strerror_marker_vprintf_push_head(char const *file, int line,
142  char const *subject, size_t offset, char const *fmt, va_list ap);
143 
144 /** Add an error marker to an existing stack of messages
145  *
146  * @param[in] _subject to mark up.
147  * @param[in] _offset Positive offset to show where the error
148  * should be positioned.
149  * @param[in] _fmt Error string.
150  * @param[in] ... Arguments for the error string.
151  *
152  * @hidecallergraph
153  */
154 #define fr_strerror_marker_printf(_subject, _offset, _fmt, ...) \
155  _fr_strerror_marker_printf(__FILE__, __LINE__, _subject, _offset, _fmt, ##__VA_ARGS__)
156 
157 static inline CC_HINT(nonnull) CC_HINT(format (printf, 5, 6))
158 void _fr_strerror_marker_printf(char const *file, int line,
159  char const *subject, size_t offset, char const *fmt, ...)
160 {
161  va_list ap;
162 
163  va_start(ap, fmt);
164  _fr_strerror_marker_vprintf(file, line, subject, offset, fmt, ap);
165  va_end(ap);
166 }
167 
168 /** Add an error marker to an existing stack of messages at the tail
169  *
170  * @param[in] _subject to mark up.
171  * @param[in] _offset Positive offset to show where the error
172  * should be positioned.
173  * @param[in] _fmt Error string.
174  * @param[in] ... Arguments for the error string.
175  *
176  * @hidecallergraph
177  */
178 #define fr_strerror_marker_printf_push(_subject, _offset, _fmt, ...) \
179  _fr_strerror_marker_printf_push(__FILE__, __LINE__, _subject, _offset, _fmt, ##__VA_ARGS__)
180 
181 static inline CC_HINT(nonnull) CC_HINT(format (printf, 5, 6))
183  char const *subject, size_t offset, char const *fmt, ...)
184 {
185  va_list ap;
186 
187  va_start(ap, fmt);
188  _fr_strerror_marker_vprintf_push(file, line, subject, offset, fmt, ap);
189  va_end(ap);
190 }
191 
192 /** Add an error marker to an existing stack of messages at the head
193  *
194  * @param[in] _subject to mark up.
195  * @param[in] _offset Positive offset to show where the error
196  * should be positioned.
197  * @param[in] _fmt Error string.
198  * @param[in] ... Arguments for the error string.
199  *
200  * @hidecallergraph
201  */
202 #define fr_strerror_marker_printf_push_head(_subject, _offset, _fmt, ...) \
203  _fr_strerror_marker_printf_push_head(__FILE__, __LINE__, _subject, _offset, _fmt, ##__VA_ARGS__)
204 
205 static inline CC_HINT(nonnull) CC_HINT(format (printf, 5, 6))
207  char const *subject, size_t offset, char const *fmt, ...)
208 {
209  va_list ap;
210 
211  va_start(ap, fmt);
212  _fr_strerror_marker_vprintf_push_head(file, line, subject, offset, fmt, ap);
213  va_end(ap);
214 }
215 /** @} */
216 
217 /** @name Add a const error string to the thread local error stack
218  *
219  * @note This ~30x the speed of the printf variants, and should be used wherever possible
220  *
221  * @{
222  */
223 #define fr_strerror_const(_msg) _fr_strerror_const(__FILE__, __LINE__, _msg)
224 /** @hidecallergraph */
225 void _fr_strerror_const(char const *file, int line, char const *msg) CC_HINT(nonnull);
226 
227 #define fr_strerror_const_push(_msg) _fr_strerror_const_push(__FILE__, __LINE__, _msg)
228 /** @hidecallergraph */
229 void _fr_strerror_const_push(char const *file, int line, char const *msg) CC_HINT(nonnull);
230 
231 #define fr_strerror_const_push_head(_msg) _fr_strerror_const_push_head(__FILE__, __LINE__, _msg)
232 /** @hidecallergraph */
233 void _fr_strerror_const_push_head(char const *file, int line, char const *msg) CC_HINT(nonnull);
234 /** @} */
235 
236 /** @name Retrieve errors from the thread local error stack
237  *
238  * @{
239  */
240 /** @hidecallergraph */
241 char const *fr_strerror(void) CC_HINT(warn_unused_result);
242 
243 /** @hidecallergraph */
244 void fr_strerror_clear(void);
245 
246 /** @hidecallergraph */
247 char const *fr_strerror_marker(char const **subject, size_t *offset) CC_HINT(nonnull);
248 
249 /** @hidecallergraph */
250 char const *fr_strerror_peek(void);
251 
252 /** @hidecallergraph */
253 char const *fr_strerror_marker_peek(char const **subject, size_t *offset) CC_HINT(nonnull);
254 
255 /** @hidecallergraph */
256 char const *fr_strerror_pop(void);
257 
258 /** @hidecallergraph */
259 char const *fr_strerror_marker_pop(char const **subject, size_t *offset) CC_HINT(nonnull);
260 
261 /** @hidecallergraph */
262 void fr_perror(char const *, ...) CC_HINT(format (printf, 1, 2));
263 
264 /** @hidecallergraph */
265 char const *fr_perror_to_str(char const *line_sep, char const *fmt, ...) CC_HINT(format (printf, 2, 3));
266 /** @} */
267 
268 #ifdef __cplusplus
269 }
270 #endif
int const char * file
Definition: acutest.h:702
va_end(args)
log_entry msg
Definition: acutest.h:794
static int const char * fmt
Definition: acutest.h:573
int const char int line
Definition: acutest.h:702
va_start(args, fmt)
#define RCSIDH(h, id)
Definition: build.h:445
void _fr_strerror_marker_vprintf_push(char const *file, int line, char const *subject, size_t offset, char const *fmt, va_list ap)
Add an error marker to an existing stack of messages at the tail.
Definition: strerror.c:348
static void _fr_strerror_marker_printf(char const *file, int line, char const *subject, size_t offset, char const *fmt,...)
Definition: strerror.h:158
void _fr_strerror_const_push(char const *file, int line, char const *msg)
Add a message to an existing stack of messages at the tail.
Definition: strerror.c:508
static void _fr_strerror_printf_push_head(char const *file, int line, char const *fmt,...)
Definition: strerror.h:108
static void _fr_strerror_printf(char const *file, int line, char const *fmt,...)
Definition: strerror.h:68
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
static void _fr_strerror_printf_push(char const *file, int line, char const *fmt,...)
Definition: strerror.h:88
char const * fr_perror_to_str(char const *line_sep, char const *fmt,...))
Print the stack of string buffers to a thread local buffer.
Definition: strerror.c:779
char const * fr_strerror_marker(char const **subject, size_t *offset)
Get the last library error marker.
Definition: strerror.c:598
static void _fr_strerror_marker_printf_push(char const *file, int line, char const *subject, size_t offset, char const *fmt,...)
Definition: strerror.h:182
char const * fr_strerror_peek(void)
Get the last library error.
Definition: strerror.c:627
char const * fr_strerror_marker_pop(char const **subject, size_t *offset)
Pop the last library error with marker information.
Definition: strerror.c:708
static void _fr_strerror_marker_printf_push_head(char const *file, int line, char const *subject, size_t offset, char const *fmt,...)
Definition: strerror.h:206
void _fr_strerror_const_push_head(char const *file, int line, char const *msg)
Add a message to an existing stack of messages at the head.
Definition: strerror.c:531
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
void fr_perror(char const *,...))
Print the current error to stderr with a prefix.
Definition: strerror.c:733
char const * fr_strerror_pop(void)
Pop the last library error.
Definition: strerror.c:681
void _fr_strerror_vprintf_push(char const *file, int line, char const *fmt, va_list ap)
Add a message to an existing stack of messages at the tail.
Definition: strerror.c:263
void _fr_strerror_marker_vprintf(char const *file, int line, char const *subject, size_t offset, char const *fmt, va_list ap)
Add an error marker to an existing stack of messages.
Definition: strerror.c:320
void _fr_strerror_vprintf_push_head(char const *file, int line, char const *fmt, va_list ap)
Add a message to an existing stack of messages at the head.
Definition: strerror.c:290
void _fr_strerror_const(char const *file, int line, char const *msg)
Log to thread local error buffer.
Definition: strerror.c:450
void _fr_strerror_marker_vprintf_push_head(char const *file, int line, char const *subject, size_t offset, char const *fmt, va_list ap)
Add an error marker to an existing stack of messages at the head.
Definition: strerror.c:382
char const * fr_strerror_marker_peek(char const **subject, size_t *offset)
Get the last library error marker.
Definition: strerror.c:651
void _fr_strerror_vprintf(char const *file, int line, char const *fmt, va_list ap)
Log to thread local error buffer.
Definition: strerror.c:245
int nonnull(2, 5))
int format(printf, 5, 0))