• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aremmell / libsir / 1749

29 Apr 2024 12:14PM UTC coverage: 95.468% (-0.03%) from 95.493%
1749

Pull #419

gitlab-ci

johnsonjh
Add semgrep exclusions to legacy `build-aux/install-sh`

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Pull Request #419: Add a suppression for semgrep

3876 of 4060 relevant lines covered (95.47%)

477462.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.81
/src/sirhelpers.c
1
/*
2
 * sirhelpers.c
3
 *
4
 * Version: 2.2.5
5
 *
6
 * -----------------------------------------------------------------------------
7
 *
8
 * SPDX-License-Identifier: MIT
9
 *
10
 * Copyright (c) 2018-2024 Ryan M. Lederman <lederman@gmail.com>
11
 * Copyright (c) 2018-2024 Jeffrey H. Johnson <trnsz@pobox.com>
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
14
 * this software and associated documentation files (the "Software"), to deal in
15
 * the Software without restriction, including without limitation the rights to
16
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17
 * the Software, and to permit persons to whom the Software is furnished to do so,
18
 * subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
27
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
 *
30
 * -----------------------------------------------------------------------------
31
 */
32

33
#include "sir/helpers.h"
34
#include "sir/errors.h"
35

36
void __sir_safefree(void** pp) {
472,955✔
37
    if (!pp || !*pp)
472,955✔
38
        return;
114,616✔
39

40
    free(*pp);
335,262✔
41
    *pp = NULL;
335,262✔
42
}
43

44
void _sir_safeclose(int* restrict fd) {
294✔
45
    if (!fd || 0 > *fd)
294✔
46
        return;
258✔
47

48
    if (-1 == close(*fd))
×
49
        (void)_sir_handleerr(errno);
×
50

51
    *fd = -1;
×
52
}
53

54
void _sir_safefclose(FILE* restrict* restrict f) {
38,715✔
55
    if (!f || !*f)
38,715✔
56
        return;
15,950✔
57

58
    if (0 != fclose(*f))
19,392✔
59
        (void)_sir_handleerr(errno);
×
60

61
    *f = NULL;
19,392✔
62
}
63

64
bool _sir_validfd(int fd) {
135✔
65
    /** stdin, stdout, stderr use up 0, 1, 2 */
66
    if (2 >= fd)
135✔
67
        return _sir_handleerr(EBADF);
84✔
68

69
#if !defined(__WIN__)
70
    int ret = fcntl(fd, F_GETFL);
51✔
71
#else /* __WIN__ */
72
# if !defined(SIR_MSVCRT_MINGW)
73
    invalparamfn old = _set_thread_local_invalid_parameter_handler(_sir_invalidparameter);
74
# endif
75
    struct _stat st;
76
    int ret = _fstat(fd, &st);
77
# if !defined(SIR_MSVCRT_MINGW)
78
    _set_thread_local_invalid_parameter_handler(old);
79
# endif
80
#endif
81
    return (-1 != ret || EBADF != errno) ? true : _sir_handleerr(errno);
51✔
82
}
83

84
/** Validates a sir_update_config_data structure. */
85
bool __sir_validupdatedata(const sir_update_config_data* data, const char* func,
76,622✔
86
    const char* file, uint32_t line) {
87
    if (!_sir_validptr(data))
76,622✔
88
        return false;
×
89

90
    bool valid = true;
63,458✔
91
    if ((data->fields & SIRU_ALL) == 0U || (data->fields & ~SIRU_ALL) != 0U)
76,616✔
92
        valid = false;
×
93

94
    if (valid && _sir_bittest(data->fields, SIRU_LEVELS))
76,613✔
95
        valid = _sir_validptrnofail(data->levels) &&
3,258✔
96
                _sir_validlevels(*data->levels);
1,629✔
97

98
    if (valid && _sir_bittest(data->fields, SIRU_OPTIONS))
76,613✔
99
        valid = _sir_validptrnofail(data->opts) &&
149,393✔
100
                _sir_validopts(*data->opts);
74,697✔
101

102
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_ID))
76,536✔
103
        valid = _sir_validstrnofail(data->sl_identity);
129✔
104

105
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_CAT))
76,532✔
106
        valid = _sir_validstrnofail(data->sl_category);
110✔
107

108
    if (!valid) {
76,528✔
109
        SIR_ASSERT(valid);
×
110
        (void)__sir_seterror(_SIR_E_INVALID, func, file, line);
3✔
111
    }
