/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 | | /** |
34 | | * @file htssafe.h |
35 | | * Safe string helpers, the fatal-assert machinery, and the "t" allocator |
36 | | * wrappers the engine uses instead of raw libc. |
37 | | * |
38 | | * Pick a helper by its overflow behaviour. The buff() family ABORTS the process |
39 | | * on overflow, though only when the destination is an array and not a bare |
40 | | * char*, for the reason the size contract below gives. The htsbuff builder |
41 | | * aborts either way. Aborting is right for data we built ourselves and wrong |
42 | | * for a value read off the wire, out of a cache or out of a header, because it |
43 | | * turns a memory smash into a crash on malformed input. Clip such a value |
44 | | * instead, with strclipbuff() or slprintfbuff(), or from the buff() family with |
45 | | * dest[0] = '\0'; strlncatbuff(dest, src, size, size - 1). The clip helpers |
46 | | * still abort on a NULL buffer or a zero size, so check a computed size first. |
47 | | */ |
48 | | |
49 | | #ifndef HTSSAFE_DEFH |
50 | | #define HTSSAFE_DEFH |
51 | | |
52 | | #include <stdarg.h> |
53 | | #include <stdio.h> |
54 | | #include <stdlib.h> |
55 | | #include <string.h> |
56 | | |
57 | | #include "htsglobal.h" |
58 | | |
59 | | /** |
60 | | * HTSSAFE_ABORT_FUNCTION(msg, file, line) reports a failed assert just before |
61 | | * the process aborts. Inside libhttrack it hands the message to the callback |
62 | | * installed by hts_set_error_callback(). Another consumer may define its own |
63 | | * before including this header, and gets only the stderr line if it does not. |
64 | | */ |
65 | | #if (!defined(HTSSAFE_ABORT_FUNCTION) && defined(LIBHTTRACK_EXPORTS)) |
66 | | |
67 | | #ifndef HTS_DEF_FWSTRUCT_htsErrorCallback |
68 | | #define HTS_DEF_FWSTRUCT_htsErrorCallback |
69 | | /** A handler receives a failed assert's message, source file and line. */ |
70 | | typedef void (*htsErrorCallback)(const char *msg, const char *file, int line); |
71 | | #ifdef __cplusplus |
72 | | extern "C" { |
73 | | #endif |
74 | | /** Returns the callback installed by hts_set_error_callback(), or NULL. */ |
75 | | HTSEXT_API htsErrorCallback hts_get_error_callback(void); |
76 | | #ifdef __cplusplus |
77 | | } |
78 | | #endif |
79 | | #endif |
80 | | |
81 | | #define HTSSAFE_ABORT_FUNCTION(A, B, C) \ |
82 | 0 | do { \ |
83 | 0 | htsErrorCallback callback = hts_get_error_callback(); \ |
84 | 0 | if (callback != NULL) { \ |
85 | 0 | callback(A, B, C); \ |
86 | 0 | } \ |
87 | 0 | } while (0) |
88 | | |
89 | | #endif |
90 | | |
91 | | /** Report message a with this call site's location, then abort. */ |
92 | 0 | #define abortLog(a) abortf_(a, __FILE__, __LINE__) |
93 | | |
94 | | /** Abort unless exp holds, reporting sexp instead of exp's own source text. */ |
95 | | #define assertf__(exp, sexp, file, line) \ |
96 | 1.60M | (void) ((exp) || (abortf_(sexp, file, line), 0)) |
97 | | |
98 | | /** Abort unless exp holds, reporting file and line instead of this call |
99 | | site's. */ |
100 | 1.32M | #define assertf_(exp, file, line) assertf__(exp, #exp, file, line) |
101 | | |
102 | | /** |
103 | | * Abort the process unless exp holds. NDEBUG does not disable it, so it guards |
104 | | * release builds too. |
105 | | */ |
106 | 64.5k | #define assertf(exp) assertf_(exp, __FILE__, __LINE__) |
107 | | |
108 | | /** Print msg and its source location to stderr. */ |
109 | 0 | static HTS_UNUSED void log_abort_(const char *msg, const char *file, int line) { |
110 | 0 | fprintf(stderr, "%s failed at %s:%d\n", msg, file, line); |
111 | 0 | fflush(stderr); |
112 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:log_abort_ Unexecuted instantiation: store.c:log_abort_ Unexecuted instantiation: htsdate.c:log_abort_ Unexecuted instantiation: htslib.c:log_abort_ Unexecuted instantiation: htsfetch.c:log_abort_ Unexecuted instantiation: htspsl.c:log_abort_ Unexecuted instantiation: htslines.c:log_abort_ Unexecuted instantiation: htscore.c:log_abort_ Unexecuted instantiation: htshash.c:log_abort_ Unexecuted instantiation: htscache.c:log_abort_ Unexecuted instantiation: htsback.c:log_abort_ Unexecuted instantiation: htsftp.c:log_abort_ Unexecuted instantiation: htsparse.c:log_abort_ Unexecuted instantiation: htscmdline.c:log_abort_ Unexecuted instantiation: htsfilters.c:log_abort_ Unexecuted instantiation: htsname.c:log_abort_ Unexecuted instantiation: htsrobots.c:log_abort_ Unexecuted instantiation: htstools.c:log_abort_ Unexecuted instantiation: htswizard.c:log_abort_ Unexecuted instantiation: htsthread.c:log_abort_ Unexecuted instantiation: htsindex.c:log_abort_ Unexecuted instantiation: htsbauth.c:log_abort_ Unexecuted instantiation: htscrashtest.c:log_abort_ Unexecuted instantiation: htsmd5.c:log_abort_ Unexecuted instantiation: htsnet.c:log_abort_ Unexecuted instantiation: htscodec.c:log_abort_ Unexecuted instantiation: htswarc.c:log_abort_ Unexecuted instantiation: htschanges.c:log_abort_ Unexecuted instantiation: htssinglefile.c:log_abort_ Unexecuted instantiation: htssitemap.c:log_abort_ Unexecuted instantiation: htsproxy.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: htsescape.c:log_abort_ Unexecuted instantiation: htssniff.c:log_abort_ |
113 | | |
114 | | /** Report exp at file:line through the abort hook and stderr, then abort. */ |
115 | | static HTS_NORETURN HTS_UNUSED void abortf_(const char *exp, const char *file, |
116 | 0 | int line) { |
117 | 0 | #ifdef HTSSAFE_ABORT_FUNCTION |
118 | 0 | HTSSAFE_ABORT_FUNCTION(exp, file, line); |
119 | 0 | #endif |
120 | 0 | log_abort_(exp, file, line); |
121 | 0 | abort(); |
122 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:abortf_ Unexecuted instantiation: store.c:abortf_ Unexecuted instantiation: htsdate.c:abortf_ Unexecuted instantiation: htslib.c:abortf_ Unexecuted instantiation: htsfetch.c:abortf_ Unexecuted instantiation: htspsl.c:abortf_ Unexecuted instantiation: htslines.c:abortf_ Unexecuted instantiation: htscore.c:abortf_ Unexecuted instantiation: htshash.c:abortf_ Unexecuted instantiation: htscache.c:abortf_ Unexecuted instantiation: htsback.c:abortf_ Unexecuted instantiation: htsftp.c:abortf_ Unexecuted instantiation: htsparse.c:abortf_ Unexecuted instantiation: htscmdline.c:abortf_ Unexecuted instantiation: htsfilters.c:abortf_ Unexecuted instantiation: htsname.c:abortf_ Unexecuted instantiation: htsrobots.c:abortf_ Unexecuted instantiation: htstools.c:abortf_ Unexecuted instantiation: htswizard.c:abortf_ Unexecuted instantiation: htsthread.c:abortf_ Unexecuted instantiation: htsindex.c:abortf_ Unexecuted instantiation: htsbauth.c:abortf_ Unexecuted instantiation: htscrashtest.c:abortf_ Unexecuted instantiation: htsmd5.c:abortf_ Unexecuted instantiation: htsnet.c:abortf_ Unexecuted instantiation: htscodec.c:abortf_ Unexecuted instantiation: htswarc.c:abortf_ Unexecuted instantiation: htschanges.c:abortf_ Unexecuted instantiation: htssinglefile.c:abortf_ Unexecuted instantiation: htssitemap.c:abortf_ Unexecuted instantiation: htsproxy.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: htsescape.c:abortf_ Unexecuted instantiation: htssniff.c:abortf_ |
123 | | |
124 | | /** |
125 | | * Is VAR a sized char[] array rather than a char* pointer? VAR is not |
126 | | * evaluated. |
127 | | */ |
128 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
129 | | |
130 | | /* Note: char[] and const char[] are compatible */ |
131 | | #define HTS_IS_CHAR_BUFFER(VAR) \ |
132 | 512k | (__builtin_types_compatible_p(__typeof__(VAR), char[])) |
133 | | #else |
134 | | /* An array of exactly pointer size reads as a pointer and loses its bound: |
135 | | keep buff() destinations off char[8] (Win64) and char[4] (Win32). */ |
136 | | #define HTS_IS_CHAR_BUFFER(VAR) (sizeof(VAR) != sizeof(char *)) |
137 | | #endif |
138 | 277k | #define HTS_IS_NOT_CHAR_BUFFER(VAR) (!HTS_IS_CHAR_BUFFER(VAR)) |
139 | | |
140 | | /* Source capacity for the buff() family, (size_t)-1 when unknown; sizeof of the |
141 | | TYPE keeps a decayed operand ("buf + 1") off -Wsizeof-array-decay. */ |
142 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
143 | | #define HTS_SIZEOF_SRC_(B) \ |
144 | 277k | (HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(__typeof__(B))) |
145 | | #else |
146 | | #define HTS_SIZEOF_SRC_(B) (HTS_IS_NOT_CHAR_BUFFER(B) ? (size_t) -1 : sizeof(B)) |
147 | | #endif |
148 | | |
149 | | /** This function does not compile if HTS_IS_CHAR_BUFFER() confuses an array |
150 | | with a pointer. */ |
151 | 0 | static HTS_UNUSED void htssafe_compile_time_check_(void) { |
152 | 0 | char array[32]; |
153 | 0 | char *pointer = array; |
154 | 0 | char check_array[HTS_IS_CHAR_BUFFER(array) ? 1 : -1]; |
155 | 0 | char check_pointer[HTS_IS_CHAR_BUFFER(pointer) ? -1 : 1]; |
156 | 0 | (void) pointer; |
157 | 0 | (void) check_array; |
158 | 0 | (void) check_pointer; |
159 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htssafe_compile_time_check_ Unexecuted instantiation: store.c:htssafe_compile_time_check_ Unexecuted instantiation: htsdate.c:htssafe_compile_time_check_ Unexecuted instantiation: htslib.c:htssafe_compile_time_check_ Unexecuted instantiation: htsfetch.c:htssafe_compile_time_check_ Unexecuted instantiation: htspsl.c:htssafe_compile_time_check_ Unexecuted instantiation: htslines.c:htssafe_compile_time_check_ Unexecuted instantiation: htscore.c:htssafe_compile_time_check_ Unexecuted instantiation: htshash.c:htssafe_compile_time_check_ Unexecuted instantiation: htscache.c:htssafe_compile_time_check_ Unexecuted instantiation: htsback.c:htssafe_compile_time_check_ Unexecuted instantiation: htsftp.c:htssafe_compile_time_check_ Unexecuted instantiation: htsparse.c:htssafe_compile_time_check_ Unexecuted instantiation: htscmdline.c:htssafe_compile_time_check_ Unexecuted instantiation: htsfilters.c:htssafe_compile_time_check_ Unexecuted instantiation: htsname.c:htssafe_compile_time_check_ Unexecuted instantiation: htsrobots.c:htssafe_compile_time_check_ Unexecuted instantiation: htstools.c:htssafe_compile_time_check_ Unexecuted instantiation: htswizard.c:htssafe_compile_time_check_ Unexecuted instantiation: htsthread.c:htssafe_compile_time_check_ Unexecuted instantiation: htsindex.c:htssafe_compile_time_check_ Unexecuted instantiation: htsbauth.c:htssafe_compile_time_check_ Unexecuted instantiation: htscrashtest.c:htssafe_compile_time_check_ Unexecuted instantiation: htsmd5.c:htssafe_compile_time_check_ Unexecuted instantiation: htsnet.c:htssafe_compile_time_check_ Unexecuted instantiation: htscodec.c:htssafe_compile_time_check_ Unexecuted instantiation: htswarc.c:htssafe_compile_time_check_ Unexecuted instantiation: htschanges.c:htssafe_compile_time_check_ Unexecuted instantiation: htssinglefile.c:htssafe_compile_time_check_ Unexecuted instantiation: htssitemap.c:htssafe_compile_time_check_ Unexecuted instantiation: htsproxy.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: htsescape.c:htssafe_compile_time_check_ Unexecuted instantiation: htssniff.c:htssafe_compile_time_check_ |
160 | | |
161 | | /* |
162 | | * Stubs standing in for the buff() macros when the destination is a bare |
163 | | * char* of unknown capacity, so the copy is NOT bounds-checked and cannot |
164 | | * abort. On GCC/Clang in C mode such a call site is a compile-time warning |
165 | | * naming the explicit-size replacement, and other compilers stay silent. |
166 | | */ |
167 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
168 | | |
169 | | #if defined(__has_attribute) |
170 | | |
171 | | #if __has_attribute(warning) |
172 | | |
173 | | #define HTS_BUFF_PTR_ATTR(msg) __attribute__((unused, noinline, warning(msg))) |
174 | | #endif |
175 | | #endif |
176 | | #ifndef HTS_BUFF_PTR_ATTR |
177 | | /* 'warning' attribute unavailable, so no diagnostic is emitted. noinline |
178 | | keeps these stubs visible as symbols. */ |
179 | | #define HTS_BUFF_PTR_ATTR(msg) __attribute__((unused, noinline)) |
180 | | #endif |
181 | | |
182 | | HTS_BUFF_PTR_ATTR("strcpybuff() destination is a pointer (capacity unknown): " |
183 | | "NOT bounds-checked; use strlcpybuff(dst, src, size)") |
184 | | |
185 | 0 | static char *strcpybuff_ptr_(char *dest, const char *src) { |
186 | 0 | return strcpy(dest, src); |
187 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:strcpybuff_ptr_ Unexecuted instantiation: store.c:strcpybuff_ptr_ Unexecuted instantiation: htsdate.c:strcpybuff_ptr_ Unexecuted instantiation: htslib.c:strcpybuff_ptr_ Unexecuted instantiation: htsfetch.c:strcpybuff_ptr_ Unexecuted instantiation: htspsl.c:strcpybuff_ptr_ Unexecuted instantiation: htslines.c:strcpybuff_ptr_ Unexecuted instantiation: htscore.c:strcpybuff_ptr_ Unexecuted instantiation: htshash.c:strcpybuff_ptr_ Unexecuted instantiation: htscache.c:strcpybuff_ptr_ Unexecuted instantiation: htsback.c:strcpybuff_ptr_ Unexecuted instantiation: htsftp.c:strcpybuff_ptr_ Unexecuted instantiation: htsparse.c:strcpybuff_ptr_ Unexecuted instantiation: htscmdline.c:strcpybuff_ptr_ Unexecuted instantiation: htsfilters.c:strcpybuff_ptr_ Unexecuted instantiation: htsname.c:strcpybuff_ptr_ Unexecuted instantiation: htsrobots.c:strcpybuff_ptr_ Unexecuted instantiation: htstools.c:strcpybuff_ptr_ Unexecuted instantiation: htswizard.c:strcpybuff_ptr_ Unexecuted instantiation: htsthread.c:strcpybuff_ptr_ Unexecuted instantiation: htsindex.c:strcpybuff_ptr_ Unexecuted instantiation: htsbauth.c:strcpybuff_ptr_ Unexecuted instantiation: htscrashtest.c:strcpybuff_ptr_ Unexecuted instantiation: htsmd5.c:strcpybuff_ptr_ Unexecuted instantiation: htsnet.c:strcpybuff_ptr_ Unexecuted instantiation: htscodec.c:strcpybuff_ptr_ Unexecuted instantiation: htswarc.c:strcpybuff_ptr_ Unexecuted instantiation: htschanges.c:strcpybuff_ptr_ Unexecuted instantiation: htssinglefile.c:strcpybuff_ptr_ Unexecuted instantiation: htssitemap.c:strcpybuff_ptr_ Unexecuted instantiation: htsproxy.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: htsescape.c:strcpybuff_ptr_ Unexecuted instantiation: htssniff.c:strcpybuff_ptr_ |
188 | | |
189 | | HTS_BUFF_PTR_ATTR("strcatbuff() destination is a pointer (capacity unknown): " |
190 | | "NOT bounds-checked; use strlcatbuff(dst, src, size)") |
191 | | |
192 | 0 | static char *strcatbuff_ptr_(char *dest, const char *src) { |
193 | 0 | return strcat(dest, src); |
194 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:strcatbuff_ptr_ Unexecuted instantiation: store.c:strcatbuff_ptr_ Unexecuted instantiation: htsdate.c:strcatbuff_ptr_ Unexecuted instantiation: htslib.c:strcatbuff_ptr_ Unexecuted instantiation: htsfetch.c:strcatbuff_ptr_ Unexecuted instantiation: htspsl.c:strcatbuff_ptr_ Unexecuted instantiation: htslines.c:strcatbuff_ptr_ Unexecuted instantiation: htscore.c:strcatbuff_ptr_ Unexecuted instantiation: htshash.c:strcatbuff_ptr_ Unexecuted instantiation: htscache.c:strcatbuff_ptr_ Unexecuted instantiation: htsback.c:strcatbuff_ptr_ Unexecuted instantiation: htsftp.c:strcatbuff_ptr_ Unexecuted instantiation: htsparse.c:strcatbuff_ptr_ Unexecuted instantiation: htscmdline.c:strcatbuff_ptr_ Unexecuted instantiation: htsfilters.c:strcatbuff_ptr_ Unexecuted instantiation: htsname.c:strcatbuff_ptr_ Unexecuted instantiation: htsrobots.c:strcatbuff_ptr_ Unexecuted instantiation: htstools.c:strcatbuff_ptr_ Unexecuted instantiation: htswizard.c:strcatbuff_ptr_ Unexecuted instantiation: htsthread.c:strcatbuff_ptr_ Unexecuted instantiation: htsindex.c:strcatbuff_ptr_ Unexecuted instantiation: htsbauth.c:strcatbuff_ptr_ Unexecuted instantiation: htscrashtest.c:strcatbuff_ptr_ Unexecuted instantiation: htsmd5.c:strcatbuff_ptr_ Unexecuted instantiation: htsnet.c:strcatbuff_ptr_ Unexecuted instantiation: htscodec.c:strcatbuff_ptr_ Unexecuted instantiation: htswarc.c:strcatbuff_ptr_ Unexecuted instantiation: htschanges.c:strcatbuff_ptr_ Unexecuted instantiation: htssinglefile.c:strcatbuff_ptr_ Unexecuted instantiation: htssitemap.c:strcatbuff_ptr_ Unexecuted instantiation: htsproxy.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: htsescape.c:strcatbuff_ptr_ Unexecuted instantiation: htssniff.c:strcatbuff_ptr_ |
195 | | |
196 | | HTS_BUFF_PTR_ATTR("strncatbuff() destination is a pointer (capacity unknown): " |
197 | | "NOT bounds-checked; use strlcatbuff(dst, src, size)") |
198 | | |
199 | 0 | static char *strncatbuff_ptr_(char *dest, const char *src, size_t n) { |
200 | 0 | return strncat(dest, src, n); |
201 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:strncatbuff_ptr_ Unexecuted instantiation: store.c:strncatbuff_ptr_ Unexecuted instantiation: htsdate.c:strncatbuff_ptr_ Unexecuted instantiation: htslib.c:strncatbuff_ptr_ Unexecuted instantiation: htsfetch.c:strncatbuff_ptr_ Unexecuted instantiation: htspsl.c:strncatbuff_ptr_ Unexecuted instantiation: htslines.c:strncatbuff_ptr_ Unexecuted instantiation: htscore.c:strncatbuff_ptr_ Unexecuted instantiation: htshash.c:strncatbuff_ptr_ Unexecuted instantiation: htscache.c:strncatbuff_ptr_ Unexecuted instantiation: htsback.c:strncatbuff_ptr_ Unexecuted instantiation: htsftp.c:strncatbuff_ptr_ Unexecuted instantiation: htsparse.c:strncatbuff_ptr_ Unexecuted instantiation: htscmdline.c:strncatbuff_ptr_ Unexecuted instantiation: htsfilters.c:strncatbuff_ptr_ Unexecuted instantiation: htsname.c:strncatbuff_ptr_ Unexecuted instantiation: htsrobots.c:strncatbuff_ptr_ Unexecuted instantiation: htstools.c:strncatbuff_ptr_ Unexecuted instantiation: htswizard.c:strncatbuff_ptr_ Unexecuted instantiation: htsthread.c:strncatbuff_ptr_ Unexecuted instantiation: htsindex.c:strncatbuff_ptr_ Unexecuted instantiation: htsbauth.c:strncatbuff_ptr_ Unexecuted instantiation: htscrashtest.c:strncatbuff_ptr_ Unexecuted instantiation: htsmd5.c:strncatbuff_ptr_ Unexecuted instantiation: htsnet.c:strncatbuff_ptr_ Unexecuted instantiation: htscodec.c:strncatbuff_ptr_ Unexecuted instantiation: htswarc.c:strncatbuff_ptr_ Unexecuted instantiation: htschanges.c:strncatbuff_ptr_ Unexecuted instantiation: htssinglefile.c:strncatbuff_ptr_ Unexecuted instantiation: htssitemap.c:strncatbuff_ptr_ Unexecuted instantiation: htsproxy.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: htsescape.c:strncatbuff_ptr_ Unexecuted instantiation: htssniff.c:strncatbuff_ptr_ |
202 | | #endif |
203 | | |
204 | | /* |
205 | | * SIZE CONTRACT shared by strcpybuff/strcatbuff/strncatbuff (the "buff" |
206 | | * family): the destination bound is taken from sizeof(A), so A MUST be a real |
207 | | * char[] array in scope. The bound is the full array size in bytes, INCLUDING |
208 | | * the terminating NUL. On overflow the *_safe_ helpers do NOT truncate: they |
209 | | * abort() (assertf). The destination must already be NUL-terminated inside its |
210 | | * capacity, because its length is measured first, and an unterminated one |
211 | | * aborts too. On success the result is always NUL-terminated. |
212 | | * |
213 | | * CRITICAL CAVEAT: if A is a bare char* pointer (not an array), sizeof(A) is |
214 | | * the pointer size, not the buffer capacity. There is no way to recover the |
215 | | * real capacity, so these macros SILENTLY DEGRADE to the unbounded raw |
216 | | * strcpy()/strcat()/strncat() while still looking like a checked call. The |
217 | | * bound is lost. On GCC/Clang (C) the pointer case routes through the |
218 | | * *_ptr_ stubs above, which carry a 'warning' attribute to flag the site at |
219 | | * compile time; on other compilers it is silent. When the destination is a |
220 | | * pointer of known capacity, call the explicit-size strlcpybuff/strlcatbuff |
221 | | * (passing the capacity, NUL included) instead. |
222 | | */ |
223 | | |
224 | | /** |
225 | | * Append at most N bytes of B to A, and ABORT if the result does not fit. B |
226 | | * must still be NUL-terminated, because its whole length is measured before N |
227 | | * caps it. A's capacity comes from the size contract above. |
228 | | */ |
229 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
230 | | |
231 | | #define strncatbuff(A, B, N) \ |
232 | 32.3k | __builtin_choose_expr(HTS_IS_CHAR_BUFFER(A), \ |
233 | 32.3k | strncat_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), N, \ |
234 | 32.3k | "overflow while appending '" #B \ |
235 | 32.3k | "' to '" #A "'", \ |
236 | 32.3k | __FILE__, __LINE__), \ |
237 | 32.3k | strncatbuff_ptr_((A), (B), (N))) |
238 | | #else |
239 | | #define strncatbuff(A, B, N) \ |
240 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
241 | | ? strncat(A, B, N) \ |
242 | | : strncat_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), N, \ |
243 | | "overflow while appending '" #B "' to '" #A "'", \ |
244 | | __FILE__, __LINE__)) |
245 | | #endif |
246 | | |
247 | | /** Append all of B to A, and ABORT if the result does not fit. A's capacity |
248 | | comes from the size contract above. */ |
249 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
250 | | |
251 | | #define strcatbuff(A, B) \ |
252 | 52.4k | __builtin_choose_expr( \ |
253 | 52.4k | HTS_IS_CHAR_BUFFER(A), \ |
254 | 52.4k | strncat_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), (size_t) -1, \ |
255 | 52.4k | "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
256 | 52.4k | __LINE__), \ |
257 | 52.4k | strcatbuff_ptr_((A), (B))) |
258 | | #else |
259 | | #define strcatbuff(A, B) \ |
260 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
261 | | ? strcat(A, B) \ |
262 | | : strncat_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), (size_t) -1, \ |
263 | | "overflow while appending '" #B "' to '" #A "'", \ |
264 | | __FILE__, __LINE__)) |
265 | | #endif |
266 | | |
267 | | /** Copy B over A, and ABORT if it does not fit. A's capacity comes from the |
268 | | size contract above. */ |
269 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
270 | | |
271 | | #define strcpybuff(A, B) \ |
272 | 150k | __builtin_choose_expr(HTS_IS_CHAR_BUFFER(A), \ |
273 | 150k | strcpy_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), \ |
274 | 150k | "overflow while copying '" #B "' to '" #A \ |
275 | 150k | "'", \ |
276 | 150k | __FILE__, __LINE__), \ |
277 | 150k | strcpybuff_ptr_((A), (B))) |
278 | | #else |
279 | | #define strcpybuff(A, B) \ |
280 | | (HTS_IS_NOT_CHAR_BUFFER(A) \ |
281 | | ? strcpy(A, B) \ |
282 | | : strcpy_safe_(A, sizeof(A), B, HTS_SIZEOF_SRC_(B), \ |
283 | | "overflow while copying '" #B "' to '" #A "'", __FILE__, \ |
284 | | __LINE__)) |
285 | | #endif |
286 | | |
287 | | /* |
288 | | * Explicit-size variants (strlcatbuff/strlncatbuff/strlcpybuff): the |
289 | | * destination capacity is the caller-supplied S (total bytes, NUL included), |
290 | | * NOT derived from sizeof(A). Use these when A is a pointer or its capacity is |
291 | | * not its sizeof. Same abort-on-overflow, always-NUL-terminated contract; no |
292 | | * silent pointer degradation since the bound is passed in. |
293 | | */ |
294 | | |
295 | | /** Append all of B to A, whose capacity is S bytes including the NUL. ABORTS |
296 | | if the result does not fit. */ |
297 | | #define strlcatbuff(A, B, S) \ |
298 | 0 | strncat_safe_(A, S, B, HTS_SIZEOF_SRC_(B), (size_t) -1, \ |
299 | 0 | "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
300 | 0 | __LINE__) |
301 | | |
302 | | /** Append at most N bytes of B to A, whose capacity is S bytes including the |
303 | | NUL. ABORTS if the result does not fit. */ |
304 | | #define strlncatbuff(A, B, S, N) \ |
305 | 42.7k | strncat_safe_(A, S, B, HTS_SIZEOF_SRC_(B), N, \ |
306 | 42.7k | "overflow while appending '" #B "' to '" #A "'", __FILE__, \ |
307 | 42.7k | __LINE__) |
308 | | |
309 | | /** Copy B over A, whose capacity is S bytes including the NUL. ABORTS if B |
310 | | does not fit. */ |
311 | | #define strlcpybuff(A, B, S) \ |
312 | 0 | strcpy_safe_(A, S, B, HTS_SIZEOF_SRC_(B), \ |
313 | 0 | "overflow while copying '" #B "' to '" #A "'", __FILE__, \ |
314 | 0 | __LINE__) |
315 | | |
316 | | /** strlen of s, capped at maxlen. POSIX strnlen is hidden from a strict-ISO |
317 | | consumer (__STRICT_ANSI__) and absent on a few targets, so call this. */ |
318 | | static HTS_INLINE HTS_UNUSED size_t htssafe_strnlen_(const char *s, |
319 | 436k | size_t maxlen) { |
320 | 436k | #if (defined(_WIN32) || (defined(HAVE_STRNLEN) && !defined(__STRICT_ANSI__))) |
321 | 436k | return strnlen(s, maxlen); |
322 | | #else |
323 | | size_t i; |
324 | | for (i = 0; i < maxlen && s[i] != '\0'; i++) |
325 | | ; |
326 | | return i; |
327 | | #endif |
328 | 436k | } Unexecuted instantiation: fuzz-cachendx.c:htssafe_strnlen_ Line | Count | Source | 319 | 361k | size_t maxlen) { | 320 | 361k | #if (defined(_WIN32) || (defined(HAVE_STRNLEN) && !defined(__STRICT_ANSI__))) | 321 | 361k | return strnlen(s, maxlen); | 322 | | #else | 323 | | size_t i; | 324 | | for (i = 0; i < maxlen && s[i] != '\0'; i++) | 325 | | ; | 326 | | return i; | 327 | | #endif | 328 | 361k | } |
htsdate.c:htssafe_strnlen_ Line | Count | Source | 319 | 75.4k | size_t maxlen) { | 320 | 75.4k | #if (defined(_WIN32) || (defined(HAVE_STRNLEN) && !defined(__STRICT_ANSI__))) | 321 | 75.4k | return strnlen(s, maxlen); | 322 | | #else | 323 | | size_t i; | 324 | | for (i = 0; i < maxlen && s[i] != '\0'; i++) | 325 | | ; | 326 | | return i; | 327 | | #endif | 328 | 75.4k | } |
Unexecuted instantiation: htslib.c:htssafe_strnlen_ Unexecuted instantiation: htsfetch.c:htssafe_strnlen_ Unexecuted instantiation: htspsl.c:htssafe_strnlen_ Unexecuted instantiation: htslines.c:htssafe_strnlen_ Unexecuted instantiation: htscore.c:htssafe_strnlen_ Unexecuted instantiation: htshash.c:htssafe_strnlen_ Unexecuted instantiation: htscache.c:htssafe_strnlen_ Unexecuted instantiation: htsback.c:htssafe_strnlen_ Unexecuted instantiation: htsftp.c:htssafe_strnlen_ Unexecuted instantiation: htsparse.c:htssafe_strnlen_ Unexecuted instantiation: htscmdline.c:htssafe_strnlen_ Unexecuted instantiation: htsfilters.c:htssafe_strnlen_ Unexecuted instantiation: htsname.c:htssafe_strnlen_ Unexecuted instantiation: htsrobots.c:htssafe_strnlen_ Unexecuted instantiation: htstools.c:htssafe_strnlen_ Unexecuted instantiation: htswizard.c:htssafe_strnlen_ Unexecuted instantiation: htsthread.c:htssafe_strnlen_ Unexecuted instantiation: htsindex.c:htssafe_strnlen_ Unexecuted instantiation: htsbauth.c:htssafe_strnlen_ Unexecuted instantiation: htscrashtest.c:htssafe_strnlen_ Unexecuted instantiation: htsmd5.c:htssafe_strnlen_ Unexecuted instantiation: htsnet.c:htssafe_strnlen_ Unexecuted instantiation: htscodec.c:htssafe_strnlen_ Unexecuted instantiation: htswarc.c:htssafe_strnlen_ Unexecuted instantiation: htschanges.c:htssafe_strnlen_ Unexecuted instantiation: htssinglefile.c:htssafe_strnlen_ Unexecuted instantiation: htssitemap.c:htssafe_strnlen_ Unexecuted instantiation: htsproxy.c:htssafe_strnlen_ Unexecuted instantiation: htszlib.c:htssafe_strnlen_ Unexecuted instantiation: htsconcat.c:htssafe_strnlen_ Unexecuted instantiation: htsmodules.c:htssafe_strnlen_ Unexecuted instantiation: htscharset.c:htssafe_strnlen_ Unexecuted instantiation: htsencoding.c:htssafe_strnlen_ Unexecuted instantiation: htsescape.c:htssafe_strnlen_ Unexecuted instantiation: htssniff.c:htssafe_strnlen_ |
329 | | |
330 | | /** strnlen() for the targets that lack it, so engine sources may call it. */ |
331 | | #if (!defined(_WIN32) && !defined(HAVE_STRNLEN)) |
332 | | |
333 | | static HTS_UNUSED size_t strnlen(const char *s, size_t maxlen) { |
334 | | return htssafe_strnlen_(s, maxlen); |
335 | | } |
336 | | #endif |
337 | | |
338 | | /** strlen of source, bounded by sizeof_source (its capacity, NUL included). |
339 | | Aborts if source is NULL or has no NUL within that capacity. The sentinel |
340 | | sizeof_source == (size_t)-1 means "capacity unknown", and falls back to the |
341 | | unbounded strlen (used when the source is a pointer, not an array). */ |
342 | | static HTS_INLINE HTS_UNUSED size_t strlen_safe_(const char *source, |
343 | | const size_t sizeof_source, |
344 | 555k | const char *file, int line) { |
345 | 555k | size_t size; |
346 | 555k | assertf_(source != NULL, file, line); |
347 | 555k | size = sizeof_source != (size_t) -1 ? htssafe_strnlen_(source, sizeof_source) |
348 | 555k | : strlen(source); |
349 | 555k | assertf_(size < sizeof_source, file, line); |
350 | 0 | return size; |
351 | 555k | } Unexecuted instantiation: fuzz-cachendx.c:strlen_safe_ Line | Count | Source | 344 | 404k | const char *file, int line) { | 345 | 404k | size_t size; | 346 | 404k | assertf_(source != NULL, file, line); | 347 | 404k | size = sizeof_source != (size_t) -1 ? htssafe_strnlen_(source, sizeof_source) | 348 | 404k | : strlen(source); | 349 | 404k | assertf_(size < sizeof_source, file, line); | 350 | 0 | return size; | 351 | 404k | } |
Line | Count | Source | 344 | 150k | const char *file, int line) { | 345 | 150k | size_t size; | 346 | 150k | assertf_(source != NULL, file, line); | 347 | 150k | size = sizeof_source != (size_t) -1 ? htssafe_strnlen_(source, sizeof_source) | 348 | 150k | : strlen(source); | 349 | 150k | assertf_(size < sizeof_source, file, line); | 350 | 0 | return size; | 351 | 150k | } |
Unexecuted instantiation: htslib.c:strlen_safe_ Unexecuted instantiation: htsfetch.c:strlen_safe_ Unexecuted instantiation: htspsl.c:strlen_safe_ Unexecuted instantiation: htslines.c:strlen_safe_ Unexecuted instantiation: htscore.c:strlen_safe_ Unexecuted instantiation: htshash.c:strlen_safe_ Unexecuted instantiation: htscache.c:strlen_safe_ Unexecuted instantiation: htsback.c:strlen_safe_ Unexecuted instantiation: htsftp.c:strlen_safe_ Unexecuted instantiation: htsparse.c:strlen_safe_ Unexecuted instantiation: htscmdline.c:strlen_safe_ Unexecuted instantiation: htsfilters.c:strlen_safe_ Unexecuted instantiation: htsname.c:strlen_safe_ Unexecuted instantiation: htsrobots.c:strlen_safe_ Unexecuted instantiation: htstools.c:strlen_safe_ Unexecuted instantiation: htswizard.c:strlen_safe_ Unexecuted instantiation: htsthread.c:strlen_safe_ Unexecuted instantiation: htsindex.c:strlen_safe_ Unexecuted instantiation: htsbauth.c:strlen_safe_ Unexecuted instantiation: htscrashtest.c:strlen_safe_ Unexecuted instantiation: htsmd5.c:strlen_safe_ Unexecuted instantiation: htsnet.c:strlen_safe_ Unexecuted instantiation: htscodec.c:strlen_safe_ Unexecuted instantiation: htswarc.c:strlen_safe_ Unexecuted instantiation: htschanges.c:strlen_safe_ Unexecuted instantiation: htssinglefile.c:strlen_safe_ Unexecuted instantiation: htssitemap.c:strlen_safe_ Unexecuted instantiation: htsproxy.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: htsescape.c:strlen_safe_ Unexecuted instantiation: htssniff.c:strlen_safe_ |
352 | | |
353 | | /** Core bounded append behind the buff() family. Appends min(strlen(source), |
354 | | n) bytes of source onto dest. sizeof_dest is dest's total capacity (NUL |
355 | | included), and sizeof_source is source's capacity or (size_t)-1 if unknown. |
356 | | Aborts if the result plus its NUL would not fit sizeof_dest, so this NEVER |
357 | | truncates. Always NUL-terminates on success, and returns dest. */ |
358 | | static HTS_INLINE HTS_UNUSED char * |
359 | | strncat_safe_(char *const dest, const size_t sizeof_dest, |
360 | | const char *const source, const size_t sizeof_source, |
361 | 277k | const size_t n, const char *exp, const char *file, int line) { |
362 | 277k | const size_t source_len = strlen_safe_(source, sizeof_source, file, line); |
363 | 277k | const size_t dest_len = strlen_safe_(dest, sizeof_dest, file, line); |
364 | | /* note: "size_t is an unsigned integral type" ((size_t) -1 is positive) */ |
365 | 277k | const size_t source_copy = source_len <= n ? source_len : n; |
366 | 277k | const size_t dest_final_len = dest_len + source_copy; |
367 | 277k | assertf__(dest_final_len < sizeof_dest, exp, file, line); |
368 | 0 | memcpy(dest + dest_len, source, source_copy); |
369 | 277k | dest[dest_final_len] = '\0'; |
370 | 277k | return dest; |
371 | 277k | } Unexecuted instantiation: fuzz-cachendx.c:strncat_safe_ Line | Count | Source | 361 | 202k | const size_t n, const char *exp, const char *file, int line) { | 362 | 202k | const size_t source_len = strlen_safe_(source, sizeof_source, file, line); | 363 | 202k | const size_t dest_len = strlen_safe_(dest, sizeof_dest, file, line); | 364 | | /* note: "size_t is an unsigned integral type" ((size_t) -1 is positive) */ | 365 | 202k | const size_t source_copy = source_len <= n ? source_len : n; | 366 | 202k | const size_t dest_final_len = dest_len + source_copy; | 367 | 202k | assertf__(dest_final_len < sizeof_dest, exp, file, line); | 368 | 0 | memcpy(dest + dest_len, source, source_copy); | 369 | 202k | dest[dest_final_len] = '\0'; | 370 | 202k | return dest; | 371 | 202k | } |
Line | Count | Source | 361 | 75.4k | const size_t n, const char *exp, const char *file, int line) { | 362 | 75.4k | const size_t source_len = strlen_safe_(source, sizeof_source, file, line); | 363 | 75.4k | const size_t dest_len = strlen_safe_(dest, sizeof_dest, file, line); | 364 | | /* note: "size_t is an unsigned integral type" ((size_t) -1 is positive) */ | 365 | 75.4k | const size_t source_copy = source_len <= n ? source_len : n; | 366 | 75.4k | const size_t dest_final_len = dest_len + source_copy; | 367 | 75.4k | assertf__(dest_final_len < sizeof_dest, exp, file, line); | 368 | 0 | memcpy(dest + dest_len, source, source_copy); | 369 | 75.4k | dest[dest_final_len] = '\0'; | 370 | 75.4k | return dest; | 371 | 75.4k | } |
Unexecuted instantiation: htslib.c:strncat_safe_ Unexecuted instantiation: htsfetch.c:strncat_safe_ Unexecuted instantiation: htspsl.c:strncat_safe_ Unexecuted instantiation: htslines.c:strncat_safe_ Unexecuted instantiation: htscore.c:strncat_safe_ Unexecuted instantiation: htshash.c:strncat_safe_ Unexecuted instantiation: htscache.c:strncat_safe_ Unexecuted instantiation: htsback.c:strncat_safe_ Unexecuted instantiation: htsftp.c:strncat_safe_ Unexecuted instantiation: htsparse.c:strncat_safe_ Unexecuted instantiation: htscmdline.c:strncat_safe_ Unexecuted instantiation: htsfilters.c:strncat_safe_ Unexecuted instantiation: htsname.c:strncat_safe_ Unexecuted instantiation: htsrobots.c:strncat_safe_ Unexecuted instantiation: htstools.c:strncat_safe_ Unexecuted instantiation: htswizard.c:strncat_safe_ Unexecuted instantiation: htsthread.c:strncat_safe_ Unexecuted instantiation: htsindex.c:strncat_safe_ Unexecuted instantiation: htsbauth.c:strncat_safe_ Unexecuted instantiation: htscrashtest.c:strncat_safe_ Unexecuted instantiation: htsmd5.c:strncat_safe_ Unexecuted instantiation: htsnet.c:strncat_safe_ Unexecuted instantiation: htscodec.c:strncat_safe_ Unexecuted instantiation: htswarc.c:strncat_safe_ Unexecuted instantiation: htschanges.c:strncat_safe_ Unexecuted instantiation: htssinglefile.c:strncat_safe_ Unexecuted instantiation: htssitemap.c:strncat_safe_ Unexecuted instantiation: htsproxy.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: htsescape.c:strncat_safe_ Unexecuted instantiation: htssniff.c:strncat_safe_ |
372 | | |
373 | | /** Core bounded copy behind the buff() family. sizeof_dest is dest's total |
374 | | capacity (NUL included). Aborts rather than truncating if source plus its |
375 | | NUL would not fit, and returns dest. */ |
376 | | static HTS_INLINE HTS_UNUSED char * |
377 | | strcpy_safe_(char *const dest, const size_t sizeof_dest, |
378 | | const char *const source, const size_t sizeof_source, |
379 | 150k | const char *exp, const char *file, int line) { |
380 | 150k | assertf_(sizeof_dest != 0, file, line); |
381 | 0 | dest[0] = '\0'; |
382 | 150k | return strncat_safe_(dest, sizeof_dest, source, sizeof_source, (size_t) -1, |
383 | 150k | exp, file, line); |
384 | 150k | } Unexecuted instantiation: fuzz-cachendx.c:strcpy_safe_ Line | Count | Source | 379 | 106k | const char *exp, const char *file, int line) { | 380 | 106k | assertf_(sizeof_dest != 0, file, line); | 381 | 0 | dest[0] = '\0'; | 382 | 106k | return strncat_safe_(dest, sizeof_dest, source, sizeof_source, (size_t) -1, | 383 | 106k | exp, file, line); | 384 | 106k | } |
Line | Count | Source | 379 | 43.1k | const char *exp, const char *file, int line) { | 380 | 43.1k | assertf_(sizeof_dest != 0, file, line); | 381 | 0 | dest[0] = '\0'; | 382 | 43.1k | return strncat_safe_(dest, sizeof_dest, source, sizeof_source, (size_t) -1, | 383 | 43.1k | exp, file, line); | 384 | 43.1k | } |
Unexecuted instantiation: htslib.c:strcpy_safe_ Unexecuted instantiation: htsfetch.c:strcpy_safe_ Unexecuted instantiation: htspsl.c:strcpy_safe_ Unexecuted instantiation: htslines.c:strcpy_safe_ Unexecuted instantiation: htscore.c:strcpy_safe_ Unexecuted instantiation: htshash.c:strcpy_safe_ Unexecuted instantiation: htscache.c:strcpy_safe_ Unexecuted instantiation: htsback.c:strcpy_safe_ Unexecuted instantiation: htsftp.c:strcpy_safe_ Unexecuted instantiation: htsparse.c:strcpy_safe_ Unexecuted instantiation: htscmdline.c:strcpy_safe_ Unexecuted instantiation: htsfilters.c:strcpy_safe_ Unexecuted instantiation: htsname.c:strcpy_safe_ Unexecuted instantiation: htsrobots.c:strcpy_safe_ Unexecuted instantiation: htstools.c:strcpy_safe_ Unexecuted instantiation: htswizard.c:strcpy_safe_ Unexecuted instantiation: htsthread.c:strcpy_safe_ Unexecuted instantiation: htsindex.c:strcpy_safe_ Unexecuted instantiation: htsbauth.c:strcpy_safe_ Unexecuted instantiation: htscrashtest.c:strcpy_safe_ Unexecuted instantiation: htsmd5.c:strcpy_safe_ Unexecuted instantiation: htsnet.c:strcpy_safe_ Unexecuted instantiation: htscodec.c:strcpy_safe_ Unexecuted instantiation: htswarc.c:strcpy_safe_ Unexecuted instantiation: htschanges.c:strcpy_safe_ Unexecuted instantiation: htssinglefile.c:strcpy_safe_ Unexecuted instantiation: htssitemap.c:strcpy_safe_ Unexecuted instantiation: htsproxy.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: htsescape.c:strcpy_safe_ Unexecuted instantiation: htssniff.c:strcpy_safe_ |
385 | | |
386 | | /** |
387 | | * htsbuff: a non-owning bounded string builder over a fixed buffer. |
388 | | * |
389 | | * Use it instead of a hand-rolled cursor when appending repeatedly to a buffer |
390 | | * of known capacity. It does not own the buffer, which must outlive it. Every |
391 | | * append ABORTS on overflow like the *_safe_ helpers, so do not build remote |
392 | | * text with it. Create one with htsbuff_array() for an in-scope array or |
393 | | * htsbuff_ptr() for a pointer of known capacity, and read the result back with |
394 | | * htsbuff_str(). |
395 | | */ |
396 | | typedef struct { |
397 | | char *buf; /**< backing buffer, kept NUL-terminated */ |
398 | | size_t cap; /**< total capacity of buf, including the NUL */ |
399 | | size_t len; /**< current length, excluding the NUL */ |
400 | | } htsbuff; |
401 | | |
402 | | /** Builder over buf, whose capacity is cap bytes including the NUL. Empties |
403 | | buf, and aborts if cap is 0. */ |
404 | 0 | static HTS_INLINE HTS_UNUSED htsbuff htsbuff_ptr_(char *buf, size_t cap) { |
405 | 0 | htsbuff b; |
406 | 0 | b.buf = buf; |
407 | 0 | b.cap = cap; |
408 | 0 | b.len = 0; |
409 | 0 | assertf(cap != 0); |
410 | 0 | buf[0] = '\0'; |
411 | 0 | return b; |
412 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_ptr_ Unexecuted instantiation: store.c:htsbuff_ptr_ Unexecuted instantiation: htsdate.c:htsbuff_ptr_ Unexecuted instantiation: htslib.c:htsbuff_ptr_ Unexecuted instantiation: htsfetch.c:htsbuff_ptr_ Unexecuted instantiation: htspsl.c:htsbuff_ptr_ Unexecuted instantiation: htslines.c:htsbuff_ptr_ Unexecuted instantiation: htscore.c:htsbuff_ptr_ Unexecuted instantiation: htshash.c:htsbuff_ptr_ Unexecuted instantiation: htscache.c:htsbuff_ptr_ Unexecuted instantiation: htsback.c:htsbuff_ptr_ Unexecuted instantiation: htsftp.c:htsbuff_ptr_ Unexecuted instantiation: htsparse.c:htsbuff_ptr_ Unexecuted instantiation: htscmdline.c:htsbuff_ptr_ Unexecuted instantiation: htsfilters.c:htsbuff_ptr_ Unexecuted instantiation: htsname.c:htsbuff_ptr_ Unexecuted instantiation: htsrobots.c:htsbuff_ptr_ Unexecuted instantiation: htstools.c:htsbuff_ptr_ Unexecuted instantiation: htswizard.c:htsbuff_ptr_ Unexecuted instantiation: htsthread.c:htsbuff_ptr_ Unexecuted instantiation: htsindex.c:htsbuff_ptr_ Unexecuted instantiation: htsbauth.c:htsbuff_ptr_ Unexecuted instantiation: htscrashtest.c:htsbuff_ptr_ Unexecuted instantiation: htsmd5.c:htsbuff_ptr_ Unexecuted instantiation: htsnet.c:htsbuff_ptr_ Unexecuted instantiation: htscodec.c:htsbuff_ptr_ Unexecuted instantiation: htswarc.c:htsbuff_ptr_ Unexecuted instantiation: htschanges.c:htsbuff_ptr_ Unexecuted instantiation: htssinglefile.c:htsbuff_ptr_ Unexecuted instantiation: htssitemap.c:htsbuff_ptr_ Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_ptr_ Unexecuted instantiation: htssniff.c:htsbuff_ptr_ |
413 | | |
414 | | /** |
415 | | * Builder over the in-scope array ARR (capacity = sizeof(ARR)). |
416 | | * On GCC/Clang this rejects a non-array (e.g. a char* pointer), whose sizeof |
417 | | * would be the pointer size and silently wrong; use htsbuff_ptr() for pointers. |
418 | | * On other compilers there is no such guard, so pass only true arrays there. |
419 | | */ |
420 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
421 | | |
422 | | /** It evaluates to 0 for an array, and fails to compile for a pointer. */ |
423 | | #define htsbuff_must_be_array_(A) \ |
424 | 4.10k | (sizeof(char[1 - 2 * !!__builtin_types_compatible_p(__typeof__(A), \ |
425 | 4.10k | __typeof__(&(A)[0]))]) - \ |
426 | 4.10k | 1) |
427 | | |
428 | | #define htsbuff_array(ARR) \ |
429 | 0 | htsbuff_ptr_((ARR), sizeof(ARR) + htsbuff_must_be_array_(ARR)) |
430 | | #else |
431 | | #define htsbuff_array(ARR) htsbuff_ptr_((ARR), sizeof(ARR)) |
432 | | #endif |
433 | | /** Builder over pointer P of known capacity N (N includes the NUL). */ |
434 | 0 | #define htsbuff_ptr(P, N) htsbuff_ptr_((P), (N)) |
435 | | |
436 | | /** Append at most n characters of s (stopping at its NUL). Aborts on overflow. |
437 | | */ |
438 | | static HTS_INLINE HTS_UNUSED void htsbuff_catn(htsbuff *b, const char *s, |
439 | 0 | size_t n) { |
440 | | /* the (size_t)-1 "no limit" sentinel would reach strnlen as a bound past |
441 | | PTRDIFF_MAX */ |
442 | 0 | const size_t add = n != (size_t) -1 ? htssafe_strnlen_(s, n) : strlen(s); |
443 | | /* Overflow-safe: keep the (potentially huge) 'add' alone on one side. The |
444 | | maintained invariant len < cap makes 'cap - len' >= 1 (no underflow), so |
445 | | 'add < cap - len' cannot wrap the way 'len + add < cap' could. */ |
446 | 0 | assertf__(add < b->cap - b->len, "htsbuff append overflow", __FILE__, |
447 | 0 | __LINE__); |
448 | 0 | memcpy(b->buf + b->len, s, add); |
449 | 0 | b->len += add; |
450 | 0 | b->buf[b->len] = '\0'; |
451 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_catn Unexecuted instantiation: store.c:htsbuff_catn Unexecuted instantiation: htsdate.c:htsbuff_catn Unexecuted instantiation: htslib.c:htsbuff_catn Unexecuted instantiation: htsfetch.c:htsbuff_catn Unexecuted instantiation: htspsl.c:htsbuff_catn Unexecuted instantiation: htslines.c:htsbuff_catn Unexecuted instantiation: htscore.c:htsbuff_catn Unexecuted instantiation: htshash.c:htsbuff_catn Unexecuted instantiation: htscache.c:htsbuff_catn Unexecuted instantiation: htsback.c:htsbuff_catn Unexecuted instantiation: htsftp.c:htsbuff_catn Unexecuted instantiation: htsparse.c:htsbuff_catn Unexecuted instantiation: htscmdline.c:htsbuff_catn Unexecuted instantiation: htsfilters.c:htsbuff_catn Unexecuted instantiation: htsname.c:htsbuff_catn Unexecuted instantiation: htsrobots.c:htsbuff_catn Unexecuted instantiation: htstools.c:htsbuff_catn Unexecuted instantiation: htswizard.c:htsbuff_catn Unexecuted instantiation: htsthread.c:htsbuff_catn Unexecuted instantiation: htsindex.c:htsbuff_catn Unexecuted instantiation: htsbauth.c:htsbuff_catn Unexecuted instantiation: htscrashtest.c:htsbuff_catn Unexecuted instantiation: htsmd5.c:htsbuff_catn Unexecuted instantiation: htsnet.c:htsbuff_catn Unexecuted instantiation: htscodec.c:htsbuff_catn Unexecuted instantiation: htswarc.c:htsbuff_catn Unexecuted instantiation: htschanges.c:htsbuff_catn Unexecuted instantiation: htssinglefile.c:htsbuff_catn Unexecuted instantiation: htssitemap.c:htsbuff_catn Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_catn Unexecuted instantiation: htssniff.c:htsbuff_catn |
452 | | |
453 | | /** Append s. Aborts on overflow. */ |
454 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_cat(htsbuff *b, const char *s) { |
455 | 0 | htsbuff_catn(b, s, (size_t) -1); |
456 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_cat Unexecuted instantiation: store.c:htsbuff_cat Unexecuted instantiation: htsdate.c:htsbuff_cat Unexecuted instantiation: htslib.c:htsbuff_cat Unexecuted instantiation: htsfetch.c:htsbuff_cat Unexecuted instantiation: htspsl.c:htsbuff_cat Unexecuted instantiation: htslines.c:htsbuff_cat Unexecuted instantiation: htscore.c:htsbuff_cat Unexecuted instantiation: htshash.c:htsbuff_cat Unexecuted instantiation: htscache.c:htsbuff_cat Unexecuted instantiation: htsback.c:htsbuff_cat Unexecuted instantiation: htsftp.c:htsbuff_cat Unexecuted instantiation: htsparse.c:htsbuff_cat Unexecuted instantiation: htscmdline.c:htsbuff_cat Unexecuted instantiation: htsfilters.c:htsbuff_cat Unexecuted instantiation: htsname.c:htsbuff_cat Unexecuted instantiation: htsrobots.c:htsbuff_cat Unexecuted instantiation: htstools.c:htsbuff_cat Unexecuted instantiation: htswizard.c:htsbuff_cat Unexecuted instantiation: htsthread.c:htsbuff_cat Unexecuted instantiation: htsindex.c:htsbuff_cat Unexecuted instantiation: htsbauth.c:htsbuff_cat Unexecuted instantiation: htscrashtest.c:htsbuff_cat Unexecuted instantiation: htsmd5.c:htsbuff_cat Unexecuted instantiation: htsnet.c:htsbuff_cat Unexecuted instantiation: htscodec.c:htsbuff_cat Unexecuted instantiation: htswarc.c:htsbuff_cat Unexecuted instantiation: htschanges.c:htsbuff_cat Unexecuted instantiation: htssinglefile.c:htsbuff_cat Unexecuted instantiation: htssitemap.c:htsbuff_cat Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_cat Unexecuted instantiation: htssniff.c:htsbuff_cat |
457 | | |
458 | | /** Append a single character (including '\0' as data). Aborts on overflow. */ |
459 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_catc(htsbuff *b, char c) { |
460 | 0 | assertf__(1 < b->cap - b->len, "htsbuff append overflow", __FILE__, __LINE__); |
461 | 0 | b->buf[b->len++] = c; |
462 | 0 | b->buf[b->len] = '\0'; |
463 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_catc Unexecuted instantiation: store.c:htsbuff_catc Unexecuted instantiation: htsdate.c:htsbuff_catc Unexecuted instantiation: htslib.c:htsbuff_catc Unexecuted instantiation: htsfetch.c:htsbuff_catc Unexecuted instantiation: htspsl.c:htsbuff_catc Unexecuted instantiation: htslines.c:htsbuff_catc Unexecuted instantiation: htscore.c:htsbuff_catc Unexecuted instantiation: htshash.c:htsbuff_catc Unexecuted instantiation: htscache.c:htsbuff_catc Unexecuted instantiation: htsback.c:htsbuff_catc Unexecuted instantiation: htsftp.c:htsbuff_catc Unexecuted instantiation: htsparse.c:htsbuff_catc Unexecuted instantiation: htscmdline.c:htsbuff_catc Unexecuted instantiation: htsfilters.c:htsbuff_catc Unexecuted instantiation: htsname.c:htsbuff_catc Unexecuted instantiation: htsrobots.c:htsbuff_catc Unexecuted instantiation: htstools.c:htsbuff_catc Unexecuted instantiation: htswizard.c:htsbuff_catc Unexecuted instantiation: htsthread.c:htsbuff_catc Unexecuted instantiation: htsindex.c:htsbuff_catc Unexecuted instantiation: htsbauth.c:htsbuff_catc Unexecuted instantiation: htscrashtest.c:htsbuff_catc Unexecuted instantiation: htsmd5.c:htsbuff_catc Unexecuted instantiation: htsnet.c:htsbuff_catc Unexecuted instantiation: htscodec.c:htsbuff_catc Unexecuted instantiation: htswarc.c:htsbuff_catc Unexecuted instantiation: htschanges.c:htsbuff_catc Unexecuted instantiation: htssinglefile.c:htsbuff_catc Unexecuted instantiation: htssitemap.c:htsbuff_catc Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_catc Unexecuted instantiation: htssniff.c:htsbuff_catc |
464 | | |
465 | | /** Reset content to s. Aborts on overflow. */ |
466 | 0 | static HTS_INLINE HTS_UNUSED void htsbuff_cpy(htsbuff *b, const char *s) { |
467 | 0 | b->len = 0; |
468 | 0 | htsbuff_catn(b, s, (size_t) -1); |
469 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_cpy Unexecuted instantiation: store.c:htsbuff_cpy Unexecuted instantiation: htsdate.c:htsbuff_cpy Unexecuted instantiation: htslib.c:htsbuff_cpy Unexecuted instantiation: htsfetch.c:htsbuff_cpy Unexecuted instantiation: htspsl.c:htsbuff_cpy Unexecuted instantiation: htslines.c:htsbuff_cpy Unexecuted instantiation: htscore.c:htsbuff_cpy Unexecuted instantiation: htshash.c:htsbuff_cpy Unexecuted instantiation: htscache.c:htsbuff_cpy Unexecuted instantiation: htsback.c:htsbuff_cpy Unexecuted instantiation: htsftp.c:htsbuff_cpy Unexecuted instantiation: htsparse.c:htsbuff_cpy Unexecuted instantiation: htscmdline.c:htsbuff_cpy Unexecuted instantiation: htsfilters.c:htsbuff_cpy Unexecuted instantiation: htsname.c:htsbuff_cpy Unexecuted instantiation: htsrobots.c:htsbuff_cpy Unexecuted instantiation: htstools.c:htsbuff_cpy Unexecuted instantiation: htswizard.c:htsbuff_cpy Unexecuted instantiation: htsthread.c:htsbuff_cpy Unexecuted instantiation: htsindex.c:htsbuff_cpy Unexecuted instantiation: htsbauth.c:htsbuff_cpy Unexecuted instantiation: htscrashtest.c:htsbuff_cpy Unexecuted instantiation: htsmd5.c:htsbuff_cpy Unexecuted instantiation: htsnet.c:htsbuff_cpy Unexecuted instantiation: htscodec.c:htsbuff_cpy Unexecuted instantiation: htswarc.c:htsbuff_cpy Unexecuted instantiation: htschanges.c:htsbuff_cpy Unexecuted instantiation: htssinglefile.c:htsbuff_cpy Unexecuted instantiation: htssitemap.c:htsbuff_cpy Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_cpy Unexecuted instantiation: htssniff.c:htsbuff_cpy |
470 | | |
471 | | /** Current NUL-terminated content. */ |
472 | 0 | static HTS_INLINE HTS_UNUSED const char *htsbuff_str(const htsbuff *b) { |
473 | 0 | return b->buf; |
474 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:htsbuff_str Unexecuted instantiation: store.c:htsbuff_str Unexecuted instantiation: htsdate.c:htsbuff_str Unexecuted instantiation: htslib.c:htsbuff_str Unexecuted instantiation: htsfetch.c:htsbuff_str Unexecuted instantiation: htspsl.c:htsbuff_str Unexecuted instantiation: htslines.c:htsbuff_str Unexecuted instantiation: htscore.c:htsbuff_str Unexecuted instantiation: htshash.c:htsbuff_str Unexecuted instantiation: htscache.c:htsbuff_str Unexecuted instantiation: htsback.c:htsbuff_str Unexecuted instantiation: htsftp.c:htsbuff_str Unexecuted instantiation: htsparse.c:htsbuff_str Unexecuted instantiation: htscmdline.c:htsbuff_str Unexecuted instantiation: htsfilters.c:htsbuff_str Unexecuted instantiation: htsname.c:htsbuff_str Unexecuted instantiation: htsrobots.c:htsbuff_str Unexecuted instantiation: htstools.c:htsbuff_str Unexecuted instantiation: htswizard.c:htsbuff_str Unexecuted instantiation: htsthread.c:htsbuff_str Unexecuted instantiation: htsindex.c:htsbuff_str Unexecuted instantiation: htsbauth.c:htsbuff_str Unexecuted instantiation: htscrashtest.c:htsbuff_str Unexecuted instantiation: htsmd5.c:htsbuff_str Unexecuted instantiation: htsnet.c:htsbuff_str Unexecuted instantiation: htscodec.c:htsbuff_str Unexecuted instantiation: htswarc.c:htsbuff_str Unexecuted instantiation: htschanges.c:htsbuff_str Unexecuted instantiation: htssinglefile.c:htsbuff_str Unexecuted instantiation: htssitemap.c:htsbuff_str Unexecuted instantiation: htsproxy.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: htsescape.c:htsbuff_str Unexecuted instantiation: htssniff.c:htsbuff_str |
475 | | |
476 | | /** |
477 | | * Copy src into dest (capacity size, NUL included), truncating to fit and |
478 | | * always NUL-terminating. Unlike strlcpybuff() it does not abort on overflow, |
479 | | * so it suits a value read back from a cache, a header or the wire, where |
480 | | * refusing the whole record is worse than keeping a clipped one. Returns |
481 | | * HTS_TRUE if it all fit; callers that clip on purpose ignore that, so it is |
482 | | * not HTS_CHECK_RESULT. |
483 | | */ |
484 | | static HTS_INLINE HTS_UNUSED hts_boolean strclipbuff(char *dest, size_t size, |
485 | 0 | const char *src) { |
486 | 0 | size_t len, copy; |
487 | |
|
488 | 0 | assertf(dest != NULL && src != NULL && size != 0); |
489 | 0 | len = strlen(src); |
490 | 0 | copy = len < size ? len : size - 1; |
491 | 0 | memcpy(dest, src, copy); |
492 | 0 | dest[copy] = '\0'; |
493 | 0 | return copy == len ? HTS_TRUE : HTS_FALSE; |
494 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:strclipbuff Unexecuted instantiation: store.c:strclipbuff Unexecuted instantiation: htsdate.c:strclipbuff Unexecuted instantiation: htslib.c:strclipbuff Unexecuted instantiation: htsfetch.c:strclipbuff Unexecuted instantiation: htspsl.c:strclipbuff Unexecuted instantiation: htslines.c:strclipbuff Unexecuted instantiation: htscore.c:strclipbuff Unexecuted instantiation: htshash.c:strclipbuff Unexecuted instantiation: htscache.c:strclipbuff Unexecuted instantiation: htsback.c:strclipbuff Unexecuted instantiation: htsftp.c:strclipbuff Unexecuted instantiation: htsparse.c:strclipbuff Unexecuted instantiation: htscmdline.c:strclipbuff Unexecuted instantiation: htsfilters.c:strclipbuff Unexecuted instantiation: htsname.c:strclipbuff Unexecuted instantiation: htsrobots.c:strclipbuff Unexecuted instantiation: htstools.c:strclipbuff Unexecuted instantiation: htswizard.c:strclipbuff Unexecuted instantiation: htsthread.c:strclipbuff Unexecuted instantiation: htsindex.c:strclipbuff Unexecuted instantiation: htsbauth.c:strclipbuff Unexecuted instantiation: htscrashtest.c:strclipbuff Unexecuted instantiation: htsmd5.c:strclipbuff Unexecuted instantiation: htsnet.c:strclipbuff Unexecuted instantiation: htscodec.c:strclipbuff Unexecuted instantiation: htswarc.c:strclipbuff Unexecuted instantiation: htschanges.c:strclipbuff Unexecuted instantiation: htssinglefile.c:strclipbuff Unexecuted instantiation: htssitemap.c:strclipbuff Unexecuted instantiation: htsproxy.c:strclipbuff Unexecuted instantiation: htszlib.c:strclipbuff Unexecuted instantiation: htsconcat.c:strclipbuff Unexecuted instantiation: htsmodules.c:strclipbuff Unexecuted instantiation: htscharset.c:strclipbuff Unexecuted instantiation: htsencoding.c:strclipbuff Unexecuted instantiation: htsescape.c:strclipbuff Unexecuted instantiation: htssniff.c:strclipbuff |
495 | | |
496 | | /* This header is installed, so the name carries the project prefix. */ |
497 | 2.24M | #define HTS_IS_PATH_SEP(c) ((c) == '/' || (c) == '\\') |
498 | | |
499 | | /** |
500 | | * True if path holds no ".." component, either separator counting. Lexical |
501 | | * only, so "a..b" is a name and no symlink is resolved. Use it on the |
502 | | * UNTRUSTED half of a path, never on the assembled one: the user's own -O may |
503 | | * legitimately start with "..". |
504 | | */ |
505 | | static HTS_INLINE HTS_UNUSED hts_boolean |
506 | 29.1k | hts_path_is_contained(const char *path) { |
507 | 29.1k | const char *s; |
508 | | |
509 | 77.7k | for (s = path; *s != '\0';) { |
510 | 85.5k | while (HTS_IS_PATH_SEP(*s)) { |
511 | 36.3k | s++; |
512 | 36.3k | } |
513 | 49.2k | if (s[0] == '.' && s[1] == '.' && (s[2] == '\0' || HTS_IS_PATH_SEP(s[2]))) { |
514 | 666 | return HTS_FALSE; |
515 | 666 | } |
516 | 2.17M | while (*s != '\0' && !HTS_IS_PATH_SEP(*s)) { |
517 | 2.12M | s++; |
518 | 2.12M | } |
519 | 48.5k | } |
520 | 28.5k | return HTS_TRUE; |
521 | 29.1k | } Unexecuted instantiation: fuzz-cachendx.c:hts_path_is_contained store.c:hts_path_is_contained Line | Count | Source | 506 | 29.1k | hts_path_is_contained(const char *path) { | 507 | 29.1k | const char *s; | 508 | | | 509 | 77.7k | for (s = path; *s != '\0';) { | 510 | 85.5k | while (HTS_IS_PATH_SEP(*s)) { | 511 | 36.3k | s++; | 512 | 36.3k | } | 513 | 49.2k | if (s[0] == '.' && s[1] == '.' && (s[2] == '\0' || HTS_IS_PATH_SEP(s[2]))) { | 514 | 666 | return HTS_FALSE; | 515 | 666 | } | 516 | 2.17M | while (*s != '\0' && !HTS_IS_PATH_SEP(*s)) { | 517 | 2.12M | s++; | 518 | 2.12M | } | 519 | 48.5k | } | 520 | 28.5k | return HTS_TRUE; | 521 | 29.1k | } |
Unexecuted instantiation: htsdate.c:hts_path_is_contained Unexecuted instantiation: htslib.c:hts_path_is_contained Unexecuted instantiation: htsfetch.c:hts_path_is_contained Unexecuted instantiation: htspsl.c:hts_path_is_contained Unexecuted instantiation: htslines.c:hts_path_is_contained Unexecuted instantiation: htscore.c:hts_path_is_contained Unexecuted instantiation: htshash.c:hts_path_is_contained Unexecuted instantiation: htscache.c:hts_path_is_contained Unexecuted instantiation: htsback.c:hts_path_is_contained Unexecuted instantiation: htsftp.c:hts_path_is_contained Unexecuted instantiation: htsparse.c:hts_path_is_contained Unexecuted instantiation: htscmdline.c:hts_path_is_contained Unexecuted instantiation: htsfilters.c:hts_path_is_contained Unexecuted instantiation: htsname.c:hts_path_is_contained Unexecuted instantiation: htsrobots.c:hts_path_is_contained Unexecuted instantiation: htstools.c:hts_path_is_contained Unexecuted instantiation: htswizard.c:hts_path_is_contained Unexecuted instantiation: htsthread.c:hts_path_is_contained Unexecuted instantiation: htsindex.c:hts_path_is_contained Unexecuted instantiation: htsbauth.c:hts_path_is_contained Unexecuted instantiation: htscrashtest.c:hts_path_is_contained Unexecuted instantiation: htsmd5.c:hts_path_is_contained Unexecuted instantiation: htsnet.c:hts_path_is_contained Unexecuted instantiation: htscodec.c:hts_path_is_contained Unexecuted instantiation: htswarc.c:hts_path_is_contained Unexecuted instantiation: htschanges.c:hts_path_is_contained Unexecuted instantiation: htssinglefile.c:hts_path_is_contained Unexecuted instantiation: htssitemap.c:hts_path_is_contained Unexecuted instantiation: htsproxy.c:hts_path_is_contained Unexecuted instantiation: htszlib.c:hts_path_is_contained Unexecuted instantiation: htsconcat.c:hts_path_is_contained Unexecuted instantiation: htsmodules.c:hts_path_is_contained Unexecuted instantiation: htscharset.c:hts_path_is_contained Unexecuted instantiation: htsencoding.c:hts_path_is_contained Unexecuted instantiation: htsescape.c:hts_path_is_contained Unexecuted instantiation: htssniff.c:hts_path_is_contained |
522 | | |
523 | | /** |
524 | | * True if path is a relative name that no ".." component can walk out of: what |
525 | | * a filename read back out of a cache has to be before it is joined to a root. |
526 | | * Refusing ".." alone is not enough, because with no -O that root is "" and an |
527 | | * absolute cached name is then used verbatim. Spelled as ProxyTrack's own |
528 | | * readers already spell it, plus the backslash Windows also takes. Letters are |
529 | | * ranged rather than isalpha() so this header needs no <ctype.h>. |
530 | | */ |
531 | | static HTS_INLINE HTS_UNUSED hts_boolean |
532 | 13.4k | hts_path_is_relative_contained(const char *path) { |
533 | 13.4k | if (HTS_IS_PATH_SEP(path[0])) { |
534 | 1.16k | return HTS_FALSE; |
535 | 1.16k | } |
536 | | /* a drive prefix names its own root, "c:rel" included */ |
537 | 12.2k | if (((path[0] >= 'A' && path[0] <= 'Z') || |
538 | 10.8k | (path[0] >= 'a' && path[0] <= 'z')) && |
539 | 4.09k | path[1] == ':') { |
540 | 232 | return HTS_FALSE; |
541 | 232 | } |
542 | 12.0k | return hts_path_is_contained(path); |
543 | 12.2k | } Unexecuted instantiation: fuzz-cachendx.c:hts_path_is_relative_contained store.c:hts_path_is_relative_contained Line | Count | Source | 532 | 13.4k | hts_path_is_relative_contained(const char *path) { | 533 | 13.4k | if (HTS_IS_PATH_SEP(path[0])) { | 534 | 1.16k | return HTS_FALSE; | 535 | 1.16k | } | 536 | | /* a drive prefix names its own root, "c:rel" included */ | 537 | 12.2k | if (((path[0] >= 'A' && path[0] <= 'Z') || | 538 | 10.8k | (path[0] >= 'a' && path[0] <= 'z')) && | 539 | 4.09k | path[1] == ':') { | 540 | 232 | return HTS_FALSE; | 541 | 232 | } | 542 | 12.0k | return hts_path_is_contained(path); | 543 | 12.2k | } |
Unexecuted instantiation: htsdate.c:hts_path_is_relative_contained Unexecuted instantiation: htslib.c:hts_path_is_relative_contained Unexecuted instantiation: htsfetch.c:hts_path_is_relative_contained Unexecuted instantiation: htspsl.c:hts_path_is_relative_contained Unexecuted instantiation: htslines.c:hts_path_is_relative_contained Unexecuted instantiation: htscore.c:hts_path_is_relative_contained Unexecuted instantiation: htshash.c:hts_path_is_relative_contained Unexecuted instantiation: htscache.c:hts_path_is_relative_contained Unexecuted instantiation: htsback.c:hts_path_is_relative_contained Unexecuted instantiation: htsftp.c:hts_path_is_relative_contained Unexecuted instantiation: htsparse.c:hts_path_is_relative_contained Unexecuted instantiation: htscmdline.c:hts_path_is_relative_contained Unexecuted instantiation: htsfilters.c:hts_path_is_relative_contained Unexecuted instantiation: htsname.c:hts_path_is_relative_contained Unexecuted instantiation: htsrobots.c:hts_path_is_relative_contained Unexecuted instantiation: htstools.c:hts_path_is_relative_contained Unexecuted instantiation: htswizard.c:hts_path_is_relative_contained Unexecuted instantiation: htsthread.c:hts_path_is_relative_contained Unexecuted instantiation: htsindex.c:hts_path_is_relative_contained Unexecuted instantiation: htsbauth.c:hts_path_is_relative_contained Unexecuted instantiation: htscrashtest.c:hts_path_is_relative_contained Unexecuted instantiation: htsmd5.c:hts_path_is_relative_contained Unexecuted instantiation: htsnet.c:hts_path_is_relative_contained Unexecuted instantiation: htscodec.c:hts_path_is_relative_contained Unexecuted instantiation: htswarc.c:hts_path_is_relative_contained Unexecuted instantiation: htschanges.c:hts_path_is_relative_contained Unexecuted instantiation: htssinglefile.c:hts_path_is_relative_contained Unexecuted instantiation: htssitemap.c:hts_path_is_relative_contained Unexecuted instantiation: htsproxy.c:hts_path_is_relative_contained Unexecuted instantiation: htszlib.c:hts_path_is_relative_contained Unexecuted instantiation: htsconcat.c:hts_path_is_relative_contained Unexecuted instantiation: htsmodules.c:hts_path_is_relative_contained Unexecuted instantiation: htscharset.c:hts_path_is_relative_contained Unexecuted instantiation: htsencoding.c:hts_path_is_relative_contained Unexecuted instantiation: htsescape.c:hts_path_is_relative_contained Unexecuted instantiation: htssniff.c:hts_path_is_relative_contained |
544 | | |
545 | | /** |
546 | | * Callers that deliberately ignore truncation use this instead of |
547 | | * slprintfbuff(), so it is not HTS_CHECK_RESULT. |
548 | | */ |
549 | | static HTS_INLINE HTS_UNUSED HTS_PRINTF_FUN(3, 0) hts_boolean |
550 | 64.5k | vslprintfbuff(char *dest, size_t size, const char *fmt, va_list args) { |
551 | 64.5k | int ret; |
552 | | |
553 | 64.5k | assertf(dest != NULL && size != 0); |
554 | | /* a vsnprintf failing outright may write nothing at all, leaving whatever |
555 | | the caller had on the stack for it to publish */ |
556 | 0 | dest[0] = '\0'; |
557 | 64.5k | ret = vsnprintf(dest, size, fmt, args); |
558 | | /* pre-C99 runtimes (msvcrt _vsnprintf) return -1 and do not terminate */ |
559 | 64.5k | dest[size - 1] = '\0'; |
560 | 64.5k | return ret >= 0 && (size_t) ret < size ? HTS_TRUE : HTS_FALSE; |
561 | 64.5k | } Unexecuted instantiation: fuzz-cachendx.c:vslprintfbuff Line | Count | Source | 550 | 64.5k | vslprintfbuff(char *dest, size_t size, const char *fmt, va_list args) { | 551 | 64.5k | int ret; | 552 | | | 553 | 64.5k | assertf(dest != NULL && size != 0); | 554 | | /* a vsnprintf failing outright may write nothing at all, leaving whatever | 555 | | the caller had on the stack for it to publish */ | 556 | 0 | dest[0] = '\0'; | 557 | 64.5k | ret = vsnprintf(dest, size, fmt, args); | 558 | | /* pre-C99 runtimes (msvcrt _vsnprintf) return -1 and do not terminate */ | 559 | 64.5k | dest[size - 1] = '\0'; | 560 | 64.5k | return ret >= 0 && (size_t) ret < size ? HTS_TRUE : HTS_FALSE; | 561 | 64.5k | } |
Unexecuted instantiation: htsdate.c:vslprintfbuff Unexecuted instantiation: htslib.c:vslprintfbuff Unexecuted instantiation: htsfetch.c:vslprintfbuff Unexecuted instantiation: htspsl.c:vslprintfbuff Unexecuted instantiation: htslines.c:vslprintfbuff Unexecuted instantiation: htscore.c:vslprintfbuff Unexecuted instantiation: htshash.c:vslprintfbuff Unexecuted instantiation: htscache.c:vslprintfbuff Unexecuted instantiation: htsback.c:vslprintfbuff Unexecuted instantiation: htsftp.c:vslprintfbuff Unexecuted instantiation: htsparse.c:vslprintfbuff Unexecuted instantiation: htscmdline.c:vslprintfbuff Unexecuted instantiation: htsfilters.c:vslprintfbuff Unexecuted instantiation: htsname.c:vslprintfbuff Unexecuted instantiation: htsrobots.c:vslprintfbuff Unexecuted instantiation: htstools.c:vslprintfbuff Unexecuted instantiation: htswizard.c:vslprintfbuff Unexecuted instantiation: htsthread.c:vslprintfbuff Unexecuted instantiation: htsindex.c:vslprintfbuff Unexecuted instantiation: htsbauth.c:vslprintfbuff Unexecuted instantiation: htscrashtest.c:vslprintfbuff Unexecuted instantiation: htsmd5.c:vslprintfbuff Unexecuted instantiation: htsnet.c:vslprintfbuff Unexecuted instantiation: htscodec.c:vslprintfbuff Unexecuted instantiation: htswarc.c:vslprintfbuff Unexecuted instantiation: htschanges.c:vslprintfbuff Unexecuted instantiation: htssinglefile.c:vslprintfbuff Unexecuted instantiation: htssitemap.c:vslprintfbuff Unexecuted instantiation: htsproxy.c:vslprintfbuff Unexecuted instantiation: htszlib.c:vslprintfbuff Unexecuted instantiation: htsconcat.c:vslprintfbuff Unexecuted instantiation: htsmodules.c:vslprintfbuff Unexecuted instantiation: htscharset.c:vslprintfbuff Unexecuted instantiation: htsencoding.c:vslprintfbuff Unexecuted instantiation: htsescape.c:vslprintfbuff Unexecuted instantiation: htssniff.c:vslprintfbuff |
562 | | |
563 | | /** |
564 | | * Formatted print into dest (capacity size, NUL included), truncating to fit |
565 | | * and always NUL-terminating. Returns HTS_TRUE if the whole output fit; the |
566 | | * result is the only truncation signal, so it must be acted on. Unlike |
567 | | * strcpybuff() it does not abort on overflow, so it suits text built from |
568 | | * remote input. |
569 | | */ |
570 | | static HTS_INLINE HTS_UNUSED HTS_CHECK_RESULT HTS_PRINTF_FUN(3, 4) hts_boolean |
571 | 59.0k | slprintfbuff(char *dest, size_t size, const char *fmt, ...) { |
572 | 59.0k | va_list args; |
573 | 59.0k | hts_boolean ret; |
574 | | |
575 | 59.0k | va_start(args, fmt); |
576 | 59.0k | ret = vslprintfbuff(dest, size, fmt, args); |
577 | 59.0k | va_end(args); |
578 | 59.0k | return ret; |
579 | 59.0k | } Unexecuted instantiation: fuzz-cachendx.c:slprintfbuff Line | Count | Source | 571 | 59.0k | slprintfbuff(char *dest, size_t size, const char *fmt, ...) { | 572 | 59.0k | va_list args; | 573 | 59.0k | hts_boolean ret; | 574 | | | 575 | 59.0k | va_start(args, fmt); | 576 | 59.0k | ret = vslprintfbuff(dest, size, fmt, args); | 577 | | va_end(args); | 578 | 59.0k | return ret; | 579 | 59.0k | } |
Unexecuted instantiation: htsdate.c:slprintfbuff Unexecuted instantiation: htslib.c:slprintfbuff Unexecuted instantiation: htsfetch.c:slprintfbuff Unexecuted instantiation: htspsl.c:slprintfbuff Unexecuted instantiation: htslines.c:slprintfbuff Unexecuted instantiation: htscore.c:slprintfbuff Unexecuted instantiation: htshash.c:slprintfbuff Unexecuted instantiation: htscache.c:slprintfbuff Unexecuted instantiation: htsback.c:slprintfbuff Unexecuted instantiation: htsftp.c:slprintfbuff Unexecuted instantiation: htsparse.c:slprintfbuff Unexecuted instantiation: htscmdline.c:slprintfbuff Unexecuted instantiation: htsfilters.c:slprintfbuff Unexecuted instantiation: htsname.c:slprintfbuff Unexecuted instantiation: htsrobots.c:slprintfbuff Unexecuted instantiation: htstools.c:slprintfbuff Unexecuted instantiation: htswizard.c:slprintfbuff Unexecuted instantiation: htsthread.c:slprintfbuff Unexecuted instantiation: htsindex.c:slprintfbuff Unexecuted instantiation: htsbauth.c:slprintfbuff Unexecuted instantiation: htscrashtest.c:slprintfbuff Unexecuted instantiation: htsmd5.c:slprintfbuff Unexecuted instantiation: htsnet.c:slprintfbuff Unexecuted instantiation: htscodec.c:slprintfbuff Unexecuted instantiation: htswarc.c:slprintfbuff Unexecuted instantiation: htschanges.c:slprintfbuff Unexecuted instantiation: htssinglefile.c:slprintfbuff Unexecuted instantiation: htssitemap.c:slprintfbuff Unexecuted instantiation: htsproxy.c:slprintfbuff Unexecuted instantiation: htszlib.c:slprintfbuff Unexecuted instantiation: htsconcat.c:slprintfbuff Unexecuted instantiation: htsmodules.c:slprintfbuff Unexecuted instantiation: htscharset.c:slprintfbuff Unexecuted instantiation: htsencoding.c:slprintfbuff Unexecuted instantiation: htsescape.c:slprintfbuff Unexecuted instantiation: htssniff.c:slprintfbuff |
580 | | |
581 | | /** |
582 | | * Append formatted text at dest[*used] (dest capacity size, NUL included), |
583 | | * advancing *used past it. All-or-nothing: on overflow dest is left as it was |
584 | | * and HTS_FALSE returned, so a record parsed back field by field never carries |
585 | | * a half-written one. *used must be below size. |
586 | | */ |
587 | | static HTS_INLINE HTS_UNUSED HTS_CHECK_RESULT HTS_PRINTF_FUN(4, 5) hts_boolean |
588 | | slcatprintfbuff(char *dest, size_t size, size_t *used, const char *fmt, |
589 | 0 | ...) { |
590 | 0 | va_list args; |
591 | 0 | hts_boolean fit; |
592 | |
|
593 | 0 | assertf(dest != NULL && used != NULL && *used < size); |
594 | 0 | va_start(args, fmt); |
595 | 0 | fit = vslprintfbuff(dest + *used, size - *used, fmt, args); |
596 | 0 | va_end(args); |
597 | 0 | if (fit) { |
598 | 0 | *used += strlen(dest + *used); |
599 | 0 | } else { |
600 | 0 | dest[*used] = '\0'; |
601 | 0 | } |
602 | 0 | return fit; |
603 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:slcatprintfbuff Unexecuted instantiation: store.c:slcatprintfbuff Unexecuted instantiation: htsdate.c:slcatprintfbuff Unexecuted instantiation: htslib.c:slcatprintfbuff Unexecuted instantiation: htsfetch.c:slcatprintfbuff Unexecuted instantiation: htspsl.c:slcatprintfbuff Unexecuted instantiation: htslines.c:slcatprintfbuff Unexecuted instantiation: htscore.c:slcatprintfbuff Unexecuted instantiation: htshash.c:slcatprintfbuff Unexecuted instantiation: htscache.c:slcatprintfbuff Unexecuted instantiation: htsback.c:slcatprintfbuff Unexecuted instantiation: htsftp.c:slcatprintfbuff Unexecuted instantiation: htsparse.c:slcatprintfbuff Unexecuted instantiation: htscmdline.c:slcatprintfbuff Unexecuted instantiation: htsfilters.c:slcatprintfbuff Unexecuted instantiation: htsname.c:slcatprintfbuff Unexecuted instantiation: htsrobots.c:slcatprintfbuff Unexecuted instantiation: htstools.c:slcatprintfbuff Unexecuted instantiation: htswizard.c:slcatprintfbuff Unexecuted instantiation: htsthread.c:slcatprintfbuff Unexecuted instantiation: htsindex.c:slcatprintfbuff Unexecuted instantiation: htsbauth.c:slcatprintfbuff Unexecuted instantiation: htscrashtest.c:slcatprintfbuff Unexecuted instantiation: htsmd5.c:slcatprintfbuff Unexecuted instantiation: htsnet.c:slcatprintfbuff Unexecuted instantiation: htscodec.c:slcatprintfbuff Unexecuted instantiation: htswarc.c:slcatprintfbuff Unexecuted instantiation: htschanges.c:slcatprintfbuff Unexecuted instantiation: htssinglefile.c:slcatprintfbuff Unexecuted instantiation: htssitemap.c:slcatprintfbuff Unexecuted instantiation: htsproxy.c:slcatprintfbuff Unexecuted instantiation: htszlib.c:slcatprintfbuff Unexecuted instantiation: htsconcat.c:slcatprintfbuff Unexecuted instantiation: htsmodules.c:slcatprintfbuff Unexecuted instantiation: htscharset.c:slcatprintfbuff Unexecuted instantiation: htsencoding.c:slcatprintfbuff Unexecuted instantiation: htsescape.c:slcatprintfbuff Unexecuted instantiation: htssniff.c:slcatprintfbuff |
604 | | |
605 | | /** |
606 | | * slprintfbuff() for diagnostics quoting remote or client text, which are |
607 | | * meant to be clipped: nothing to act on, hence not HTS_CHECK_RESULT. A (void) |
608 | | * cast on slprintfbuff() is no substitute, GCC warns through it. |
609 | | */ |
610 | | static HTS_INLINE HTS_UNUSED HTS_PRINTF_FUN(3, 4) void slprintfbuff_clip( |
611 | 5.54k | char *dest, size_t size, const char *fmt, ...) { |
612 | 5.54k | va_list args; |
613 | | |
614 | 5.54k | va_start(args, fmt); |
615 | 5.54k | (void) vslprintfbuff(dest, size, fmt, args); |
616 | 5.54k | va_end(args); |
617 | 5.54k | } Unexecuted instantiation: fuzz-cachendx.c:slprintfbuff_clip store.c:slprintfbuff_clip Line | Count | Source | 611 | 5.54k | char *dest, size_t size, const char *fmt, ...) { | 612 | 5.54k | va_list args; | 613 | | | 614 | 5.54k | va_start(args, fmt); | 615 | 5.54k | (void) vslprintfbuff(dest, size, fmt, args); | 616 | | va_end(args); | 617 | 5.54k | } |
Unexecuted instantiation: htsdate.c:slprintfbuff_clip Unexecuted instantiation: htslib.c:slprintfbuff_clip Unexecuted instantiation: htsfetch.c:slprintfbuff_clip Unexecuted instantiation: htspsl.c:slprintfbuff_clip Unexecuted instantiation: htslines.c:slprintfbuff_clip Unexecuted instantiation: htscore.c:slprintfbuff_clip Unexecuted instantiation: htshash.c:slprintfbuff_clip Unexecuted instantiation: htscache.c:slprintfbuff_clip Unexecuted instantiation: htsback.c:slprintfbuff_clip Unexecuted instantiation: htsftp.c:slprintfbuff_clip Unexecuted instantiation: htsparse.c:slprintfbuff_clip Unexecuted instantiation: htscmdline.c:slprintfbuff_clip Unexecuted instantiation: htsfilters.c:slprintfbuff_clip Unexecuted instantiation: htsname.c:slprintfbuff_clip Unexecuted instantiation: htsrobots.c:slprintfbuff_clip Unexecuted instantiation: htstools.c:slprintfbuff_clip Unexecuted instantiation: htswizard.c:slprintfbuff_clip Unexecuted instantiation: htsthread.c:slprintfbuff_clip Unexecuted instantiation: htsindex.c:slprintfbuff_clip Unexecuted instantiation: htsbauth.c:slprintfbuff_clip Unexecuted instantiation: htscrashtest.c:slprintfbuff_clip Unexecuted instantiation: htsmd5.c:slprintfbuff_clip Unexecuted instantiation: htsnet.c:slprintfbuff_clip Unexecuted instantiation: htscodec.c:slprintfbuff_clip Unexecuted instantiation: htswarc.c:slprintfbuff_clip Unexecuted instantiation: htschanges.c:slprintfbuff_clip Unexecuted instantiation: htssinglefile.c:slprintfbuff_clip Unexecuted instantiation: htssitemap.c:slprintfbuff_clip Unexecuted instantiation: htsproxy.c:slprintfbuff_clip Unexecuted instantiation: htszlib.c:slprintfbuff_clip Unexecuted instantiation: htsconcat.c:slprintfbuff_clip Unexecuted instantiation: htsmodules.c:slprintfbuff_clip Unexecuted instantiation: htscharset.c:slprintfbuff_clip Unexecuted instantiation: htsencoding.c:slprintfbuff_clip Unexecuted instantiation: htsescape.c:slprintfbuff_clip Unexecuted instantiation: htssniff.c:slprintfbuff_clip |
618 | | |
619 | | /** |
620 | | * slcatprintfbuff() for text meant to be clipped rather than dropped whole: |
621 | | * keeps what fitted and advances *used past it. Nothing to act on, hence not |
622 | | * HTS_CHECK_RESULT. |
623 | | */ |
624 | | static HTS_INLINE HTS_UNUSED HTS_PRINTF_FUN(4, 5) void slcatprintfbuff_clip( |
625 | 0 | char *dest, size_t size, size_t *used, const char *fmt, ...) { |
626 | 0 | va_list args; |
627 | |
|
628 | 0 | assertf(dest != NULL && used != NULL && *used < size); |
629 | 0 | va_start(args, fmt); |
630 | 0 | (void) vslprintfbuff(dest + *used, size - *used, fmt, args); |
631 | 0 | va_end(args); |
632 | 0 | *used += strlen(dest + *used); |
633 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:slcatprintfbuff_clip Unexecuted instantiation: store.c:slcatprintfbuff_clip Unexecuted instantiation: htsdate.c:slcatprintfbuff_clip Unexecuted instantiation: htslib.c:slcatprintfbuff_clip Unexecuted instantiation: htsfetch.c:slcatprintfbuff_clip Unexecuted instantiation: htspsl.c:slcatprintfbuff_clip Unexecuted instantiation: htslines.c:slcatprintfbuff_clip Unexecuted instantiation: htscore.c:slcatprintfbuff_clip Unexecuted instantiation: htshash.c:slcatprintfbuff_clip Unexecuted instantiation: htscache.c:slcatprintfbuff_clip Unexecuted instantiation: htsback.c:slcatprintfbuff_clip Unexecuted instantiation: htsftp.c:slcatprintfbuff_clip Unexecuted instantiation: htsparse.c:slcatprintfbuff_clip Unexecuted instantiation: htscmdline.c:slcatprintfbuff_clip Unexecuted instantiation: htsfilters.c:slcatprintfbuff_clip Unexecuted instantiation: htsname.c:slcatprintfbuff_clip Unexecuted instantiation: htsrobots.c:slcatprintfbuff_clip Unexecuted instantiation: htstools.c:slcatprintfbuff_clip Unexecuted instantiation: htswizard.c:slcatprintfbuff_clip Unexecuted instantiation: htsthread.c:slcatprintfbuff_clip Unexecuted instantiation: htsindex.c:slcatprintfbuff_clip Unexecuted instantiation: htsbauth.c:slcatprintfbuff_clip Unexecuted instantiation: htscrashtest.c:slcatprintfbuff_clip Unexecuted instantiation: htsmd5.c:slcatprintfbuff_clip Unexecuted instantiation: htsnet.c:slcatprintfbuff_clip Unexecuted instantiation: htscodec.c:slcatprintfbuff_clip Unexecuted instantiation: htswarc.c:slcatprintfbuff_clip Unexecuted instantiation: htschanges.c:slcatprintfbuff_clip Unexecuted instantiation: htssinglefile.c:slcatprintfbuff_clip Unexecuted instantiation: htssitemap.c:slcatprintfbuff_clip Unexecuted instantiation: htsproxy.c:slcatprintfbuff_clip Unexecuted instantiation: htszlib.c:slcatprintfbuff_clip Unexecuted instantiation: htsconcat.c:slcatprintfbuff_clip Unexecuted instantiation: htsmodules.c:slcatprintfbuff_clip Unexecuted instantiation: htscharset.c:slcatprintfbuff_clip Unexecuted instantiation: htsencoding.c:slcatprintfbuff_clip Unexecuted instantiation: htsescape.c:slcatprintfbuff_clip Unexecuted instantiation: htssniff.c:slcatprintfbuff_clip |
634 | | |
635 | | /** |
636 | | * slprintfbuff() over the in-scope array ARR (capacity = sizeof(ARR)). |
637 | | * On GCC/Clang a pointer is a compile error; use slprintfbuff() for those. |
638 | | */ |
639 | | #if (defined(__GNUC__) && !defined(__cplusplus)) |
640 | | #define sprintfbuff(ARR, ...) \ |
641 | 4.10k | slprintfbuff((ARR), sizeof(ARR) + htsbuff_must_be_array_(ARR), __VA_ARGS__) |
642 | | #else |
643 | | #define sprintfbuff(ARR, ...) slprintfbuff((ARR), sizeof(ARR), __VA_ARGS__) |
644 | | #endif |
645 | | |
646 | | /** Last character of s, or '\0' when s is empty. Replaces s[strlen(s) - 1], |
647 | | which indexes one byte before the buffer on an empty string. */ |
648 | 43.1k | static HTS_INLINE HTS_UNUSED char hts_lastchar(const char *s) { |
649 | 43.1k | const size_t len = strlen(s); |
650 | | |
651 | 43.1k | return len != 0 ? s[len - 1] : '\0'; |
652 | 43.1k | } Unexecuted instantiation: fuzz-cachendx.c:hts_lastchar Line | Count | Source | 648 | 43.1k | static HTS_INLINE HTS_UNUSED char hts_lastchar(const char *s) { | 649 | 43.1k | const size_t len = strlen(s); | 650 | | | 651 | 43.1k | return len != 0 ? s[len - 1] : '\0'; | 652 | 43.1k | } |
Unexecuted instantiation: htsdate.c:hts_lastchar Unexecuted instantiation: htslib.c:hts_lastchar Unexecuted instantiation: htsfetch.c:hts_lastchar Unexecuted instantiation: htspsl.c:hts_lastchar Unexecuted instantiation: htslines.c:hts_lastchar Unexecuted instantiation: htscore.c:hts_lastchar Unexecuted instantiation: htshash.c:hts_lastchar Unexecuted instantiation: htscache.c:hts_lastchar Unexecuted instantiation: htsback.c:hts_lastchar Unexecuted instantiation: htsftp.c:hts_lastchar Unexecuted instantiation: htsparse.c:hts_lastchar Unexecuted instantiation: htscmdline.c:hts_lastchar Unexecuted instantiation: htsfilters.c:hts_lastchar Unexecuted instantiation: htsname.c:hts_lastchar Unexecuted instantiation: htsrobots.c:hts_lastchar Unexecuted instantiation: htstools.c:hts_lastchar Unexecuted instantiation: htswizard.c:hts_lastchar Unexecuted instantiation: htsthread.c:hts_lastchar Unexecuted instantiation: htsindex.c:hts_lastchar Unexecuted instantiation: htsbauth.c:hts_lastchar Unexecuted instantiation: htscrashtest.c:hts_lastchar Unexecuted instantiation: htsmd5.c:hts_lastchar Unexecuted instantiation: htsnet.c:hts_lastchar Unexecuted instantiation: htscodec.c:hts_lastchar Unexecuted instantiation: htswarc.c:hts_lastchar Unexecuted instantiation: htschanges.c:hts_lastchar Unexecuted instantiation: htssinglefile.c:hts_lastchar Unexecuted instantiation: htssitemap.c:hts_lastchar Unexecuted instantiation: htsproxy.c:hts_lastchar Unexecuted instantiation: htszlib.c:hts_lastchar Unexecuted instantiation: htsconcat.c:hts_lastchar Unexecuted instantiation: htsmodules.c:hts_lastchar Unexecuted instantiation: htscharset.c:hts_lastchar Unexecuted instantiation: htsencoding.c:hts_lastchar Unexecuted instantiation: htsescape.c:hts_lastchar Unexecuted instantiation: htssniff.c:hts_lastchar |
653 | | |
654 | | /** Drop a trailing c from s if present. HTS_TRUE if one was dropped. */ |
655 | 0 | static HTS_INLINE HTS_UNUSED hts_boolean hts_striplastchar(char *s, char c) { |
656 | 0 | const size_t len = strlen(s); |
657 | |
|
658 | 0 | if (len != 0 && s[len - 1] == c) { |
659 | 0 | s[len - 1] = '\0'; |
660 | 0 | return HTS_TRUE; |
661 | 0 | } |
662 | 0 | return HTS_FALSE; |
663 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:hts_striplastchar Unexecuted instantiation: store.c:hts_striplastchar Unexecuted instantiation: htsdate.c:hts_striplastchar Unexecuted instantiation: htslib.c:hts_striplastchar Unexecuted instantiation: htsfetch.c:hts_striplastchar Unexecuted instantiation: htspsl.c:hts_striplastchar Unexecuted instantiation: htslines.c:hts_striplastchar Unexecuted instantiation: htscore.c:hts_striplastchar Unexecuted instantiation: htshash.c:hts_striplastchar Unexecuted instantiation: htscache.c:hts_striplastchar Unexecuted instantiation: htsback.c:hts_striplastchar Unexecuted instantiation: htsftp.c:hts_striplastchar Unexecuted instantiation: htsparse.c:hts_striplastchar Unexecuted instantiation: htscmdline.c:hts_striplastchar Unexecuted instantiation: htsfilters.c:hts_striplastchar Unexecuted instantiation: htsname.c:hts_striplastchar Unexecuted instantiation: htsrobots.c:hts_striplastchar Unexecuted instantiation: htstools.c:hts_striplastchar Unexecuted instantiation: htswizard.c:hts_striplastchar Unexecuted instantiation: htsthread.c:hts_striplastchar Unexecuted instantiation: htsindex.c:hts_striplastchar Unexecuted instantiation: htsbauth.c:hts_striplastchar Unexecuted instantiation: htscrashtest.c:hts_striplastchar Unexecuted instantiation: htsmd5.c:hts_striplastchar Unexecuted instantiation: htsnet.c:hts_striplastchar Unexecuted instantiation: htscodec.c:hts_striplastchar Unexecuted instantiation: htswarc.c:hts_striplastchar Unexecuted instantiation: htschanges.c:hts_striplastchar Unexecuted instantiation: htssinglefile.c:hts_striplastchar Unexecuted instantiation: htssitemap.c:hts_striplastchar Unexecuted instantiation: htsproxy.c:hts_striplastchar Unexecuted instantiation: htszlib.c:hts_striplastchar Unexecuted instantiation: htsconcat.c:hts_striplastchar Unexecuted instantiation: htsmodules.c:hts_striplastchar Unexecuted instantiation: htscharset.c:hts_striplastchar Unexecuted instantiation: htsencoding.c:hts_striplastchar Unexecuted instantiation: htsescape.c:hts_striplastchar Unexecuted instantiation: htssniff.c:hts_striplastchar |
664 | | |
665 | | /** Drop the last character of s whatever it is. HTS_TRUE if s was not |
666 | | empty. */ |
667 | 0 | static HTS_INLINE HTS_UNUSED hts_boolean hts_choplastchar(char *s) { |
668 | 0 | const size_t len = strlen(s); |
669 | 0 |
|
670 | 0 | if (len != 0) { |
671 | 0 | s[len - 1] = '\0'; |
672 | 0 | return HTS_TRUE; |
673 | 0 | } |
674 | 0 | return HTS_FALSE; |
675 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:hts_choplastchar Unexecuted instantiation: store.c:hts_choplastchar Unexecuted instantiation: htsdate.c:hts_choplastchar Unexecuted instantiation: htslib.c:hts_choplastchar Unexecuted instantiation: htsfetch.c:hts_choplastchar Unexecuted instantiation: htspsl.c:hts_choplastchar Unexecuted instantiation: htslines.c:hts_choplastchar Unexecuted instantiation: htscore.c:hts_choplastchar Unexecuted instantiation: htshash.c:hts_choplastchar Unexecuted instantiation: htscache.c:hts_choplastchar Unexecuted instantiation: htsback.c:hts_choplastchar Unexecuted instantiation: htsftp.c:hts_choplastchar Unexecuted instantiation: htsparse.c:hts_choplastchar Unexecuted instantiation: htscmdline.c:hts_choplastchar Unexecuted instantiation: htsfilters.c:hts_choplastchar Unexecuted instantiation: htsname.c:hts_choplastchar Unexecuted instantiation: htsrobots.c:hts_choplastchar Unexecuted instantiation: htstools.c:hts_choplastchar Unexecuted instantiation: htswizard.c:hts_choplastchar Unexecuted instantiation: htsthread.c:hts_choplastchar Unexecuted instantiation: htsindex.c:hts_choplastchar Unexecuted instantiation: htsbauth.c:hts_choplastchar Unexecuted instantiation: htscrashtest.c:hts_choplastchar Unexecuted instantiation: htsmd5.c:hts_choplastchar Unexecuted instantiation: htsnet.c:hts_choplastchar Unexecuted instantiation: htscodec.c:hts_choplastchar Unexecuted instantiation: htswarc.c:hts_choplastchar Unexecuted instantiation: htschanges.c:hts_choplastchar Unexecuted instantiation: htssinglefile.c:hts_choplastchar Unexecuted instantiation: htssitemap.c:hts_choplastchar Unexecuted instantiation: htsproxy.c:hts_choplastchar Unexecuted instantiation: htszlib.c:hts_choplastchar Unexecuted instantiation: htsconcat.c:hts_choplastchar Unexecuted instantiation: htsmodules.c:hts_choplastchar Unexecuted instantiation: htscharset.c:hts_choplastchar Unexecuted instantiation: htsencoding.c:hts_choplastchar Unexecuted instantiation: htsescape.c:hts_choplastchar Unexecuted instantiation: htssniff.c:hts_choplastchar |
676 | | |
677 | | /** The character sets matching htslib.h's is_space(), is_realspace(), |
678 | | is_taborspace() and is_retorsep(), for hts_rtrim() and for the strspn() and |
679 | | strcspn() skips that replaced the hand-written loops. The -#test=rtrim |
680 | | self-test keeps each set and its macro in sync. HTS_RETORSEP has no skip |
681 | | caller yet, and is here so each class has one spelling as a set. */ |
682 | 0 | #define HTS_SPACES " \"\n\r\t\f\v'" |
683 | 29.0k | #define HTS_REALSPACES " \n\r\t\f\v" |
684 | | #define HTS_TABORSPACES " \t" |
685 | | #define HTS_RETORSEP "\n\r\t" |
686 | | |
687 | | /** Length of s with its trailing bytes from set dropped, so 0 when every byte |
688 | | of s is in set. */ |
689 | | static HTS_INLINE HTS_UNUSED size_t hts_rtrimlen(const char *s, |
690 | 0 | const char *set) { |
691 | 0 | size_t len = strlen(s); |
692 | |
|
693 | 0 | while (len != 0 && strchr(set, s[len - 1]) != NULL) |
694 | 0 | len--; |
695 | 0 | return len; |
696 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:hts_rtrimlen Unexecuted instantiation: store.c:hts_rtrimlen Unexecuted instantiation: htsdate.c:hts_rtrimlen Unexecuted instantiation: htslib.c:hts_rtrimlen Unexecuted instantiation: htsfetch.c:hts_rtrimlen Unexecuted instantiation: htspsl.c:hts_rtrimlen Unexecuted instantiation: htslines.c:hts_rtrimlen Unexecuted instantiation: htscore.c:hts_rtrimlen Unexecuted instantiation: htshash.c:hts_rtrimlen Unexecuted instantiation: htscache.c:hts_rtrimlen Unexecuted instantiation: htsback.c:hts_rtrimlen Unexecuted instantiation: htsftp.c:hts_rtrimlen Unexecuted instantiation: htsparse.c:hts_rtrimlen Unexecuted instantiation: htscmdline.c:hts_rtrimlen Unexecuted instantiation: htsfilters.c:hts_rtrimlen Unexecuted instantiation: htsname.c:hts_rtrimlen Unexecuted instantiation: htsrobots.c:hts_rtrimlen Unexecuted instantiation: htstools.c:hts_rtrimlen Unexecuted instantiation: htswizard.c:hts_rtrimlen Unexecuted instantiation: htsthread.c:hts_rtrimlen Unexecuted instantiation: htsindex.c:hts_rtrimlen Unexecuted instantiation: htsbauth.c:hts_rtrimlen Unexecuted instantiation: htscrashtest.c:hts_rtrimlen Unexecuted instantiation: htsmd5.c:hts_rtrimlen Unexecuted instantiation: htsnet.c:hts_rtrimlen Unexecuted instantiation: htscodec.c:hts_rtrimlen Unexecuted instantiation: htswarc.c:hts_rtrimlen Unexecuted instantiation: htschanges.c:hts_rtrimlen Unexecuted instantiation: htssinglefile.c:hts_rtrimlen Unexecuted instantiation: htssitemap.c:hts_rtrimlen Unexecuted instantiation: htsproxy.c:hts_rtrimlen Unexecuted instantiation: htszlib.c:hts_rtrimlen Unexecuted instantiation: htsconcat.c:hts_rtrimlen Unexecuted instantiation: htsmodules.c:hts_rtrimlen Unexecuted instantiation: htscharset.c:hts_rtrimlen Unexecuted instantiation: htsencoding.c:hts_rtrimlen Unexecuted instantiation: htsescape.c:hts_rtrimlen Unexecuted instantiation: htssniff.c:hts_rtrimlen |
697 | | |
698 | | /** Drop the trailing bytes of s that occur in set. */ |
699 | 0 | static HTS_INLINE HTS_UNUSED void hts_rtrim(char *s, const char *set) { |
700 | 0 | s[hts_rtrimlen(s, set)] = '\0'; |
701 | 0 | } Unexecuted instantiation: fuzz-cachendx.c:hts_rtrim Unexecuted instantiation: store.c:hts_rtrim Unexecuted instantiation: htsdate.c:hts_rtrim Unexecuted instantiation: htslib.c:hts_rtrim Unexecuted instantiation: htsfetch.c:hts_rtrim Unexecuted instantiation: htspsl.c:hts_rtrim Unexecuted instantiation: htslines.c:hts_rtrim Unexecuted instantiation: htscore.c:hts_rtrim Unexecuted instantiation: htshash.c:hts_rtrim Unexecuted instantiation: htscache.c:hts_rtrim Unexecuted instantiation: htsback.c:hts_rtrim Unexecuted instantiation: htsftp.c:hts_rtrim Unexecuted instantiation: htsparse.c:hts_rtrim Unexecuted instantiation: htscmdline.c:hts_rtrim Unexecuted instantiation: htsfilters.c:hts_rtrim Unexecuted instantiation: htsname.c:hts_rtrim Unexecuted instantiation: htsrobots.c:hts_rtrim Unexecuted instantiation: htstools.c:hts_rtrim Unexecuted instantiation: htswizard.c:hts_rtrim Unexecuted instantiation: htsthread.c:hts_rtrim Unexecuted instantiation: htsindex.c:hts_rtrim Unexecuted instantiation: htsbauth.c:hts_rtrim Unexecuted instantiation: htscrashtest.c:hts_rtrim Unexecuted instantiation: htsmd5.c:hts_rtrim Unexecuted instantiation: htsnet.c:hts_rtrim Unexecuted instantiation: htscodec.c:hts_rtrim Unexecuted instantiation: htswarc.c:hts_rtrim Unexecuted instantiation: htschanges.c:hts_rtrim Unexecuted instantiation: htssinglefile.c:hts_rtrim Unexecuted instantiation: htssitemap.c:hts_rtrim Unexecuted instantiation: htsproxy.c:hts_rtrim Unexecuted instantiation: htszlib.c:hts_rtrim Unexecuted instantiation: htsconcat.c:hts_rtrim Unexecuted instantiation: htsmodules.c:hts_rtrim Unexecuted instantiation: htscharset.c:hts_rtrim Unexecuted instantiation: htsencoding.c:hts_rtrim Unexecuted instantiation: htsescape.c:hts_rtrim Unexecuted instantiation: htssniff.c:hts_rtrim |
702 | | |
703 | | /** Offset of the last character of s, or 0 when s is empty. */ |
704 | 3.99k | static HTS_INLINE HTS_UNUSED size_t hts_lastcharoffset(const char *s) { |
705 | 3.99k | const size_t len = strlen(s); |
706 | | |
707 | 3.99k | return len != 0 ? len - 1 : 0; |
708 | 3.99k | } Unexecuted instantiation: fuzz-cachendx.c:hts_lastcharoffset store.c:hts_lastcharoffset Line | Count | Source | 704 | 3.99k | static HTS_INLINE HTS_UNUSED size_t hts_lastcharoffset(const char *s) { | 705 | 3.99k | const size_t len = strlen(s); | 706 | | | 707 | 3.99k | return len != 0 ? len - 1 : 0; | 708 | 3.99k | } |
Unexecuted instantiation: htsdate.c:hts_lastcharoffset Unexecuted instantiation: htslib.c:hts_lastcharoffset Unexecuted instantiation: htsfetch.c:hts_lastcharoffset Unexecuted instantiation: htspsl.c:hts_lastcharoffset Unexecuted instantiation: htslines.c:hts_lastcharoffset Unexecuted instantiation: htscore.c:hts_lastcharoffset Unexecuted instantiation: htshash.c:hts_lastcharoffset Unexecuted instantiation: htscache.c:hts_lastcharoffset Unexecuted instantiation: htsback.c:hts_lastcharoffset Unexecuted instantiation: htsftp.c:hts_lastcharoffset Unexecuted instantiation: htsparse.c:hts_lastcharoffset Unexecuted instantiation: htscmdline.c:hts_lastcharoffset Unexecuted instantiation: htsfilters.c:hts_lastcharoffset Unexecuted instantiation: htsname.c:hts_lastcharoffset Unexecuted instantiation: htsrobots.c:hts_lastcharoffset Unexecuted instantiation: htstools.c:hts_lastcharoffset Unexecuted instantiation: htswizard.c:hts_lastcharoffset Unexecuted instantiation: htsthread.c:hts_lastcharoffset Unexecuted instantiation: htsindex.c:hts_lastcharoffset Unexecuted instantiation: htsbauth.c:hts_lastcharoffset Unexecuted instantiation: htscrashtest.c:hts_lastcharoffset Unexecuted instantiation: htsmd5.c:hts_lastcharoffset Unexecuted instantiation: htsnet.c:hts_lastcharoffset Unexecuted instantiation: htscodec.c:hts_lastcharoffset Unexecuted instantiation: htswarc.c:hts_lastcharoffset Unexecuted instantiation: htschanges.c:hts_lastcharoffset Unexecuted instantiation: htssinglefile.c:hts_lastcharoffset Unexecuted instantiation: htssitemap.c:hts_lastcharoffset Unexecuted instantiation: htsproxy.c:hts_lastcharoffset Unexecuted instantiation: htszlib.c:hts_lastcharoffset Unexecuted instantiation: htsconcat.c:hts_lastcharoffset Unexecuted instantiation: htsmodules.c:hts_lastcharoffset Unexecuted instantiation: htscharset.c:hts_lastcharoffset Unexecuted instantiation: htsencoding.c:hts_lastcharoffset Unexecuted instantiation: htsescape.c:hts_lastcharoffset Unexecuted instantiation: htssniff.c:hts_lastcharoffset |
709 | | |
710 | | /** Address of the last character of S, or of its terminating NUL when S is |
711 | | empty. S is evaluated twice, so pass a plain lvalue. */ |
712 | 3.99k | #define hts_lastcharptr(S) ((S) + hts_lastcharoffset(S)) |
713 | | |
714 | | /* The "t" suffix is historical. These are aliases over libc and add no bounds |
715 | | checking. Engine sources call them rather than libc directly, test and |
716 | | selftest code included. */ |
717 | | |
718 | | /** Allocate A bytes, uninitialised. Returns NULL when out of memory. */ |
719 | 7.78k | #define malloct(A) malloc(A) |
720 | | |
721 | | /** Allocate A elements of B bytes, zeroed, keeping calloc's argument order. |
722 | | Returns NULL when out of memory. */ |
723 | 0 | #define calloct(A, B) calloc((A), (B)) |
724 | | |
725 | | /** |
726 | | * Free A and set it to NULL, doing nothing when A is already NULL. A must be a |
727 | | * plain lvalue, because the macro reads it twice and then assigns to it. |
728 | | */ |
729 | | #define freet(A) \ |
730 | 3.97k | do { \ |
731 | 3.97k | if ((A) != NULL) { \ |
732 | 3.97k | free(A); \ |
733 | 3.97k | (A) = NULL; \ |
734 | 3.97k | } \ |
735 | 3.97k | } while (0) |
736 | | |
737 | | /** Copy string A onto the heap. The caller owns the copy and releases it with |
738 | | freet(). Returns NULL when out of memory. */ |
739 | 0 | #define strdupt(A) strdup(A) |
740 | | |
741 | | /** Resize A to B bytes. Returns NULL when out of memory and A then stays |
742 | | allocated, so test the result before overwriting A with it. */ |
743 | 0 | #define realloct(A, B) realloc(A, B) |
744 | | |
745 | | /** Raw memcpy despite the name, and the caller owns the bounds. */ |
746 | | #define memcpybuff(A, B, N) memcpy((A), (B), (N)) |
747 | | |
748 | | #endif |