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

aremmell / libsir / 161

23 Aug 2023 11:01AM UTC coverage: 94.786% (-0.05%) from 94.833%
161

Pull #231

gitlab-ci

johnsonjh
Improve glibc version checking; use system strlcat/strlcpy on glibc >= 2.38

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Pull Request #231: Improve glibc version checking macros; use system strlcat & strlcpy on glibc >= 2.38

3018 of 3184 relevant lines covered (94.79%)

601370.38 hits per line

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

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

29
bool __sir_validptrptr(const void* restrict* pp, bool fail) {
244,428✔
30
    bool valid = NULL != pp;
244,428✔
31
    if (!valid && fail) {
244,428✔
32
        (void)_sir_seterror(_SIR_E_NULLPTR);
×
33
        SIR_ASSERT("!NULL pointer");
34
    }
35
    return valid;
244,538✔
36
}
37

38
bool __sir_validptr(const void* restrict p, bool fail) {
71,621,424✔
39
    bool valid = NULL != p;
71,621,424✔
40
    if (!valid && fail) {
71,621,424✔
41
        (void)_sir_seterror(_SIR_E_NULLPTR);
147✔
42
        SIR_ASSERT(!"NULL pointer");
140✔
43
    }
44
    return valid;
71,626,705✔
45
}
46

47
void __sir_safefree(void** pp) {
853,342✔
48
    if (!pp || !*pp)
853,342✔
49
        return;
221,718✔
50

51
    free(*pp);
589,051✔
52
    *pp = NULL;
589,051✔
53
}
54

55
void _sir_safeclose(int* restrict fd) {
161✔
56
    if (!fd || 0 > *fd)
161✔
57
        return;
×
58

59
    if (-1 == close(*fd))
161✔
60
        (void)_sir_handleerr(errno);
×
61

62
    *fd = -1;
161✔
63
}
64

65
void _sir_safefclose(FILE* restrict* restrict f) {
34,877✔
66
    if (!f || !*f)
34,877✔
67
        return;
4✔
68

69
    if (0 != fclose(*f))
34,873✔
70
        (void)_sir_handleerr(errno);
×
71

72
    *f = NULL;
34,873✔
73
}
74

75
bool _sir_validfd(int fd) {
101✔
76
    /** stdin, stdout, stderr use up 0, 1, 2 */
77
    if (2 >= fd)
101✔
78
        return _sir_handleerr(EBADF);
63✔
79

80
#if !defined(__WIN__)
81
    int ret = fcntl(fd, F_GETFL);
38✔
82
#else /* __WIN__ */
83
# if !defined(SIR_MSVCRT_MINGW)
84
    invalparamfn old = _set_thread_local_invalid_parameter_handler(_sir_invalidparameter);
85
# endif
86
    struct _stat st;
87
    int ret = _fstat(fd, &st);
88
# if !defined(SIR_MSVCRT_MINGW)
89
    _set_thread_local_invalid_parameter_handler(old);
90
# endif
91
#endif
92
    return (-1 != ret || EBADF != errno) ? true : _sir_handleerr(errno);
38✔
93
}
94

95
/** Validates a sir_update_config_data structure. */
96
#if defined(__clang__) /* only Clang has implicit-conversion; GCC BZ#87454 */
97
SANITIZE_SUPPRESS("implicit-conversion")
98
#endif
99
bool _sir_validupdatedata(sir_update_config_data* data) {
136,830✔
100
    if (!_sir_validptr(data))
136,830✔
101
        return false;
×
102

103
    bool valid = true;
112,997✔
104
    if ((data->fields & SIRU_ALL) == 0 ||
136,845✔
105
          (data->fields & ~SIRU_ALL) != 0) /* implicit-conversion */
113,011✔
106
        valid = false;
×
107

108
    if (valid && _sir_bittest(data->fields, SIRU_LEVELS))
136,845✔
109
        valid &= (_sir_validptrnofail(data->levels) &&
2,386✔
110
            _sir_validlevels(*data->levels));
1,193✔
111

112
    if (valid && _sir_bittest(data->fields, SIRU_OPTIONS))
136,857✔
113
        valid &= (_sir_validptrnofail(data->opts) &&
270,733✔
114
            _sir_validopts(*data->opts));
135,364✔
115

116
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_ID))
136,623✔
117
        valid &= _sir_validstrnofail(data->sl_identity);
92✔
118

119
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_CAT))
136,567✔
120
        valid &= _sir_validstrnofail(data->sl_category);
82✔
121

122
    if (!valid) {
136,458✔
123
        (void)_sir_seterror(_SIR_E_INVALID);
92✔
124
        SIR_ASSERT("!invalid sir_update_config_data");
125
    }
126

127
    return valid;
112,897✔
128
}
129

130
bool _sir_validlevels(sir_levels levels) {
73,611✔
131
    if ((SIRL_ALL == levels || SIRL_NONE == levels) ||
75,197✔
132
        ((_sir_bittest(levels, SIRL_INFO)           ||
2,999✔
133
         _sir_bittest(levels, SIRL_DEBUG)           ||
2,215✔
134
         _sir_bittest(levels, SIRL_NOTICE)          ||
1,819✔
135
         _sir_bittest(levels, SIRL_WARN)            ||
1,496✔
136
         _sir_bittest(levels, SIRL_ERROR)           ||
1,003✔
137
         _sir_bittest(levels, SIRL_CRIT)            ||
549✔
138
         _sir_bittest(levels, SIRL_ALERT)           ||
330✔
139
         _sir_bittest(levels, SIRL_EMERG))          &&
1,957✔
140
         ((levels & ~SIRL_ALL) == 0)))
141
         return true;
60,498✔
142

143
    _sir_selflog("invalid levels: %04"PRIx16, levels);
89✔
144
    return _sir_seterror(_SIR_E_LEVELS);
94✔
145
}
146

147
bool _sir_validlevel(sir_level level) {
4,525,963✔
148
    if (SIRL_INFO   == level || SIRL_DEBUG == level ||
4,525,963✔
149
        SIRL_NOTICE == level || SIRL_WARN  == level ||
6,687✔
150
        SIRL_ERROR  == level || SIRL_CRIT  == level ||
3,996✔
151
        SIRL_ALERT  == level || SIRL_EMERG == level)
1,338✔
152
        return true;
4,437,895✔
153

154
    _sir_selflog("invalid level: %04"PRIx32, level);
20✔
155
    return _sir_seterror(_SIR_E_LEVELS);
21✔
156
}
157

158
#if defined(__clang__) /* only Clang has implicit-conversion; GCC BZ#87454 */
159
SANITIZE_SUPPRESS("implicit-conversion")
160
#endif
161
bool _sir_validopts(sir_options opts) {
207,962✔
162
    if ((SIRO_ALL == opts || SIRO_MSGONLY == opts) ||
321,763✔
163
        ((_sir_bittest(opts, SIRO_NOTIME)          ||
221,738✔
164
         _sir_bittest(opts, SIRO_NOHOST)           ||
101,962✔
165
         _sir_bittest(opts, SIRO_NOLEVEL)          ||
632✔
166
         _sir_bittest(opts, SIRO_NONAME)           ||
522✔
167
         _sir_bittest(opts, SIRO_NOMSEC)           ||
414✔
168
         _sir_bittest(opts, SIRO_NOPID)            ||
293✔
169
         _sir_bittest(opts, SIRO_NOTID)            ||
177✔
170
         _sir_bittest(opts, SIRO_NOHDR))           &&
84✔
171
         ((opts & ~(SIRO_MSGONLY | SIRO_NOHDR)) == 0))) /* implicit-conversion */
137,601✔
172
         return true;
171,285✔
173

174
    _sir_selflog("invalid options: %08"PRIx32, opts);
239✔
175
    return _sir_seterror(_SIR_E_OPTIONS);
334✔
176
}
177