112

113
    return valid;
63,401✔
114
}
115

116
bool __sir_validlevels(sir_levels levels, const char* func,
44,218✔
117
    const char* file, uint32_t line) {
118
    if ((SIRL_ALL == levels || SIRL_NONE == levels) ||
46,422✔
119
        ((_sir_bittest(levels, SIRL_INFO)           ||
4,139✔
120
         _sir_bittest(levels, SIRL_DEBUG)           ||
2,922✔
121
         _sir_bittest(levels, SIRL_NOTICE)          ||
2,226✔
122
         _sir_bittest(levels, SIRL_WARN)            ||
1,803✔
123
         _sir_bittest(levels, SIRL_ERROR)           ||
1,206✔
124
         _sir_bittest(levels, SIRL_CRIT)            ||
584✔
125
         _sir_bittest(levels, SIRL_ALERT)           ||
356✔
126
         _sir_bittest(levels, SIRL_EMERG))          &&
2,728✔
127
         ((levels & ~SIRL_ALL) == 0U)))
128
         return true;
36,485✔
129

130
    _sir_selflog("invalid levels: %04"PRIx16, levels);
114✔
131
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
124✔
132
}
133

134
bool __sir_validlevel(sir_level level, const char* func, const char* file,
4,427,120✔
135
    uint32_t line) {
136
    if (SIRL_INFO   == level || SIRL_DEBUG == level ||
4,427,120✔
137
        SIRL_NOTICE == level || SIRL_WARN  == level ||
8,950✔
138
        SIRL_ERROR  == level || SIRL_CRIT  == level ||
5,348✔
139
        SIRL_ALERT  == level || SIRL_EMERG == level)
1,791✔
140
        return true;
4,360,810✔
141

142
    _sir_selflog("invalid level: %04"PRIx16, level);
25✔
143
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
27✔
144
}
145

146
bool __sir_validopts(sir_options opts, const char* func, const char* file,
117,533✔
147
    uint32_t line) {
148
    if ((SIRO_ALL == opts || SIRO_MSGONLY == opts) ||
182,398✔
149
        ((_sir_bittest(opts, SIRO_NOTIME)          ||
125,066✔
150
         _sir_bittest(opts, SIRO_NOHOST)           ||
56,837✔
151
         _sir_bittest(opts, SIRO_NOLEVEL)          ||
801✔
152
         _sir_bittest(opts, SIRO_NONAME)           ||
646✔
153
         _sir_bittest(opts, SIRO_NOMSEC)           ||
516✔
154
         _sir_bittest(opts, SIRO_NOPID)            ||
392✔
155
         _sir_bittest(opts, SIRO_NOTID)            ||
227✔
156
         _sir_bittest(opts, SIRO_NOHDR))           &&
108✔
157
         ((opts & ~(SIRO_MSGONLY | SIRO_NOHDR)) == 0U)))
78,188✔
158
         return true;
96,967✔
159

160
    _sir_selflog("invalid options: %08"PRIx32, opts);
349✔
161
    return __sir_seterror(_SIR_E_OPTIONS, func, file, line);
408✔
162
}
163

164
bool __sir_validtextattr(sir_textattr attr, const char* func, const char* file,
92,664✔
165
    uint32_t line) {
166
    switch(attr) {
92,664✔
167
        case SIRTA_NORMAL:
79,460✔
168
        case SIRTA_BOLD:
169
        case SIRTA_DIM:
170
        case SIRTA_EMPH:
171
        case SIRTA_ULINE:
172
            return true;
79,460✔
173
        default: {
24✔
174
            _sir_selflog("invalid text attr: %d", attr);
23✔
175
            return __sir_seterror(_SIR_E_TEXTATTR, func, file, line);
24✔
176
        }
177
    }
178
}
179

180
bool __sir_validtextcolor(sir_colormode mode, sir_textcolor color, const char* func,
185,256✔
181
    const char* file, uint32_t line) {
182
    bool valid = false;
158,899✔
183
    switch (mode) {
185,256✔
184
        case SIRCM_16:
159,912✔
185
            /* in 16-color mode:
186
             * compare to 30..37, 39, 40..47, 49, 90..97, 100..107. */
187
            valid = SIRTC_DEFAULT == color ||
159,912✔
188
                    (color >= 30U && color <= 37U) || color == 39U ||
159,912✔
189
                    (color >= 40U && color <= 47U) || color == 49U ||
73,643✔
190
                    (color >= 90U && color <= 97U) || (color >= 100U && color <= 107U);
273,446✔
191
            break;
136,723✔
192
        case SIRCM_256:
12,624✔
193
            /* in 256-color mode: compare to 0..255. sir_textcolor is unsigned,
194
             * so only need to ensure it's <= 255. */
195
            valid = SIRTC_DEFAULT == color || color <= 255U;
12,624✔
196
            break;
12,624✔
197
        case SIRCM_RGB: {
12,720✔
198
            /* in RGB-color mode: mask and compare to 0x00ffffff. */
199
            valid = SIRTC_DEFAULT == color || ((color & 0xff000000U) == 0U);
12,720✔
200
            break;
12,720✔
201
        }
202
        case SIRCM_INVALID: // GCOVR_EXCL_START
203
        default:
204
            valid = false;
205
            break;
206
    } // GCOVR_EXCL_STOP
207

208
    if (!valid) {
162,067✔
209
        _sir_selflog("invalid text color for mode %d %08"PRIx32" (%"PRIu32")",
23✔
210
            mode, color, color);
211
        (void)__sir_seterror(_SIR_E_TEXTCOLOR, func, file, line);
24✔
212
    }
213

214
    return valid;
185,256✔
215
}
216

217
bool __sir_validcolormode(sir_colormode mode, const char* func, const char* file,
93,705✔
218
    uint32_t line) {
219
    switch (mode) {
93,705✔
220
        case SIRCM_16:
80,371✔
221
        case SIRCM_256:
222
        case SIRCM_RGB:
223
            return true;
80,371✔
224
        case SIRCM_INVALID:
24✔
225
        default: {
226
            _sir_selflog("invalid color mode: %d", mode);
23✔
227
            return __sir_seterror(_SIR_E_COLORMODE, func, file, line);
24✔
228
        }
229
    }
230
}
231

232
int _sir_strncpy(char* restrict dest, size_t destsz, const char* restrict src,
4,195,102✔
233
    size_t count) {
234
    if (_sir_validptr(dest) && _sir_validstr(src)) {
4,195,102✔
235
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
236
        int ret = strncpy_s(dest, destsz, src, count);
237
        if (0 != ret) {
238
            (void)_sir_handleerr(ret);
239
            return -1;
240
        }
241
        return 0;
242
#else
243
        SIR_UNUSED(count);
244
        size_t cpy = strlcpy(dest, src, destsz);
4,167,937✔
245
        SIR_ASSERT_UNUSED(cpy < destsz, cpy);
4,184,601✔
246
        return 0;
4,195,077✔
247
#endif
248
    }
249

250
    return -1;
20✔
251
}
252

253
int _sir_strncat(char* restrict dest, size_t destsz, const char* restrict src,
28,368,594✔
254
    size_t count) {
255
    if (_sir_validptr(dest) && _sir_validstr(src)) {
28,368,594✔
256
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
257
        int ret = strncat_s(dest, destsz, src, count);
258
        if (0 != ret) {
259
            (void)_sir_handleerr(ret);
260
            return -1;
261
        }
262
        return 0;
263
#else
264
        SIR_UNUSED(count);
265
        size_t cat = strlcat(dest, src, destsz);
28,141,000✔
266
        SIR_ASSERT_UNUSED(cat < destsz, cat);
28,260,453✔
267
        return 0;
28,367,153✔
268
#endif
269
    }
270

271
    return -1;
2,559✔
272
}
273

274
int _sir_fopen(FILE* restrict* restrict streamptr, const char* restrict filename,
19,452✔
275
    const char* restrict mode) {
276
    if (_sir_validptrptr(streamptr) && _sir_validstr(filename) && _sir_validstr(mode)) {
19,452✔
277
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
278
        int ret = fopen_s(streamptr, filename, mode);
279
        if (0 != ret) {
280
            (void)_sir_handleerr(ret);
281
            return -1;
282
        }
283
        return 0;
284
#else
285
        *streamptr = fopen(filename, mode);
19,452✔
286
        if (!*streamptr) {
19,452✔
287
            (void)_sir_handleerr(errno);
108✔
288
            return -1;
108✔
289
        }
290
        return 0;
15,963✔
291
#endif
292
    }
293

294
    return -1;
×
295
}
296

297
bool _sir_getchar(char* input) {
1✔
298
#if defined(__WIN__)
299
# if defined(__EMBARCADEROC__) && (__clang_major__ < 15)
300
    if (input)
301
        *input = (char)getch();
302
# else
303
    if (input)
304
        *input = (char)_getch();
305
# endif
306
     return true;
307
#else /* !__WIN__ */
308
    struct termios cur = {0};
1✔
309
    if (0 != tcgetattr(STDIN_FILENO, &cur))
1✔
310
        return _sir_handleerr(errno);
×
311

312
    struct termios new = cur;
1✔
313
    new.c_lflag &= ~(ICANON | ECHO);
1✔
314

315
    if (0 != tcsetattr(STDIN_FILENO, TCSANOW, &new))
1✔
316
        return _sir_handleerr(errno);
×
317

318
    int ch = getchar();
1✔
319

320
    if (NULL != input)
1✔
321
        *input = (char)ch;
1✔
322

323
    return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &cur) ? true
1✔
324
        : _sir_handleerr(errno);
1✔
325
#endif
326
}
327

328
#if !defined(GCC_STATIC_ANALYZER)
329
typedef void*(*_sir_explicit_memset_t)(void*, int, size_t);
330
static const volatile _sir_explicit_memset_t _sir_explicit_memset_impl = memset;
331
#else
332
# define _sir_explicit_memset_impl(s, c, n) memset(s, c, n)
333
#endif
334
void* _sir_explicit_memset(void* ptr, int c, size_t len)
1,168✔
335
{
336
    return _sir_explicit_memset_impl(ptr, c, len);
1,168✔
337
}
338

339
char* _sir_strremove(char *str, const char *sub) {
81✔
340
    if (!str)
81✔
341
        return NULL;
23✔
342

343
    if (!sub)
54✔
344
        return str;
23✔
345

346
    char* r;
347
    char* q;
348

349
    if (*sub && (q = r = strstr(str, sub)) != NULL) {
27✔
350
        size_t len = strnlen(sub, strlen(str));
27✔
351
        const char* p;
352

353
        while ((r = strstr(p = r + len, sub)) != NULL)
27✔
354
            while (p < r)
×
355
                *q++ = *p++;
×
356

357
        while ((*q++ = *p++) != '\0');
54✔
358
    }
359

360
    return str;
23✔
361
}
362

363
char* _sir_strsqueeze(char *str) {
54✔
364
    if (!str)
54✔
365
        return NULL;
23✔
366

367
    unsigned long j;
368

369
    for (unsigned long i = j = 0; str[i]; ++i)
891✔
370
        if ((i > 0 && !isspace((unsigned char)(str[i - 1])))
864✔
371
                   || !isspace((unsigned char)(str[i])))
459✔
372
            str[j++] = str[i];
486✔
373

374
    str[j] = '\0';
27✔
375

376
    return str;
27✔
377
}
378

379
char* _sir_strredact(char *str, const char *sub, const char c) {
243✔
380
    if (!str)
243✔
381
        return NULL;
23✔
382

383
    if (!sub)
216✔
384
        return str;
23✔
385

386
    char *p = strstr(str, sub);
189✔
387

388
    if (!c || !p)
189✔
389
        return str;
69✔
390

391
    (void)_sir_explicit_memset(p, c, strnlen(sub, strlen(str)));
108✔
392

393
    return _sir_strredact(str, sub, c);
108✔
394
}
395

396
char* _sir_strreplace(char *str, const char c, const char n) {
108✔
397
    if (!str)
108✔
398
        return NULL;
23✔
399

400
    char *i = str;
69✔
401

402
    if (!c || !n)
81✔
403
        return str;
46✔
404

405
    while ((i = strchr(i, c)) != NULL)
54✔
406
        *i++ = n;
27✔
407

408
    return str;
23✔
409
}
410

411
size_t _sir_strcreplace(char *str, const char c, const char n, int32_t max) {
135✔
412
    char*  i   = str;
115✔
413
    size_t cnt = 0;
115✔
414

415
    if (!str || !c || !n || !max)
135✔
416
        return cnt;
92✔
417

418
    while (cnt < (size_t)max && (i = strchr(i, c)) != NULL) {
54✔
419
        *i++ = n;
27✔
420
        cnt++;
27✔
421
    }
422

423
    return cnt;
23✔
424
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc