/src/httrack/src/htssafe.h
Line | Count | Source |
1 | | /* ------------------------------------------------------------ */ |
2 | | /* |
3 | | HTTrack Website Copier, Offline Browser for Windows and Unix |
4 | | Copyright (C) 2014 Xavier Roche and other contributors |
5 | | |
6 | | SPDX-License-Identifier: GPL-3.0-or-later |
7 | | |
8 | | This program is free software: you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation, either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | | |
21 | | Ethical use: we kindly ask that you NOT use this software to harvest email |
22 | | addresses or to collect any other private information about people. Doing so |
23 | | would dishonor our work and waste the many hours we have spent on it. |
24 | | |
25 | | Please visit our Website: http://www.httrack.com |
26 | | */ |
27 | | |
28 | | /* ------------------------------------------------------------ */ |
29 | | /* File: htssafe.h safe strings operations, and asserts */ |
30 | | /* Author: Xavier Roche */ |
31 | | /* ------------------------------------------------------------ */ |
32 | | |
33 | | #ifndef HTSSAFE_DEFH |
34 | | #define HTSSAFE_DEFH |
35 | | |
36 | | #include <stdio.h> |
37 | | #include <stdlib.h> |
38 | | #include <string.h> |
39 | | |
40 | | #include "htsglobal.h" |
41 | | |
42 | | /** |
43 | | * Emergency logging. |
44 | | * Default is to use libhttrack one. |
45 | | */ |
46 | | #if (!defined(HTSSAFE_ABORT_FUNCTION) && defined(LIBHTTRACK_EXPORTS)) |
47 | | |
48 | | /** Assert error callback. **/ |
49 | | #ifndef HTS_DEF_FWSTRUCT_htsErrorCallback |
50 | | #define HTS_DEF_FWSTRUCT_htsErrorCallback |
51 | | typedef void (*htsErrorCallback)(const char *msg, const char *file, int line); |
52 | | #ifdef __cplusplus |
53 | | extern "C" { |
54 | | #endif |
55 | | HTSEXT_API htsErrorCallback hts_get_error_callback(void); |
56 | | #ifdef __cplusplus |
57 | | } |
58 | | #endif |
59 | | #endif |
60 | | |
61 | | #define HTSSAFE_ABORT_FUNCTION(A, B, C) \ |
62 | 0 | do { \ |
63 | 0 | htsErrorCallback callback = hts_get_error_callback(); \ |
64 | 0 | if (callback != NULL) { \ |
65 | 0 | callback(A, B, C); \ |
66 | 0 | } \ |
67 | 0 | } while (0) |
68 | | |
69 | | #endif |
70 | | |
71 | | /** |
72 | | * Log an abort condition, and calls abort(). |
73 | | */ |
74 | | #define abortLog(a) abortf_(a, __FILE__, __LINE__) |
75 | | |
76 | | /** |
77 | | * Fatal assertion check. |
78 | | */ |
79 | | #define assertf__(exp, sexp, file, line) \ |
80 | 7.48k | (void) ((exp) || (abortf_(sexp, file, line), 0)) |
81 | | |
82 | | /** |
83 | | * Fatal assertion check. |
84 | | */ |
85 | 6.01k | #define assertf_(exp, file, line) assertf__(exp, #exp, file, line) |
86 | | |
87 | | /** |
88 | | * Fatal assertion check. |
89 | | */ |
90 | 0 | #define assertf(exp) assertf_(exp, __FILE__, __LINE__) |
91 | | |
92 | 0 | static HTS_UNUSED void log_abort_(const char *msg, const char *file, int line) { |
93 | 0 | fprintf(stderr, "%s failed at %s:%d\n", msg, file, line); |
94 | 0 | fflush(stderr); |
95 | 0 | } Unexecuted instantiation: fuzz-url.c:log_abort_ Unexecuted instantiation: htslib.c:log_abort_ Unexecuted instantiation: htstools.c:log_abort_ Unexecuted instantiation: htsthread.c:log_abort_ Unexecuted instantiation: htsbauth.c:log_abort_ Unexecuted instantiation: htsmd5.c:log_abort_ Unexecuted instantiation: htscodec.c:log_abort_ Unexecuted instantiation: htswarc.c:log_abort_ Unexecuted instantiation: htszlib.c:log_abort_ Unexecuted instantiation: htsconcat.c:log_abort_ Unexecuted instantiation: htsmodules.c:log_abort_ Unexecuted instantiation: htscharset.c:log_abort_ Unexecuted instantiation: htsencoding.c:log_abort_ Unexecuted instantiation: htscore.c:log_abort_ Unexecuted instantiation: htsparse.c:log_abort_ Unexecuted instantiation: htsback.c:log_abort_ Unexecuted instantiation: htscache.c:log_abort_ Unexecuted instantiation: htsfilters.c:log_abort_ Unexecuted instantiation: htsftp.c:log_abort_ Unexecuted instantiation: htshash.c:log_abort_ Unexecuted instantiation: htsname.c:log_abort_ Unexecuted instantiation: htsrobots.c:log_abort_ Unexecuted instantiation: htswizard.c:log_abort_ Unexecuted instantiation: htsindex.c:log_abort_ Unexecuted instantiation: htsproxy.c:log_abort_ Unexecuted instantiation: htssniff.c:log_abort_ |
96 | | |
97 | 0 | static HTS_UNUSED void abortf_(const char *exp, const char *file, int line) { |
98 | 0 | #ifdef HTSSAFE_ABORT_FUNCTION |
99 | 0 | HTSSAFE_ABORT_FUNCTION(exp, file, line); |
100 | 0 | #endif |
101 | 0 | log_abort_(exp, file, line); |
102 | 0 | abort(); |
103 | 0 | } Unexecuted instantiation: fuzz-url.c:abortf_ Unexecuted instantiation: htslib.c:abortf_ Unexecuted instantiation: htstools.c:abortf_ Unexecuted instantiation: htsthread.c:abortf_ Unexecuted instantiation: htsbauth.c:abortf_ Unexecuted instantiation: htsmd5.c:abortf_ Unexecuted instantiation: htscodec.c:abortf_ Unexecuted instantiation: htswarc.c:abortf_ Unexecuted instantiation: htszlib.c:abortf_ Unexecuted instantiation: htsconcat.c:abortf_ Unexecuted instantiation: htsmodules.c:abortf_ Unexecuted instantiation: htscharset.c:abortf_ Unexecuted instantiation: htsencoding.c:abortf_ Unexecuted instantiation: htscore.c:abortf_ Unexecuted instantiation: htsparse.c:abortf_ Unexecuted instantiation: htsback.c:abortf_ Unexecuted instantiation: htscache.c:abortf_ Unexecuted instantiation: htsfilters.c:abortf_ Unexecuted instantiation: htsftp.c:abortf_ Unexecuted instantiation: htshash.c:abortf_ Unexecuted instantiation: htsname.c:abortf_ Unexecuted instantiation: htsrobots.c:abortf_ Unexecuted instantiation: htswizard.c:abortf_ Unexecuted instantiation: htsindex.c:abortf_ Unexecuted instantiation: htsproxy.c:abortf_ Unexecuted instantiation: htssniff.c:abortf_ |
104 | | |
105 | | /** |
106 | | * Check whether 'VAR' is of type char[]. |
107 | | */ |
108 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
109 | | |
110 | | /* Note: char[] and const char[] are compatible */ |
111 | | #define HTS_IS_CHAR_BUFFER(VAR) \ |
112 | 2.93k | (__builtin_types_compatible_p(typeof(VAR), char[])) |
113 | | #else |
114 | | /* Note: a bit lame as char[8] won't be seen. */ |
115 | | #define HTS_IS_CHAR_BUFFER(VAR) (sizeof(VAR) != sizeof(char *)) |
116 | | #endif |
117 | 1.46k | #define HTS_IS_NOT_CHAR_BUFFER(VAR) (!HTS_IS_CHAR_BUFFER(VAR)) |
118 | | |
119 | | /* Compile-time checks. */ |
120 | 0 | static HTS_UNUSED void htssafe_compile_time_check_(void) { |
121 | 0 | char array[32]; |
122 | 0 | char *pointer = array; |
123 | 0 | char check_array[HTS_IS_CHAR_BUFFER(array) ? 1 : -1]; |
124 | 0 | char check_pointer[HTS_IS_CHAR_BUFFER(pointer) ? -1 : 1]; |
125 | 0 | (void) pointer; |
126 | 0 | (void) check_array; |
127 | 0 | (void) check_pointer; |
128 | 0 | } Unexecuted instantiation: fuzz-url.c:htssafe_compile_time_check_ Unexecuted instantiation: htslib.c:htssafe_compile_time_check_ Unexecuted instantiation: htstools.c:htssafe_compile_time_check_ Unexecuted instantiation: htsthread.c:htssafe_compile_time_check_ Unexecuted instantiation: htsbauth.c:htssafe_compile_time_check_ Unexecuted instantiation: htsmd5.c:htssafe_compile_time_check_ Unexecuted instantiation: htscodec.c:htssafe_compile_time_check_ Unexecuted instantiation: htswarc.c:htssafe_compile_time_check_ Unexecuted instantiation: htszlib.c:htssafe_compile_time_check_ Unexecuted instantiation: htsconcat.c:htssafe_compile_time_check_ Unexecuted instantiation: htsmodules.c:htssafe_compile_time_check_ Unexecuted instantiation: htscharset.c:htssafe_compile_time_check_ Unexecuted instantiation: htsencoding.c:htssafe_compile_time_check_ Unexecuted instantiation: htscore.c:htssafe_compile_time_check_ Unexecuted instantiation: htsparse.c:htssafe_compile_time_check_ Unexecuted instantiation: htsback.c:htssafe_compile_time_check_ Unexecuted instantiation: htscache.c:htssafe_compile_time_check_ Unexecuted instantiation: htsfilters.c:htssafe_compile_time_check_ Unexecuted instantiation: htsftp.c:htssafe_compile_time_check_ Unexecuted instantiation: htshash.c:htssafe_compile_time_check_ Unexecuted instantiation: htsname.c:htssafe_compile_time_check_ Unexecuted instantiation: htsrobots.c:htssafe_compile_time_check_ Unexecuted instantiation: htswizard.c:htssafe_compile_time_check_ Unexecuted instantiation: htsindex.c:htssafe_compile_time_check_ Unexecuted instantiation: htsproxy.c:htssafe_compile_time_check_ Unexecuted instantiation: htssniff.c:htssafe_compile_time_check_ |
129 | | |
130 | | /* |
131 | | * Pointer-destination diagnostics for the buff() macros (GCC/Clang, C only). |
132 | | * |
133 | | * strcpybuff()/strcatbuff()/strncatbuff() bounds-check only when the |
134 | | * destination is a sized char[] array (HTS_IS_CHAR_BUFFER). For a bare char* |
135 | | * the capacity is unknown, so the macro silently falls back to plain |
136 | | * strcpy()/strcat()/strncat() while still looking like a checked call. |
137 | | * |
138 | | * These stubs route that pointer case through __builtin_choose_expr() so the |
139 | | * 'warning' attribute fires only at pointer-destination sites; array sites use |
140 | | * the bounded *_safe_ helpers and stay quiet. The warning names the |
141 | | * explicit-size replacement (strlcpybuff/strlcatbuff). Diagnostic only: no |
142 | | * runtime or ABI change, built only on GCC/Clang in C mode. Other compilers |
143 | | * (MSVC, ...) keep the previous behavior via the #else branches. |
144 | | */ |
145 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
146 | | |
147 | | #if defined(__has_attribute) |
148 | | |
149 | | #if __has_attribute(warning) |
150 | | |
151 | | #define HTS_BUFF_PTR_ATTR(msg) __attribute__((unused, noinline, warning(msg))) |
152 | | #endif |
153 | | #endif |
154 | | #ifndef HTS_BUFF_PTR_ATTR |
155 | | /* 'warning' attribute unavailable: keep noinline so the migration can still |
156 | | grep for these symbols, but no compile-time diagnostic is emitted. */ |
157 | | #define HTS_BUFF_PTR_ATTR(msg) __attribute__((unused, noinline)) |
158 | | #endif |
159 | | |
160 | | HTS_BUFF_PTR_ATTR("strcpybuff() destination is a pointer (capacity unknown): " |
161 | | "NOT bounds-checked; use strlcpybuff(dst, src, size)") |
162 | | |
163 | 0 | static char *strcpybuff_ptr_(char *dest, const char *src) { |
164 | 0 | return strcpy(dest, src); |
165 | 0 | } Unexecuted instantiation: fuzz-url.c:strcpybuff_ptr_ Unexecuted instantiation: htslib.c:strcpybuff_ptr_ Unexecuted instantiation: htstools.c:strcpybuff_ptr_ Unexecuted instantiation: htsthread.c:strcpybuff_ptr_ Unexecuted instantiation: htsbauth.c:strcpybuff_ptr_ Unexecuted instantiation: htsmd5.c:strcpybuff_ptr_ Unexecuted instantiation: htscodec.c:strcpybuff_ptr_ Unexecuted instantiation: htswarc.c:strcpybuff_ptr_ Unexecuted instantiation: htszlib.c:strcpybuff_ptr_ Unexecuted instantiation: htsconcat.c:strcpybuff_ptr_ Unexecuted instantiation: htsmodules.c:strcpybuff_ptr_ Unexecuted instantiation: htscharset.c:strcpybuff_ptr_ Unexecuted instantiation: htsencoding.c:strcpybuff_ptr_ Unexecuted instantiation: htscore.c:strcpybuff_ptr_ Unexecuted instantiation: htsparse.c:strcpybuff_ptr_ Unexecuted instantiation: htsback.c:strcpybuff_ptr_ Unexecuted instantiation: htscache.c:strcpybuff_ptr_ Unexecuted instantiation: htsfilters.c:strcpybuff_ptr_ Unexecuted instantiation: htsftp.c:strcpybuff_ptr_ Unexecuted instantiation: htshash.c:strcpybuff_ptr_ Unexecuted instantiation: htsname.c:strcpybuff_ptr_ Unexecuted instantiation: htsrobots.c:strcpybuff_ptr_ Unexecuted instantiation: htswizard.c:strcpybuff_ptr_ Unexecuted instantiation: htsindex.c:strcpybuff_ptr_ Unexecuted instantiation: htsproxy.c:strcpybuff_ptr_ Unexecuted instantiation: htssniff.c:strcpybuff_ptr_ |
166 | | |
167 | | HTS_BUFF_PTR_ATTR("strcatbuff() destination is a pointer (capacity unknown): " |
168 | | "NOT bounds-checked; use strlcatbuff(dst, src, size)") |
169 | | |
170 | 0 | static char *strcatbuff_ptr_(char *dest, const char *src) { |
171 | 0 | return strcat(dest, src); |
172 | 0 | } Unexecuted instantiation: fuzz-url.c:strcatbuff_ptr_ Unexecuted instantiation: htslib.c:strcatbuff_ptr_ Unexecuted instantiation: htstools.c:strcatbuff_ptr_ Unexecuted instantiation: htsthread.c:strcatbuff_ptr_ Unexecuted instantiation: htsbauth.c:strcatbuff_ptr_ Unexecuted instantiation: htsmd5.c:strcatbuff_ptr_ Unexecuted instantiation: htscodec.c:strcatbuff_ptr_ Unexecuted instantiation: htswarc.c:strcatbuff_ptr_ Unexecuted instantiation: htszlib.c:strcatbuff_ptr_ Unexecuted instantiation: htsconcat.c:strcatbuff_ptr_ Unexecuted instantiation: htsmodules.c:strcatbuff_ptr_ Unexecuted instantiation: htscharset.c:strcatbuff_ptr_ Unexecuted instantiation: htsencoding.c:strcatbuff_ptr_ Unexecuted instantiation: htscore.c:strcatbuff_ptr_ Unexecuted instantiation: htsparse.c:strcatbuff_ptr_ Unexecuted instantiation: htsback.c:strcatbuff_ptr_ Unexecuted instantiation: htscache.c:strcatbuff_ptr_ Unexecuted instantiation: htsfilters.c:strcatbuff_ptr_ Unexecuted instantiation: htsftp.c:strcatbuff_ptr_ Unexecuted instantiation: htshash.c:strcatbuff_ptr_ Unexecuted instantiation: htsname.c:strcatbuff_ptr_ Unexecuted instantiation: htsrobots.c:strcatbuff_ptr_ Unexecuted instantiation: htswizard.c:strcatbuff_ptr_ Unexecuted instantiation: htsindex.c:strcatbuff_ptr_ Unexecuted instantiation: htsproxy.c:strcatbuff_ptr_ Unexecuted instantiation: htssniff.c:strcatbuff_ptr_ |
173 | | |
174 | | HTS_BUFF_PTR_ATTR("strncatbuff() destination is a pointer (capacity unknown): " |
175 | | "NOT bounds-checked; use strlcatbuff(dst, src, size)") |
176 | | |
177 | 0 | static char *strncatbuff_ptr_(char *dest, const char *src, size_t n) { |
178 | 0 | return strncat(dest, src, n); |
179 | 0 | } Unexecuted instantiation: fuzz-url.c:strncatbuff_ptr_ Unexecuted instantiation: htslib.c:strncatbuff_ptr_ Unexecuted instantiation: htstools.c:strncatbuff_ptr_ Unexecuted instantiation: htsthread.c:strncatbuff_ptr_ Unexecuted instantiation: htsbauth.c:strncatbuff_ptr_ Unexecuted instantiation: htsmd5.c:strncatbuff_ptr_ Unexecuted instantiation: htscodec.c:strncatbuff_ptr_ Unexecuted instantiation: htswarc.c:strncatbuff_ptr_ Unexecuted instantiation: htszlib.c:strncatbuff_ptr_ Unexecuted instantiation: htsconcat.c:strncatbuff_ptr_ Unexecuted instantiation: htsmodules.c:strncatbuff_ptr_ Unexecuted instantiation: htscharset.c:strncatbuff_ptr_ Unexecuted instantiation: htsencoding.c:strncatbuff_ptr_ Unexecuted instantiation: htscore.c:strncatbuff_ptr_ Unexecuted instantiation: htsparse.c:strncatbuff_ptr_ Unexecuted instantiation: htsback.c:strncatbuff_ptr_ Unexecuted instantiation: htscache.c:strncatbuff_ptr_ Unexecuted instantiation: htsfilters.c:strncatbuff_ptr_ Unexecuted instantiation: htsftp.c:strncatbuff_ptr_ Unexecuted instantiation: htshash.c:strncatbuff_ptr_ Unexecuted instantiation: htsname.c:strncatbuff_ptr_ Unexecuted instantiation: htsrobots.c:strncatbuff_ptr_ Unexecuted instantiation: htswizard.c:strncatbuff_ptr_ Unexecuted instantiation: htsindex.c:strncatbuff_ptr_ Unexecuted instantiation: htsproxy.c:strncatbuff_ptr_ Unexecuted instantiation: htssniff.c:strncatbuff_ptr_ |
180 | | #endif |
181 | | |
182 | | /* |
183 | | * SIZE CONTRACT shared by strcpybuff/strcatbuff/strncatbuff (the "buff" |
184 | | * family): the destination bound is taken from sizeof(A), so A MUST be a real |
185 | | * char[] array in scope. The bound is the full array size in bytes, INCLUDING |
186 | | * the terminating NUL. On overflow the *_safe_ helpers do NOT truncate: they |
187 | | * abort() (assertf). On success the result is always NUL-terminated. |
188 | | * |
189 | | * CRITICAL CAVEAT: if A is a bare char* pointer (not an array), sizeof(A) is |
190 | | * the pointer size, not the buffer capacity. There is no way to recover the |
191 | | * real capacity, so these macros SILENTLY DEGRADE to the unbounded raw |
192 | | * strcpy()/strcat()/strncat() while still looking like a checked call. The |
193 | | * bound is lost. On GCC/Clang (C) the pointer case routes through the |
194 | | * *_ptr_ stubs above, which carry a 'warning' attribute to flag the site at |
195 | | * compile time; on other compilers it is silent. When the destination is a |
196 | | * pointer of known capacity, call the explicit-size strlcpybuff/strlcatbuff |
197 | | * (passing the capacity, NUL included) instead. |
198 | | */ |
199 | | |
200 | | /** |
201 | | * Append at most N characters from "B" to "A". |
202 | | * If "A" is a char[] variable whose size is not sizeof(char*), then the size |
203 | | * is assumed to be the capacity of this array. |
204 | | */ |
205 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
206 | | |
207 | | #define strncatbuff(A, B, N) \ |
208 | 427 | __builtin_choose_expr( \ |
209 | 427 | HTS_IS_CHAR_BUFFER(A), \ |
210 | 427 | strncat_safe_(A, sizeof(A), B, \ |
211 | 427 | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), N, \ |
212 | 427 | "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
213 | 427 | __LINE__), \ |
214 | 427 | strncatbuff_ptr_((A), (B), (N))) |
215 | | #else |
216 | | #define strncatbuff(A, B, N) \ |
217 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
218 | | ? strncat(A, B, N) \ |
219 | | : strncat_safe_(A, sizeof(A), B, \ |
220 | | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), N, \ |
221 | | "overflow while appending '" #B "' to '" #A "'", \ |
222 | | __FILE__, __LINE__)) |
223 | | #endif |
224 | | |
225 | | /** |
226 | | * Append characters of "B" to "A". |
227 | | * If "A" is a char[] variable whose size is not sizeof(char*), then the size |
228 | | * is assumed to be the capacity of this array. |
229 | | */ |
230 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
231 | | |
232 | | #define strcatbuff(A, B) \ |
233 | 890 | __builtin_choose_expr( \ |
234 | 890 | HTS_IS_CHAR_BUFFER(A), \ |
235 | 890 | strncat_safe_(A, sizeof(A), B, \ |
236 | 890 | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
237 | 890 | (size_t) -1, \ |
238 | 890 | "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
239 | 890 | __LINE__), \ |
240 | 890 | strcatbuff_ptr_((A), (B))) |
241 | | #else |
242 | | #define strcatbuff(A, B) \ |
243 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
244 | | ? strcat(A, B) \ |
245 | | : strncat_safe_(A, sizeof(A), B, \ |
246 | | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
247 | | (size_t) -1, \ |
248 | | "overflow while appending '" #B "' to '" #A "'", \ |
249 | | __FILE__, __LINE__)) |
250 | | #endif |
251 | | |
252 | | /** |
253 | | * Copy characters from "B" to "A". |
254 | | * If "A" is a char[] variable whose size is not sizeof(char*), then the size |
255 | | * is assumed to be the capacity of this array. |
256 | | */ |
257 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
258 | | |
259 | | #define strcpybuff(A, B) \ |
260 | 150 | __builtin_choose_expr( \ |
261 | 150 | HTS_IS_CHAR_BUFFER(A), \ |
262 | 150 | strcpy_safe_(A, sizeof(A), B, \ |
263 | 150 | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
264 | 150 | "overflow while copying '" #B "' to '" #A "'", __FILE__, \ |
265 | 150 | __LINE__), \ |
266 | 150 | strcpybuff_ptr_((A), (B))) |
267 | | #else |
268 | | #define strcpybuff(A, B) \ |
269 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
270 | | ? strcpy(A, B) \ |
271 | | : strcpy_safe_(A, sizeof(A), B, \ |
272 | | HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
273 | | "overflow while copying '" #B "' to '" #A "'", __FILE__, \ |
274 | | __LINE__)) |
275 | | #endif |
276 | | |
277 | | /* |
278 | | * Explicit-size variants (strlcatbuff/strlncatbuff/strlcpybuff): the |
279 | | * destination capacity is the caller-supplied S (total bytes, NUL included), |
280 | | * NOT derived from sizeof(A). Use these when A is a pointer or its capacity is |
281 | | * not its sizeof. Same abort-on-overflow, always-NUL-terminated contract; no |
282 | | * silent pointer degradation since the bound is passed in. |
283 | | */ |
284 | | |
285 | | /** |
286 | | * Append characters of "B" to "A", "A" having a maximum capacity of "S". |
287 | | */ |
288 | | #define strlcatbuff(A, B, S) \ |
289 | 0 | strncat_safe_(A, S, B, HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
290 | 0 | (size_t) -1, "overflow while appending '" #B "' to '" #A "'", \ |
291 | 0 | __FILE__, __LINE__) |
292 | | |
293 | | /** |
294 | | * Append at most "N" characters of "B" to "A", "A" having a maximum capacity |
295 | | * of "S". |
296 | | */ |
297 | | #define strlncatbuff(A, B, S, N) \ |
298 | 0 | strncat_safe_(A, S, B, HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
299 | 0 | N, "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
300 | 0 | __LINE__) |
301 | | |
302 | | /** |
303 | | * Copy characters of "B" to "A", "A" having a maximum capacity of "S". |
304 | | */ |
305 | | #define strlcpybuff(A, B, S) \ |
306 | 0 | strcpy_safe_(A, S, B, HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B), \ |
307 | 0 | "overflow while copying '" #B "' to '" #A "'", __FILE__, \ |
308 | 0 | __LINE__) |
309 | | |
310 | | /** strnlen replacement (autotools). **/ |
311 | | #if (!defined(_WIN32) && !defined(HAVE_STRNLEN)) |
312 | | |
313 | | static HTS_UNUSED size_t strnlen(const char *s, size_t maxlen) { |
314 | | size_t i; |
315 | | for (i = 0; i < maxlen && s[i] != '\0'; i++) |
316 | | ; |
317 | | return i; |
318 | | } |
319 | | #endif |
320 | | |
321 | | /* strlen of source, but bounded by sizeof_source (its capacity, NUL included). |
322 | | Aborts if source is NULL or has no NUL within that capacity. The sentinel |
323 | | sizeof_source == (size_t)-1 means "capacity unknown", and falls back to the |
324 | | unbounded strlen (used when the source is a pointer rather than an array). */ |
325 | | static HTS_INLINE HTS_UNUSED size_t strlen_safe_(const char *source, |
326 | | const size_t sizeof_source, |
327 | 2.93k | const char *file, int line) { |
328 | 2.93k | size_t size; |
329 | 2.93k | assertf_(source != NULL, file, line); |
330 | 2.93k | size = sizeof_source != (size_t) -1 ? strnlen(source, sizeof_source) |
331 | 2.93k | : strlen(source); |
332 | 2.93k | assertf_(size < sizeof_source, file, line); |
333 | 2.93k | return size; |
334 | 2.93k | } Unexecuted instantiation: fuzz-url.c:strlen_safe_ Line | Count | Source | 327 | 2.93k | const char *file, int line) { | 328 | 2.93k | size_t size; | 329 | 2.93k | assertf_(source != NULL, file, line); | 330 | 2.93k | size = sizeof_source != (size_t) -1 ? strnlen(source, sizeof_source) | 331 | 2.93k | : strlen(source); | 332 | 2.93k | assertf_(size < sizeof_source, file, line); | 333 | 2.93k | return size; | 334 | 2.93k | } |
Unexecuted instantiation: htstools.c:strlen_safe_ Unexecuted instantiation: htsthread.c:strlen_safe_ Unexecuted instantiation: htsbauth.c:strlen_safe_ Unexecuted instantiation: htsmd5.c:strlen_safe_ Unexecuted instantiation: htscodec.c:strlen_safe_ Unexecuted instantiation: htswarc.c:strlen_safe_ Unexecuted instantiation: htszlib.c:strlen_safe_ Unexecuted instantiation: htsconcat.c:strlen_safe_ Unexecuted instantiation: htsmodules.c:strlen_safe_ Unexecuted instantiation: htscharset.c:strlen_safe_ Unexecuted instantiation: htsencoding.c:strlen_safe_ Unexecuted instantiation: htscore.c:strlen_safe_ Unexecuted instantiation: htsparse.c:strlen_safe_ Unexecuted instantiation: htsback.c:strlen_safe_ Unexecuted instantiation: htscache.c:strlen_safe_ Unexecuted instantiation: htsfilters.c:strlen_safe_ Unexecuted instantiation: htsftp.c:strlen_safe_ Unexecuted instantiation: htshash.c:strlen_safe_ Unexecuted instantiation: htsname.c:strlen_safe_ Unexecuted instantiation: htsrobots.c:strlen_safe_ Unexecuted instantiation: htswizard.c:strlen_safe_ Unexecuted instantiation: htsindex.c:strlen_safe_ Unexecuted instantiation: htsproxy.c:strlen_safe_ Unexecuted instantiation: htssniff.c:strlen_safe_ |
335 | | |
336 | | /* Core bounded append. Appends min(strlen(source), n) bytes of source onto |
337 | | dest. sizeof_dest is dest's total capacity (NUL included); sizeof_source is |
338 | | source's capacity or (size_t)-1 if unknown. Aborts if the result (existing |
339 | | dest length + appended bytes + NUL) would not fit sizeof_dest: this NEVER |
340 | | truncates. Always NUL-terminates on success. */ |
341 | | static HTS_INLINE HTS_UNUSED char * |
342 | | strncat_safe_(char *const dest, const size_t sizeof_dest, |
343 | | const char *const source, const size_t sizeof_source, |
344 | 1.46k | const size_t n, const char *exp, const char *file, int line) { |
345 | 1.46k | const size_t source_len = strlen_safe_(source, sizeof_source, file, line); |
346 | 1.46k | const size_t dest_len = strlen_safe_(dest, sizeof_dest, file, line); |
347 | | /* note: "size_t is an unsigned integral type" ((size_t) -1 is positive) */ |
348 | 1.46k | const size_t source_copy = source_len <= n ? source_len : n; |
349 | 1.46k | const size_t dest_final_len = dest_len + source_copy; |
350 | 1.46k | assertf__(dest_final_len < sizeof_dest, exp, file, line); |
351 | 1.46k | memcpy(dest + dest_len, source, source_copy); |
352 | 1.46k | dest[dest_final_len] = '\0'; |
353 | 1.46k | return dest; |
354 | 1.46k | } Unexecuted instantiation: fuzz-url.c:strncat_safe_ Line | Count | Source | 344 | 1.46k | const size_t n, const char *exp, const char *file, int line) { | 345 | 1.46k | const size_t source_len = strlen_safe_(source, sizeof_source, file, line); | 346 | 1.46k | const size_t dest_len = strlen_safe_(dest, sizeof_dest, file, line); | 347 | | /* note: "size_t is an unsigned integral type" ((size_t) -1 is positive) */ | 348 | 1.46k | const size_t source_copy = source_len <= n ? source_len : n; | 349 | 1.46k | const size_t dest_final_len = dest_len + source_copy; | 350 | 1.46k | assertf__(dest_final_len < sizeof_dest, exp, file, line); | 351 | 1.46k | memcpy(dest + dest_len, source, source_copy); | 352 | 1.46k | dest[dest_final_len] = '\0'; | 353 | 1.46k | return dest; | 354 | 1.46k | } |
Unexecuted instantiation: htstools.c:strncat_safe_ Unexecuted instantiation: htsthread.c:strncat_safe_ Unexecuted instantiation: htsbauth.c:strncat_safe_ Unexecuted instantiation: htsmd5.c:strncat_safe_ Unexecuted instantiation: htscodec.c:strncat_safe_ Unexecuted instantiation: htswarc.c:strncat_safe_ Unexecuted instantiation: htszlib.c:strncat_safe_ Unexecuted instantiation: htsconcat.c:strncat_safe_ Unexecuted instantiation: htsmodules.c:strncat_safe_ Unexecuted instantiation: htscharset.c:strncat_safe_ Unexecuted instantiation: htsencoding.c:strncat_safe_ Unexecuted instantiation: htscore.c:strncat_safe_ Unexecuted instantiation: htsparse.c:strncat_safe_ Unexecuted instantiation: htsback.c:strncat_safe_ Unexecuted instantiation: htscache.c:strncat_safe_ Unexecuted instantiation: htsfilters.c:strncat_safe_ Unexecuted instantiation: htsftp.c:strncat_safe_ Unexecuted instantiation: htshash.c:strncat_safe_ Unexecuted instantiation: htsname.c:strncat_safe_ Unexecuted instantiation: htsrobots.c:strncat_safe_ Unexecuted instantiation: htswizard.c:strncat_safe_ Unexecuted instantiation: htsindex.c:strncat_safe_ Unexecuted instantiation: htsproxy.c:strncat_safe_ Unexecuted instantiation: htssniff.c:strncat_safe_ |
355 | | |
356 | | /* Core bounded copy: empties dest then appends all of source via |
357 | | strncat_safe_. sizeof_dest is dest's total capacity (NUL included). Aborts |
358 | | (no truncation) if source plus its NUL would not fit. */ |
359 | | static HTS_INLINE HTS_UNUSED char * |
360 | | strcpy_safe_(char *const dest, const size_t sizeof_dest, |
361 | | const char *const source, const size_t sizeof_source, |
362 | 150 | const char *exp, const char *file, int line) { |
363 | 150 | assertf_(sizeof_dest != 0, file, line); |
364 | 150 | dest[0] = '\0'; |
365 | 150 | return strncat_safe_(dest, sizeof_dest, source, sizeof_source, (size_t) -1, |
366 | 150 | exp, file, line); |
367 | 150 | } Unexecuted instantiation: fuzz-url.c:strcpy_safe_ Line | Count | Source | 362 | 150 | const char *exp, const char *file, int line) { | 363 | 150 | assertf_(sizeof_dest != 0, file, line); | 364 | 150 | dest[0] = '\0'; | 365 | 150 | return strncat_safe_(dest, sizeof_dest, source, sizeof_source, (size_t) -1, | 366 | 150 | exp, file, line); | 367 | 150 | } |
Unexecuted instantiation: htstools.c:strcpy_safe_ Unexecuted instantiation: htsthread.c:strcpy_safe_ Unexecuted instantiation: htsbauth.c:strcpy_safe_ Unexecuted instantiation: htsmd5.c:strcpy_safe_ Unexecuted instantiation: htscodec.c:strcpy_safe_ Unexecuted instantiation: htswarc.c:strcpy_safe_ Unexecuted instantiation: htszlib.c:strcpy_safe_ Unexecuted instantiation: htsconcat.c:strcpy_safe_ Unexecuted instantiation: htsmodules.c:strcpy_safe_ Unexecuted instantiation: htscharset.c:strcpy_safe_ Unexecuted instantiation: htsencoding.c:strcpy_safe_ Unexecuted instantiation: htscore.c:strcpy_safe_ Unexecuted instantiation: htsparse.c:strcpy_safe_ Unexecuted instantiation: htsback.c:strcpy_safe_ Unexecuted instantiation: htscache.c:strcpy_safe_ Unexecuted instantiation: htsfilters.c:strcpy_safe_ Unexecuted instantiation: htsftp.c:strcpy_safe_ Unexecuted instantiation: htshash.c:strcpy_safe_ Unexecuted instantiation: htsname.c:strcpy_safe_ Unexecuted instantiation: htsrobots.c:strcpy_safe_ Unexecuted instantiation: htswizard.c:strcpy_safe_ Unexecuted instantiation: htsindex.c:strcpy_safe_ Unexecuted instantiation: htsproxy.c:strcpy_safe_ Unexecuted instantiation: htssniff.c:strcpy_safe_ |
368 | | |
369 | | /** |
370 | | * htsbuff: a non-owning bounded string builder over a fixed buffer. |
371 | | * |
372 | | * Companion to the strcpybuff()/strcatbuff() macros for the common case of a |
373 | | * cursor walking a buffer of known capacity (building a name into a fixed |
374 | | * array, assembling a status line, etc.). It tracks the write position, bounds |
375 | | * every write against the real capacity, and aborts on overflow (same contract |
376 | | * as the *_safe_ helpers), so the error-prone manual "p += strlen(p)" dance |
377 | | * goes away. |
378 | | * |
379 | | * Build one from an in-scope array with htsbuff_array() (capacity via sizeof, |
380 | | * so pass an array, not a pointer), or from a pointer of known capacity with |
381 | | * htsbuff_ptr(). The buffer is kept NUL-terminated; htsbuff_str() returns it. |
382 | | */ |
383 | | typedef struct { |
384 | | char *buf; /* backing buffer (kept NUL-terminated) */ |
385 | | size_t cap; /* total capacity of buf, including the NUL */ |
386 | | size_t len; /* current length, excluding the NUL */ |
387 | | } htsbuff; |
388 | | |
389 | 0 | static HTS_INLINE HTS_UNUSED htsbuff htsbuff_ptr_(char *buf, size_t cap) { |
390 | 0 | htsbuff b; |
391 | 0 | b.buf = buf; |
392 | 0 | b.cap = cap; |
393 | 0 | b.len = 0; |
394 | 0 | assertf(cap != 0); |
395 | 0 | buf[0] = '\0'; |
396 | 0 | return b; |
397 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_ptr_ Unexecuted instantiation: htslib.c:htsbuff_ptr_ Unexecuted instantiation: htstools.c:htsbuff_ptr_ Unexecuted instantiation: htsthread.c:htsbuff_ptr_ Unexecuted instantiation: htsbauth.c:htsbuff_ptr_ Unexecuted instantiation: htsmd5.c:htsbuff_ptr_ Unexecuted instantiation: htscodec.c:htsbuff_ptr_ Unexecuted instantiation: htswarc.c:htsbuff_ptr_ Unexecuted instantiation: htszlib.c:htsbuff_ptr_ Unexecuted instantiation: htsconcat.c:htsbuff_ptr_ Unexecuted instantiation: htsmodules.c:htsbuff_ptr_ Unexecuted instantiation: htscharset.c:htsbuff_ptr_ Unexecuted instantiation: htsencoding.c:htsbuff_ptr_ Unexecuted instantiation: htscore.c:htsbuff_ptr_ Unexecuted instantiation: htsparse.c:htsbuff_ptr_ Unexecuted instantiation: htsback.c:htsbuff_ptr_ Unexecuted instantiation: htscache.c:htsbuff_ptr_ Unexecuted instantiation: htsfilters.c:htsbuff_ptr_ Unexecuted instantiation: htsftp.c:htsbuff_ptr_ Unexecuted instantiation: htshash.c:htsbuff_ptr_ Unexecuted instantiation: htsname.c:htsbuff_ptr_ Unexecuted instantiation: htsrobots.c:htsbuff_ptr_ Unexecuted instantiation: htswizard.c:htsbuff_ptr_ Unexecuted instantiation: htsindex.c:htsbuff_ptr_ Unexecuted instantiation: htsproxy.c:htsbuff_ptr_ Unexecuted instantiation: htssniff.c:htsbuff_ptr_ |
398 | | |
399 | | /** |
400 | | * Builder over the in-scope array ARR (capacity = sizeof(ARR)). |
401 | | * On GCC/Clang this rejects a non-array (e.g. a char* pointer), whose sizeof |
402 | | * would be the pointer size and silently wrong; use htsbuff_ptr() for pointers. |
403 | | * On other compilers there is no such guard, so pass only true arrays there. |
404 | | */ |
405 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
406 | | |
407 | | /* 0 for an array, a -1 array-size compile error for a pointer. */ |
408 | | #define htsbuff_must_be_array_(A) \ |
409 | 0 | (sizeof(char[1 - 2 * !!__builtin_types_compatible_p(typeof(A), \ |
410 | 0 | typeof(&(A)[0]))]) - \ |
411 | 0 | 1) |
412 | | |
413 | | #define htsbuff_array(ARR) \ |
414 | 0 | htsbuff_ptr_((ARR), sizeof(ARR) + htsbuff_must_be_array_(ARR)) |
415 | | #else |
416 | | #define htsbuff_array(ARR) htsbuff_ptr_((ARR), sizeof(ARR)) |
417 | | #endif |
418 | | /** Builder over pointer P of known capacity N (N includes the NUL). */ |
419 | 0 | #define htsbuff_ptr(P, N) htsbuff_ptr_((P), (N)) |
420 | | |
421 | | /** Append at most n characters of s (stopping at its NUL). Aborts on overflow. |
422 | | */ |
423 | | static HTS_INLINE HTS_UNUSED void htsbuff_catn(htsbuff *b, const char *s, |
424 | 0 | size_t n) { |
425 | 0 | const size_t add = strnlen(s, n); |
426 | | /* Overflow-safe: keep the (potentially huge) 'add' alone on one side. The |
427 | | maintained invariant len < cap makes 'cap - len' >= 1 (no underflow), so |
428 | | 'add < cap - len' cannot wrap the way 'len + add < cap' could. */ |
429 | 0 | assertf__(add < b->cap - b->len, "htsbuff append overflow", __FILE__, |
430 | 0 | __LINE__); |
431 | 0 | memcpy(b->buf + b->len, s, add); |
432 | 0 | b->len += add; |
433 | 0 | b->buf[b->len] = '\0'; |
434 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_catn Unexecuted instantiation: htslib.c:htsbuff_catn Unexecuted instantiation: htstools.c:htsbuff_catn Unexecuted instantiation: htsthread.c:htsbuff_catn Unexecuted instantiation: htsbauth.c:htsbuff_catn Unexecuted instantiation: htsmd5.c:htsbuff_catn Unexecuted instantiation: htscodec.c:htsbuff_catn Unexecuted instantiation: htswarc.c:htsbuff_catn Unexecuted instantiation: htszlib.c:htsbuff_catn Unexecuted instantiation: htsconcat.c:htsbuff_catn Unexecuted instantiation: htsmodules.c:htsbuff_catn Unexecuted instantiation: htscharset.c:htsbuff_catn Unexecuted instantiation: htsencoding.c:htsbuff_catn Unexecuted instantiation: htscore.c:htsbuff_catn Unexecuted instantiation: htsparse.c:htsbuff_catn Unexecuted instantiation: htsback.c:htsbuff_catn Unexecuted instantiation: htscache.c:htsbuff_catn Unexecuted instantiation: htsfilters.c:htsbuff_catn Unexecuted instantiation: htsftp.c:htsbuff_catn Unexecuted instantiation: htshash.c:htsbuff_catn Unexecuted instantiation: htsname.c:htsbuff_catn Unexecuted instantiation: htsrobots.c:htsbuff_catn Unexecuted instantiation: htswizard.c:htsbuff_catn Unexecuted instantiation: htsindex.c:htsbuff_catn Unexecuted instantiation: htsproxy.c:htsbuff_catn Unexecuted instantiation: htssniff.c:htsbuff_catn |
435 | | |
436 | | /** Append s. Aborts on overflow. */ |
437 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_cat(htsbuff *b, const char *s) { |
438 | 0 | htsbuff_catn(b, s, (size_t) -1); |
439 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_cat Unexecuted instantiation: htslib.c:htsbuff_cat Unexecuted instantiation: htstools.c:htsbuff_cat Unexecuted instantiation: htsthread.c:htsbuff_cat Unexecuted instantiation: htsbauth.c:htsbuff_cat Unexecuted instantiation: htsmd5.c:htsbuff_cat Unexecuted instantiation: htscodec.c:htsbuff_cat Unexecuted instantiation: htswarc.c:htsbuff_cat Unexecuted instantiation: htszlib.c:htsbuff_cat Unexecuted instantiation: htsconcat.c:htsbuff_cat Unexecuted instantiation: htsmodules.c:htsbuff_cat Unexecuted instantiation: htscharset.c:htsbuff_cat Unexecuted instantiation: htsencoding.c:htsbuff_cat Unexecuted instantiation: htscore.c:htsbuff_cat Unexecuted instantiation: htsparse.c:htsbuff_cat Unexecuted instantiation: htsback.c:htsbuff_cat Unexecuted instantiation: htscache.c:htsbuff_cat Unexecuted instantiation: htsfilters.c:htsbuff_cat Unexecuted instantiation: htsftp.c:htsbuff_cat Unexecuted instantiation: htshash.c:htsbuff_cat Unexecuted instantiation: htsname.c:htsbuff_cat Unexecuted instantiation: htsrobots.c:htsbuff_cat Unexecuted instantiation: htswizard.c:htsbuff_cat Unexecuted instantiation: htsindex.c:htsbuff_cat Unexecuted instantiation: htsproxy.c:htsbuff_cat Unexecuted instantiation: htssniff.c:htsbuff_cat |
440 | | |
441 | | /** Append a single character (including '\0' as data). Aborts on overflow. */ |
442 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_catc(htsbuff *b, char c) { |
443 | 0 | assertf__(1 < b->cap - b->len, "htsbuff append overflow", __FILE__, __LINE__); |
444 | 0 | b->buf[b->len++] = c; |
445 | 0 | b->buf[b->len] = '\0'; |
446 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_catc Unexecuted instantiation: htslib.c:htsbuff_catc Unexecuted instantiation: htstools.c:htsbuff_catc Unexecuted instantiation: htsthread.c:htsbuff_catc Unexecuted instantiation: htsbauth.c:htsbuff_catc Unexecuted instantiation: htsmd5.c:htsbuff_catc Unexecuted instantiation: htscodec.c:htsbuff_catc Unexecuted instantiation: htswarc.c:htsbuff_catc Unexecuted instantiation: htszlib.c:htsbuff_catc Unexecuted instantiation: htsconcat.c:htsbuff_catc Unexecuted instantiation: htsmodules.c:htsbuff_catc Unexecuted instantiation: htscharset.c:htsbuff_catc Unexecuted instantiation: htsencoding.c:htsbuff_catc Unexecuted instantiation: htscore.c:htsbuff_catc Unexecuted instantiation: htsparse.c:htsbuff_catc Unexecuted instantiation: htsback.c:htsbuff_catc Unexecuted instantiation: htscache.c:htsbuff_catc Unexecuted instantiation: htsfilters.c:htsbuff_catc Unexecuted instantiation: htsftp.c:htsbuff_catc Unexecuted instantiation: htshash.c:htsbuff_catc Unexecuted instantiation: htsname.c:htsbuff_catc Unexecuted instantiation: htsrobots.c:htsbuff_catc Unexecuted instantiation: htswizard.c:htsbuff_catc Unexecuted instantiation: htsindex.c:htsbuff_catc Unexecuted instantiation: htsproxy.c:htsbuff_catc Unexecuted instantiation: htssniff.c:htsbuff_catc |
447 | | |
448 | | /** Reset content to s. Aborts on overflow. */ |
449 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_cpy(htsbuff *b, const char *s) { |
450 | 0 | b->len = 0; |
451 | 0 | htsbuff_catn(b, s, (size_t) -1); |
452 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_cpy Unexecuted instantiation: htslib.c:htsbuff_cpy Unexecuted instantiation: htstools.c:htsbuff_cpy Unexecuted instantiation: htsthread.c:htsbuff_cpy Unexecuted instantiation: htsbauth.c:htsbuff_cpy Unexecuted instantiation: htsmd5.c:htsbuff_cpy Unexecuted instantiation: htscodec.c:htsbuff_cpy Unexecuted instantiation: htswarc.c:htsbuff_cpy Unexecuted instantiation: htszlib.c:htsbuff_cpy Unexecuted instantiation: htsconcat.c:htsbuff_cpy Unexecuted instantiation: htsmodules.c:htsbuff_cpy Unexecuted instantiation: htscharset.c:htsbuff_cpy Unexecuted instantiation: htsencoding.c:htsbuff_cpy Unexecuted instantiation: htscore.c:htsbuff_cpy Unexecuted instantiation: htsparse.c:htsbuff_cpy Unexecuted instantiation: htsback.c:htsbuff_cpy Unexecuted instantiation: htscache.c:htsbuff_cpy Unexecuted instantiation: htsfilters.c:htsbuff_cpy Unexecuted instantiation: htsftp.c:htsbuff_cpy Unexecuted instantiation: htshash.c:htsbuff_cpy Unexecuted instantiation: htsname.c:htsbuff_cpy Unexecuted instantiation: htsrobots.c:htsbuff_cpy Unexecuted instantiation: htswizard.c:htsbuff_cpy Unexecuted instantiation: htsindex.c:htsbuff_cpy Unexecuted instantiation: htsproxy.c:htsbuff_cpy Unexecuted instantiation: htssniff.c:htsbuff_cpy |
453 | | |
454 | | /** Current NUL-terminated content. */ |
455 | 0 | static HTS_INLINE HTS_UNUSED const char *htsbuff_str(const htsbuff *b) { |
456 | 0 | return b->buf; |
457 | 0 | } Unexecuted instantiation: fuzz-url.c:htsbuff_str Unexecuted instantiation: htslib.c:htsbuff_str Unexecuted instantiation: htstools.c:htsbuff_str Unexecuted instantiation: htsthread.c:htsbuff_str Unexecuted instantiation: htsbauth.c:htsbuff_str Unexecuted instantiation: htsmd5.c:htsbuff_str Unexecuted instantiation: htscodec.c:htsbuff_str Unexecuted instantiation: htswarc.c:htsbuff_str Unexecuted instantiation: htszlib.c:htsbuff_str Unexecuted instantiation: htsconcat.c:htsbuff_str Unexecuted instantiation: htsmodules.c:htsbuff_str Unexecuted instantiation: htscharset.c:htsbuff_str Unexecuted instantiation: htsencoding.c:htsbuff_str Unexecuted instantiation: htscore.c:htsbuff_str Unexecuted instantiation: htsparse.c:htsbuff_str Unexecuted instantiation: htsback.c:htsbuff_str Unexecuted instantiation: htscache.c:htsbuff_str Unexecuted instantiation: htsfilters.c:htsbuff_str Unexecuted instantiation: htsftp.c:htsbuff_str Unexecuted instantiation: htshash.c:htsbuff_str Unexecuted instantiation: htsname.c:htsbuff_str Unexecuted instantiation: htsrobots.c:htsbuff_str Unexecuted instantiation: htswizard.c:htsbuff_str Unexecuted instantiation: htsindex.c:htsbuff_str Unexecuted instantiation: htsproxy.c:htsbuff_str Unexecuted instantiation: htssniff.c:htsbuff_str |
458 | | |
459 | | /* Thin aliases over the libc allocator/memcpy (historical "t" suffix); no |
460 | | added bounds checking. freet() also NULLs the freed pointer and tolerates |
461 | | NULL. memcpybuff() despite the name is a raw memcpy: the caller owns the |
462 | | bounds. */ |
463 | 1.10k | #define malloct(A) malloc(A) |
464 | | |
465 | 551 | #define calloct(A, B) calloc((A), (B)) |
466 | | |
467 | | #define freet(A) \ |
468 | 1.65k | do { \ |
469 | 1.65k | if ((A) != NULL) { \ |
470 | 1.65k | free(A); \ |
471 | 1.65k | (A) = NULL; \ |
472 | 1.65k | } \ |
473 | 1.65k | } while (0) |
474 | | |
475 | 0 | #define strdupt(A) strdup(A) |
476 | | |
477 | 0 | #define realloct(A, B) realloc(A, B) |
478 | | |
479 | | #define memcpybuff(A, B, N) memcpy((A), (B), (N)) |
480 | | |
481 | | #endif |