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

systemd / systemd / 29968961921

22 Jul 2026 03:11PM UTC coverage: 73.067% (+0.2%) from 72.837%
29968961921

push

github

keszybz
homed: verify privileged worker changes

Workers may return a newer embedded identity while processing
an owner update. Accept self-modifiable changes, but require
privileged changes to carry a trusted signature.

Follow-up for 70a5db582

16 of 36 new or added lines in 1 file covered. (44.44%)

1697 existing lines in 49 files now uncovered.

346625 of 474391 relevant lines covered (73.07%)

1335649.2 hits per line

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

99.42
/src/basic/escape.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdlib.h>
4
#include <string.h>
5

6
#include "alloc-util.h"
7
#include "escape.h"
8
#include "hexdecoct.h"
9
#include "string-util.h"
10
#include "strv.h"
11
#include "utf8.h"
12

13
int cescape_char(char c, char *buf) {
1,798,788✔
14
        char *buf_old = buf;
1,798,788✔
15

16
        /* Needs space for 4 characters in the buffer */
17

18
        switch (c) {
1,798,788✔
19

20
                case '\a':
7✔
21
                        *(buf++) = '\\';
7✔
22
                        *(buf++) = 'a';
7✔
23
                        break;
7✔
24
                case '\b':
9✔
25
                        *(buf++) = '\\';
9✔
26
                        *(buf++) = 'b';
9✔
27
                        break;
9✔
28
                case '\f':
7✔
29
                        *(buf++) = '\\';
7✔
30
                        *(buf++) = 'f';
7✔
31
                        break;
7✔
32
                case '\n':
17,713✔
33
                        *(buf++) = '\\';
17,713✔
34
                        *(buf++) = 'n';
17,713✔
35
                        break;
17,713✔
36
                case '\r':
8✔
37
                        *(buf++) = '\\';
8✔
38
                        *(buf++) = 'r';
8✔
39
                        break;
8✔
40
                case '\t':
53✔
41
                        *(buf++) = '\\';
53✔
42
                        *(buf++) = 't';
53✔
43
                        break;
53✔
44
                case '\v':
2✔
45
                        *(buf++) = '\\';
2✔
46
                        *(buf++) = 'v';
2✔
47
                        break;
2✔
48
                case '\\':
119✔
49
                        *(buf++) = '\\';
119✔
50
                        *(buf++) = '\\';
119✔
51
                        break;
119✔
52
                case '"':
3,624✔
53
                        *(buf++) = '\\';
3,624✔
54
                        *(buf++) = '"';
3,624✔
55
                        break;
3,624✔
56
                case '\'':
19✔
57
                        *(buf++) = '\\';
19✔
58
                        *(buf++) = '\'';
19✔
59
                        break;
19✔
60

61
                default:
1,777,227✔
62
                        /* For special chars we prefer octal over
63
                         * hexadecimal encoding, simply because glib's
64
                         * g_strescape() does the same */
65
                        if ((c < ' ') || (c >= 127)) {
1,777,227✔
66
                                *(buf++) = '\\';
11,905✔
67
                                *(buf++) = octchar((unsigned char) c >> 6);
11,905✔
68
                                *(buf++) = octchar((unsigned char) c >> 3);
11,905✔
69
                                *(buf++) = octchar((unsigned char) c);
11,905✔
70
                        } else
71
                                *(buf++) = c;
1,765,322✔
72
                        break;
73
        }
74

75
        return buf - buf_old;
1,798,788✔
76
}
77

78
char* cescape_length(const char *s, size_t n) {
45,428✔
79
        const char *f;
45,428✔
80
        char *r, *t;
45,428✔
81

82
        /* Does C style string escaping. May be reversed with cunescape(). */
83

84
        assert(s || n == 0);
45,428✔
85

86
        if (n == SIZE_MAX)
45,428✔
87
                n = strlen(s);
27,750✔
88

89
        if (n > (SIZE_MAX - 1) / 4)
45,428✔
90
                return NULL;
91

92
        r = new(char, n*4 + 1);
45,428✔
93
        if (!r)
45,428✔
94
                return NULL;
95

96
        for (f = s, t = r; f < s + n; f++)
1,209,232✔
97
                t += cescape_char(*f, t);
1,163,804✔
98

99
        *t = 0;
45,428✔
100

101
        return r;
45,428✔
102
}
103

104
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul) {
12,671✔
105
        int r = 1;
12,671✔
106

107
        assert(p);
12,671✔
108
        assert(ret);
12,671✔
109
        assert(eight_bit);
12,671✔
110

111
        /* Unescapes C style. Returns the unescaped character in ret.
112
         * Sets *eight_bit to true if the escaped sequence either fits in
113
         * one byte in UTF-8 or is a non-unicode literal byte and should
114
         * instead be copied directly.
115
         */
116

117
        if (length != SIZE_MAX && length < 1)
12,671✔
118
                return -EINVAL;
119

120
        switch (p[0]) {
12,671✔
121

122
        case 'a':
4✔
123
                *ret = '\a';
4✔
124
                break;
4✔
125
        case 'b':
8✔
126
                *ret = '\b';
8✔
127
                break;
8✔
128
        case 'f':
3✔
129
                *ret = '\f';
3✔
130
                break;
3✔
131
        case 'n':
22✔
132
                *ret = '\n';
22✔
133
                break;
22✔
134
        case 'r':
4✔
135
                *ret = '\r';
4✔
136
                break;
4✔
137
        case 't':
6✔
138
                *ret = '\t';
6✔
139
                break;
6✔
140
        case 'v':
3✔
141
                *ret = '\v';
3✔
142
                break;
3✔
143
        case '\\':
43✔
144
                *ret = '\\';
43✔
145
                break;
43✔
146
        case '"':
13✔
147
                *ret = '"';
13✔
148
                break;
13✔
149
        case '\'':
1✔
150
                *ret = '\'';
1✔
151
                break;
1✔
152

153
        case 's':
3✔
154
                /* This is an extension of the XDG syntax files */
155
                *ret = ' ';
3✔
156
                break;
3✔
157

158
        case 'x': {
12,474✔
159
                /* hexadecimal encoding */
160
                int a, b;
12,474✔
161

162
                if (length != SIZE_MAX && length < 3)
12,474✔
163
                        return -EINVAL;
164

165
                a = unhexchar(p[1]);
12,470✔
166
                if (a < 0)
12,470✔
167
                        return -EINVAL;
168

169
                b = unhexchar(p[2]);
12,468✔
170
                if (b < 0)
12,468✔
171
                        return -EINVAL;
172

173
                /* Don't allow NUL bytes */
174
                if (a == 0 && b == 0 && !accept_nul)
12,468✔
175
                        return -EINVAL;
176

177
                *ret = (a << 4U) | b;
12,467✔
178
                *eight_bit = true;
12,467✔
179
                r = 3;
12,467✔
180
                break;
12,467✔
181
        }
182

183
        case 'u': {
24✔
184
                /* C++11 style 16-bit unicode */
185

186
                int a[4];
24✔
187
                size_t i;
24✔
188
                uint32_t c;
24✔
189

190
                if (length != SIZE_MAX && length < 5)
24✔
191
                        return -EINVAL;
3✔
192

193
                for (i = 0; i < 4; i++) {
120✔
194
                        a[i] = unhexchar(p[1 + i]);
96✔
195
                        if (a[i] < 0)
96✔
196
                                return a[i];
197
                }
198

199
                c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
24✔
200

201
                /* Don't allow 0 chars */
202
                if (c == 0 && !accept_nul)
24✔
203
                        return -EINVAL;
204

205
                /* Don't allow UTF-16 surrogates, they cannot be encoded as valid UTF-8. Note we
206
                 * deliberately do *not* use unichar_is_valid() here (unlike the \U case below):
207
                 * it also rejects noncharacters such as U+FFFE, which callers legitimately round-trip
208
                 * through \u (e.g. systemd.mount-extra= parsing, see test-fstab-generator). */
209
                if (utf16_is_surrogate(c))
23✔
210
                        return -EINVAL;
211

212
                *ret = c;
21✔
213
                r = 5;
21✔
214
                break;
21✔
215
        }
216

217
        case 'U': {
10✔
218
                /* C++11 style 32-bit unicode */
219

220
                int a[8];
10✔
221
                size_t i;
10✔
222
                char32_t c;
10✔
223

224
                if (length != SIZE_MAX && length < 9)
10✔
UNCOV
225
                        return -EINVAL;
×
226

227
                for (i = 0; i < 8; i++) {
90✔
228
                        a[i] = unhexchar(p[1 + i]);
80✔
229
                        if (a[i] < 0)
80✔
230
                                return a[i];
231
                }
232

233
                c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
10✔
234
                    ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
10✔
235

236
                /* Don't allow 0 chars */
237
                if (c == 0 && !accept_nul)
10✔
238
                        return -EINVAL;
239

240
                /* Don't allow invalid code points */
241
                if (!unichar_is_valid(c))
10✔
242
                        return -EINVAL;
243

244
                *ret = c;
10✔
245
                r = 9;
10✔
246
                break;
10✔
247
        }
248

249
        case '0':
20✔
250
        case '1':
251
        case '2':
252
        case '3':
253
        case '4':
254
        case '5':
255
        case '6':
256
        case '7': {
257
                /* octal encoding */
258
                int a, b, c;
20✔
259
                char32_t m;
20✔
260

261
                if (length != SIZE_MAX && length < 3)
20✔
262
                        return -EINVAL;
263

264
                a = unoctchar(p[0]);
16✔
265
                if (a < 0)
16✔
266
                        return -EINVAL;
267

268
                b = unoctchar(p[1]);
16✔
269
                if (b < 0)
16✔
270
                        return -EINVAL;
271

272
                c = unoctchar(p[2]);
16✔
273
                if (c < 0)
16✔
274
                        return -EINVAL;
275

276
                /* don't allow NUL bytes */
277
                if (a == 0 && b == 0 && c == 0 && !accept_nul)
16✔
278
                        return -EINVAL;
279

280
                /* Don't allow bytes above 255 */
281
                m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
14✔
282
                if (m > 255)
14✔
283
                        return -EINVAL;
284

285
                *ret = m;
14✔
286
                *eight_bit = true;
14✔
287
                r = 3;
14✔
288
                break;
14✔
289
        }
290

291
        default:
292
                return -EINVAL;
293
        }
294

295
        return r;
296
}
297

298
ssize_t cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
155,112✔
299
        _cleanup_free_ char *ans = NULL;
155,112✔
300
        char *t;
155,112✔
301
        const char *f;
155,112✔
302
        size_t pl;
155,112✔
303
        int r;
155,112✔
304

305
        assert(s);
155,112✔
306
        assert(ret);
155,112✔
307

308
        /* Undoes C style string escaping, and optionally prefixes it. */
309

310
        if (length == SIZE_MAX)
155,112✔
311
                length = strlen(s);
113,197✔
312

313
        pl = strlen_ptr(prefix);
155,112✔
314

315
        ans = new(char, pl+length+1);
155,112✔
316
        if (!ans)
155,112✔
317
                return -ENOMEM;
318

319
        if (prefix)
155,112✔
320
                memcpy(ans, prefix, pl);
41,868✔
321

322
        for (f = s, t = ans + pl; f < s + length; f++) {
5,914,813✔
323
                size_t remaining;
5,759,712✔
324
                bool eight_bit = false;
5,759,712✔
325
                char32_t u;
5,759,712✔
326

327
                remaining = s + length - f;
5,759,712✔
328
                assert(remaining > 0);
5,759,712✔
329

330
                if (*f != '\\') {
5,759,712✔
331
                        /* A literal, copy verbatim */
332
                        *(t++) = *f;
5,747,124✔
333
                        continue;
5,747,131✔
334
                }
335

336
                if (remaining == 1) {
12,588✔
337
                        if (flags & UNESCAPE_RELAX) {
3✔
338
                                /* A trailing backslash, copy verbatim */
339
                                *(t++) = *f;
1✔
340
                                continue;
1✔
341
                        }
342

343
                        return -EINVAL;
11✔
344
                }
345

346
                r = cunescape_one(f + 1, remaining - 1, &u, &eight_bit, flags & UNESCAPE_ACCEPT_NUL);
12,585✔
347
                if (r < 0) {
12,585✔
348
                        if (flags & UNESCAPE_RELAX) {
15✔
349
                                /* Invalid escape code, let's take it literal then */
350
                                *(t++) = '\\';
6✔
351
                                continue;
6✔
352
                        }
353

354
                        return r;
9✔
355
                }
356

357
                f += r;
12,570✔
358
                if (eight_bit)
12,570✔
359
                        /* One byte? Set directly as specified */
360
                        *(t++) = u;
12,468✔
361
                else
362
                        /* Otherwise encode as multi-byte UTF-8 */
363
                        t += utf8_encode_unichar(t, u);
102✔
364
        }
