Coverage Report

Created: 2026-07-24 06:49

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