178
bool _sir_validtextattr(sir_textattr attr) {
158,745✔
179
    switch(attr) {
158,745✔
180
        case SIRTA_NORMAL:
131,448✔
181
        case SIRTA_BOLD:
182
        case SIRTA_DIM:
183
        case SIRTA_EMPH:
184
        case SIRTA_ULINE:
185
            return true;
131,448✔
186
        default: {
21✔
187
            _sir_selflog("invalid text attr: %d", attr);
20✔
188
            return _sir_seterror(_SIR_E_TEXTATTR);
21✔
189
        }
190
    }
191
}
192

193
bool _sir_validtextcolor(sir_colormode mode, sir_textcolor color) {
317,427✔
194
    bool valid = false;
262,878✔
195
    switch (mode) {
317,427✔
196
        case SIRCM_16:
295,251✔
197
            /* in 16-color mode:
198
             * compare to 30..37, 39, 40..47, 49, 90..97, 100..107. */
199
            valid = SIRTC_DEFAULT == color ||
295,251✔
200
                    (color >= 30 && color <= 37) || color == 39 ||
295,251✔
201
                    (color >= 40 && color <= 47) || color == 49 ||
125,700✔
202
                    (color >= 90 && color <= 97) || (color >= 100 && color <= 107);
487,740✔
203
            break;
243,870✔
204
        case SIRCM_256:
11,046✔
205
            /* in 256-color mode: compare to 0..255. sir_textcolor is unsigned,
206
             * so only need to ensure it's <= 255. */
207
            valid = SIRTC_DEFAULT == color || color <= 255;
11,046✔
208
            break;
11,046✔
209
        case SIRCM_RGB: {
11,130✔
210
            /* in RGB-color mode: mask and compare to 0x00ffffff. */
211
            valid = SIRTC_DEFAULT == color || ((color & 0xff000000) == 0);
11,130✔
212
            break;
11,130✔
213
        }
214
        case SIRCM_INVALID: // GCOVR_EXCL_START
215
        default:
216
            valid = false;
217
            break;
218
    } // GCOVR_EXCL_STOP
219

220
    if (!valid) {
266,046✔
221
        _sir_selflog("invalid text color for mode %d %08"PRIx32" (%"PRIu32")",
20✔
222
            mode, color, color);
223
        (void)_sir_seterror(_SIR_E_TEXTCOLOR);
21✔
224
    }
225

226
    return valid;
317,427✔
227
}
228

229
bool _sir_validcolormode(sir_colormode mode) {
159,509✔
230
    switch (mode) {
159,509✔
231
        case SIRCM_16:
132,101✔
232
        case SIRCM_256:
233
        case SIRCM_RGB:
234
            return true;
132,101✔
235
        case SIRCM_INVALID:
21✔
236
        default: {
237
            _sir_selflog("invalid color mode: %d", mode);
20✔
238
            return _sir_seterror(_SIR_E_COLORMODE);
21✔
239
        }
240
    }
241
}
242

243
bool __sir_validstr(const char* restrict str, bool fail) {
45,097,756✔
244
    bool valid = str && (*str != '\0');
45,097,756✔
245
    if (!valid && fail) {
45,097,756✔
246
        (void)_sir_seterror(_SIR_E_STRING);
18,880✔
247
        SIR_ASSERT(!"invalid string");
18,875✔
248
    }
249
    return valid;
45,099,753✔
250
}
251

252
int _sir_strncpy(char* restrict dest, size_t destsz, const char* restrict src, size_t count) {
2,166,345✔
253
    if (_sir_validptr(dest) && _sir_validstr(src)) {
2,166,345✔
254
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
255
        int ret = strncpy_s(dest, destsz, src, count);
256
        if (0 != ret) {
257
            (void)_sir_handleerr(ret);
258
            return -1;
259
        }
260
        return 0;
261
#else
262
        SIR_UNUSED(count);
263
        size_t cpy = strlcpy(dest, src, destsz);
2,142,500✔
264
        SIR_ASSERT_UNUSED(cpy < destsz, cpy);
2,158,395✔
265
        return 0;
2,166,345✔
266
#endif
267
    }
268

269
    return -1;
×
270
}
271

272
int _sir_strncat(char* restrict dest, size_t destsz, const char* restrict src, size_t count) {
25,057,514✔
273
    if (_sir_validptr(dest) && _sir_validstr(src)) {
25,057,514✔
274
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
275
        int ret = strncat_s(dest, destsz, src, count);
276
        if (0 != ret) {
277
            (void)_sir_handleerr(ret);
278
            return -1;
279
        }
280
        return 0;
281
#else
282
        SIR_UNUSED(count);
283
        size_t cat = strlcat(dest, src, destsz);
24,680,283✔
284
        SIR_ASSERT_UNUSED(cat < destsz, cat);
24,917,916✔
285
        return 0;
25,039,165✔
286
#endif
287
    }
288

289
    return -1;
18,749✔
290
}
291

292
int _sir_fopen(FILE* restrict* restrict streamptr, const char* restrict filename,
34,960✔
293
    const char* restrict mode) {
294
    if (_sir_validptrptr(streamptr) && _sir_validstr(filename) && _sir_validstr(mode)) {
34,960✔
295
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
296
        int ret = fopen_s(streamptr, filename, mode);
297
        if (0 != ret) {
298
            (void)_sir_handleerr(ret);
299
            return -1;
300
        }
301
        return 0;
302
#else
303
        *streamptr = fopen(filename, mode);
34,960✔
304
        if (!*streamptr) {
34,960✔
305
            (void)_sir_handleerr(errno);
67✔
306
            return -1;
67✔
307
        }
308
        return 0;
28,674✔
309
#endif
310
    }
311

312
    return -1;
×
313
}
314

315
struct tm* _sir_localtime(const time_t* restrict timer, struct tm* restrict buf) {
2,166,000✔
316
    if (_sir_validptr(timer) && _sir_validptr(buf)) {
2,166,000✔
317
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
318
# if defined(__WIN__)
319
        errno_t ret = (errno_t)localtime_s(buf, timer);
320
        if (0 != ret) {
321
            (void)_sir_handleerr(ret);
322
            return NULL;
323
        }
324

325
        return buf;
326
# else /* __WIN__ */
327
        struct tm* ret = localtime_s(timer, buf);
328
        if (!ret)
329
            (void)_sir_handleerr(errno);
330

331
        return ret;
332
# endif
333
#else
334
        SIR_UNUSED(buf);
335
        struct tm* ret = localtime(timer);
2,166,000✔
336
        if (!ret)
2,166,001✔
337
            (void)_sir_handleerr(errno);
×
338

339
        return ret;
2,166,001✔
340
#endif
341
    }
342

343
    return NULL;
×
344
}
345

346
bool _sir_getchar(char* input) {
1✔
347
    if (!_sir_validptr(input))
1✔
348
        return false;
×
349

350
#if defined(__WIN__)
351
# if defined(__EMBARCADEROC__)
352
     *input = (char)getch();
353
# else
354
     *input = (char)_getch();
355
# endif
356
     return true;
357
#else /* !__WIN__ */
358
    struct termios cur = {0}, new = {0};
1✔
359
    if (0 != tcgetattr(STDIN_FILENO, &cur))
1✔
360
        return _sir_handleerr(errno);
×
361

362
    memcpy(&new, &cur, sizeof(struct termios));
×
363
    new.c_lflag &= ~(ICANON | ECHO);
1✔
364

365
    if (0 != tcsetattr(STDIN_FILENO, TCSANOW, &new))
1✔
366
        return _sir_handleerr(errno);
×
367

368
    *input = (char)getchar();
1✔
369

370
    return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &cur) ? true
1✔
371
        : _sir_handleerr(errno);
1✔
372
#endif
373
}
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