365

366
        *t = 0;
155,101✔
367

368
        assert(t >= ans); /* Let static analyzers know that the answer is non-negative. */
155,101✔
369
        *ret = TAKE_PTR(ans);
155,101✔
370
        return t - *ret;
155,101✔
371
}
372

373
char* xescape_full(const char *s, const char *bad, size_t console_width, XEscapeFlags flags) {
107,221✔
374
        char *ans, *t, *prev, *prev2;
107,221✔
375
        const char *f;
107,221✔
376

377
        assert(s);
107,221✔
378

379
        /* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
380
         * reversed with cunescape(). If XESCAPE_8_BIT is specified, characters >= 127 are let through
381
         * unchanged. This corresponds to non-ASCII printable characters in pre-unicode encodings.
382
         *
383
         * If console_width is reached, or XESCAPE_FORCE_ELLIPSIS is set, output is truncated and "..." is
384
         * appended. */
385

386
        if (console_width == 0)
107,221✔
387
                return strdup("");
4✔
388

389
        size_t len_forced_ellipsis = FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS) ? STRLEN("...") : 0;
107,217✔
390
        size_t len_s = strlen(s);
107,217✔
391

392
        size_t len_body = MIN(console_width, SIZE_MAX - 1); /* We need room for the NUL byte */
107,217✔
393
        if (len_body > len_forced_ellipsis && len_s <= (len_body - len_forced_ellipsis) / 4)
107,217✔
394
                len_body = len_s * 4 + len_forced_ellipsis;
106,981✔
395

396
        ans = new(char, len_body + 1);
107,217✔
397
        if (!ans)
107,217✔
398
                return NULL;
399

400
        for (f = s, t = prev = prev2 = ans; ; f++) {
6,191,245✔
401
                char *tmp_t = t;
6,298,462✔
402

403
                if (!*f) {
6,298,462✔
404
                        if (len_forced_ellipsis != 0)
107,013✔
405
                                break;
406

407
                        *t = 0;
106,999✔
408
                        return ans;
106,999✔
409
                }
410

411
                if ((unsigned char) *f < ' ' ||
6,191,449✔
412
                    (!FLAGS_SET(flags, XESCAPE_8_BIT) && (unsigned char) *f >= 127) ||
6,190,280✔
413
                    *f == '\\' || (bad && strchr(bad, *f))) {
6,189,247✔
414
                        if ((size_t) (t - ans) + 4 + len_forced_ellipsis > len_body)
11,264✔
415
                                break;
416

417
                        *(t++) = '\\';
11,080✔
418
                        *(t++) = 'x';
11,080✔
419
                        *(t++) = hexchar(*f >> 4);
11,080✔
420
                        *(t++) = hexchar(*f);
11,080✔
421
                } else {
422
                        if ((size_t) (t - ans) + 1 + len_forced_ellipsis > len_body)
6,180,185✔
423
                                break;
424

425
                        *(t++) = *f;
6,180,165✔
426
                }
427

428
                /* We might need to go back two cycles to fit three dots, so remember two positions */
429
                prev2 = prev;
6,191,245✔
430
                prev = tmp_t;
6,191,245✔
431
        }
