Coverage Report

Created: 2026-10-17 07:02

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
/**
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_
store.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_
store.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
}
htsdate.c:strlen_safe_
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_
store.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
}
htsdate.c:strncat_safe_
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_
store.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
}
htsdate.c:strcpy_safe_
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
store.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
store.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
store.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