432

433
        /* We can just write where we want, since chars are one-byte */
434
        size_t c = MIN(len_body, STRLEN("...")); /* If the console is too narrow, write fewer dots */
218✔
435
        size_t off;
218✔
436
        if (len_body - c >= (size_t) (t - ans))
218✔
437
                off = (size_t) (t - ans);
438
        else if (len_body - c >= (size_t) (prev - ans))
76✔
439
                off = (size_t) (prev - ans);
440
        else if (len_body - c >= (size_t) (prev2 - ans))
10✔
441
                off = (size_t) (prev2 - ans);
442
        else
443
                off = len_body - c;
1✔
444
        assert(off <= (size_t) (t - ans));
218✔
445

446
        memcpy(ans + off, "...", c);
218✔
447
        ans[off + c] = '\0';
218✔
448
        return ans;
218✔
449
}
450

451
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags) {
349✔
452
        if (FLAGS_SET(flags, XESCAPE_8_BIT))
349✔
UNCOV
453
                return xescape_full(str, /* bad= */ NULL, console_width, flags);
×
454
        else
455
                return utf8_escape_non_printable_full(str,
349✔
456
                                                      console_width,
457
                                                      FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS));
349✔
458
}
459

460
char* octescape_full(const char *s, size_t len, const char *bad) {
86✔
461
        char *buf, *t;
86✔
462

463
        /* Escapes all chars in bad, in addition to \ and " chars, in \nnn octal style escaping. May be
464
         * reversed with cunescape(). */
465

466
        assert(s || len == 0);
86✔
467

468
        if (len == SIZE_MAX)
86✔
469
                len = strlen(s);
27✔
470

471
        if (len > (SIZE_MAX - 1) / 4)
86✔
472
                return NULL;
473

474
        t = buf = new(char, len * 4 + 1);
86✔
475
        if (!buf)
86✔
476
                return NULL;
477

478
        for (size_t i = 0; i < len; i++) {
1,058✔
479
                uint8_t u = (uint8_t) s[i];
972✔
480

481
                if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || (bad && strchr(bad, u))) {
972✔
482
                        *(t++) = '\\';
5✔
483
                        *(t++) = '0' + (u >> 6);
5✔
484
                        *(t++) = '0' + ((u >> 3) & 7);
5✔
485
                        *(t++) = '0' + (u & 7);
5✔
486
                } else
487
                        *(t++) = u;
967✔
488
        }
489

490
        *t = 0;
86✔
491
        return buf;
86✔
492
}
493

494
char* decescape(const char *s, size_t len, const char *bad) {
8✔
495
        char *buf, *t;
8✔
496

497
        /* Escapes all chars in bad, in addition to \ and " chars, in \nnn decimal style escaping. */
498

499
        assert(s || len == 0);
8✔
500

501
        if (len == SIZE_MAX)
8✔
502
                len = strlen(s);
6✔
503

504
        if (len > (SIZE_MAX - 1) / 4)
8✔
505
                return NULL;
506

507
        t = buf = new(char, len * 4 + 1);
8✔
508
        if (!buf)
8✔
509
                return NULL;
510

511
        for (size_t i = 0; i < len; i++) {
47✔
512
                uint8_t u = (uint8_t) s[i];
39✔
513

514
                if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || strchr(bad, u)) {
39✔
515
                        *(t++) = '\\';
20✔
516
                        *(t++) = '0' + (u / 100);
20✔
517
                        *(t++) = '0' + ((u / 10) % 10);
20✔
518
                        *(t++) = '0' + (u % 10);
20✔
519
                } else
520
                        *(t++) = u;
19✔
521
        }
522

523
        *t = 0;
8✔
524
        return buf;
8✔
525
}
526

527
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
200,454✔
528
        assert(bad);
200,454✔
529
        assert(t);
200,454✔
530
        assert(s);
200,454✔
531

532
        while (*s) {
3,893,865✔
533
                int l = utf8_encoded_valid_unichar(s, SIZE_MAX);
3,693,411✔
534

535
                if (char_is_cc(*s) || l < 0)
3,693,411✔
536
                        t += cescape_char(*(s++), t);
17,710✔
537
                else if (l == 1) {
3,675,701✔
538
                        if (*s == '\\' || strchr(bad, *s))
3,675,695✔
539
                                *(t++) = '\\';
4,540✔
540
                        *(t++) = *(s++);
3,675,695✔
541
                } else {
542
                        t = mempcpy(t, s, l);
6✔
543
                        s += l;
6✔
544
                }
545
        }
546

547
        return t;
200,454✔
548
}
549

550
char* shell_escape(const char *s, const char *bad) {
194,559✔
551
        char *buf, *t;
194,559✔
552

553
        buf = new(char, strlen(s)*4+1);
194,559✔
554
        if (!buf)
194,559✔
555
                return NULL;
556

557
        t = strcpy_backslash_escaped(buf, s, bad);
194,559✔
558
        *t = 0;
194,559✔
559

560
        return buf;
194,559✔
561
}
562

563
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
100,680✔
564
        const char *p;
100,680✔
565
        char *buf, *t;
100,680✔
566

567
        assert(s);
100,680✔
568

569
        /* Encloses a string in quotes if necessary to make it OK as a shell string. */
570

571
        if (FLAGS_SET(flags, SHELL_ESCAPE_EMPTY) && isempty(s))
100,680✔
572
                return strdup("\"\""); /* We don't use $'' here in the POSIX mode. "" is fine too. */
78✔
573

574
        for (p = s; *p; ) {
2,003,136✔
575
                int l = utf8_encoded_valid_unichar(p, SIZE_MAX);
1,908,429✔
576

577
                if (char_is_cc(*p) || l < 0 ||
1,908,429✔
578
                    strchr(WHITESPACE SHELL_NEED_QUOTES, *p))
1,908,393✔
579
                        break;
580

581
                p += l;
1,902,534✔
582
        }
583

584
        if (!*p)
100,602✔
585
                return strdup(s);
94,707✔
586

587
        buf = new(char, FLAGS_SET(flags, SHELL_ESCAPE_POSIX) + 1 + strlen(s)*4 + 1 + 1);
11,716✔
588
        if (!buf)
5,895✔
589
                return NULL;
590

591
        t = buf;
5,895✔
592
        if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX)) {
5,895✔
593
                *(t++) = '$';
74✔
594
                *(t++) = '\'';
74✔
595
        } else
596
                *(t++) = '"';
5,821✔
597

598
        t = mempcpy(t, s, p - s);
5,895✔
599

600
        t = strcpy_backslash_escaped(t, p,
11,716✔
601
                                     FLAGS_SET(flags, SHELL_ESCAPE_POSIX) ? SHELL_NEED_ESCAPE_POSIX : SHELL_NEED_ESCAPE);
602

603
        if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX))
5,895✔
604
                *(t++) = '\'';
74✔
605
        else
606
                *(t++) = '"';
5,821✔
607
        *t = 0;
5,895✔
608

609
        return str_realloc(buf);
5,895✔
610
}
611

612
char* quote_command_line(char * const *argv, ShellEscapeFlags flags) {
33,770✔
613
        _cleanup_free_ char *result = NULL;
33,770✔
614

615
        assert(argv);
33,770✔
616

617
        STRV_FOREACH(a, argv) {
133,464✔
618
                _cleanup_free_ char *t = NULL;
99,694✔
619

620
                t = shell_maybe_quote(*a, flags);
99,694✔
621
                if (!t)
99,694✔
622
                        return NULL;
623

624
                if (!strextend_with_separator(&result, " ", t))
99,694✔
625
                        return NULL;
626
        }
627

628
        return str_realloc(TAKE_PTR(result));
33,770✔
629
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc