Coverage Report

Created: 2023-03-10 06:37

/src/fluent-bit/src/flb_sds.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2022 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
/*
21
 * The following SDS interface is a clone/strip-down version of the original
22
 * SDS library created by Antirez at https://github.com/antirez/sds.
23
 */
24
25
#include <fluent-bit/flb_compat.h>
26
#include <fluent-bit/flb_info.h>
27
#include <fluent-bit/flb_mem.h>
28
#include <fluent-bit/flb_log.h>
29
#include <fluent-bit/flb_sds.h>
30
#include <fluent-bit/flb_utf8.h>
31
32
#include <stdarg.h>
33
#include <ctype.h>
34
35
static flb_sds_t sds_alloc(size_t size)
36
168
{
37
168
    void *buf;
38
168
    flb_sds_t s;
39
168
    struct flb_sds *head;
40
41
168
    buf = flb_malloc(FLB_SDS_HEADER_SIZE + size + 1);
42
168
    if (!buf) {
43
0
        flb_errno();
44
0
        return NULL;
45
0
    }
46
47
168
    head = buf;
48
168
    head->len = 0;
49
168
    head->alloc = size;
50
51
168
    s = head->buf;
52
168
    *s = '\0';
53
54
168
    return s;
55
168
}
56
57
flb_sds_t flb_sds_create_len(const char *str, int len)
58
113
{
59
113
    flb_sds_t s;
60
113
    struct flb_sds *head;
61
62
113
    s = sds_alloc(len);
63
113
    if (!s) {
64
0
        return NULL;
65
0
    }
66
67
113
    if (str) {
68
113
        memcpy(s, str, len);
69
113
        s[len] = '\0';
70
71
113
        head = FLB_SDS_HEADER(s);
72
113
        head->len = len;
73
113
    }
74
113
    return s;
75
113
}
76
77
flb_sds_t flb_sds_create(const char *str)
78
71
{
79
71
    size_t len;
80
81
71
    if (!str) {
82
0
        len = 0;
83
0
    }
84
71
    else {
85
71
        len = strlen(str);
86
71
    }
87
88
71
    return flb_sds_create_len(str, len);
89
71
}
90
91
flb_sds_t flb_sds_create_size(size_t size)
92
55
{
93
55
    return sds_alloc(size);
94
55
}
95
96
/* Increase SDS buffer size 'len' bytes */
97
flb_sds_t flb_sds_increase(flb_sds_t s, size_t len)
98
0
{
99
0
    size_t new_size;
100
0
    struct flb_sds *head;
101
0
    flb_sds_t out;
102
0
    void *tmp;
103
104
0
    out = s;
105
0
    new_size = (FLB_SDS_HEADER_SIZE + flb_sds_alloc(s) + len + 1);
106
0
    head = FLB_SDS_HEADER(s);
107
0
    tmp = flb_realloc(head, new_size);
108
0
    if (!tmp) {
109
0
        flb_errno();
110
0
        return NULL;
111
0
    }
112
0
    head = (struct flb_sds *) tmp;
113
0
    head->alloc += len;
114
0
    out = head->buf;
115
116
0
    return out;
117
0
}
118
119
flb_sds_t flb_sds_cat(flb_sds_t s, const char *str, int len)
120
0
{
121
0
    size_t avail;
122
0
    struct flb_sds *head;
123
0
    flb_sds_t tmp = NULL;
124
125
0
    avail = flb_sds_avail(s);
126
0
    if (avail < len) {
127
0
        tmp = flb_sds_increase(s, len);
128
0
        if (!tmp) {
129
0
            return NULL;
130
0
        }
131
0
        s = tmp;
132
0
    }
133
0
    memcpy((char *) (s + flb_sds_len(s)), str, len);
134
135
0
    head = FLB_SDS_HEADER(s);
136
0
    head->len += len;
137
0
    s[head->len] = '\0';
138
139
0
    return s;
140
0
}
141
142
143
/*
144
 * remove empty spaces on left/right from sds buffer 's' and return the new length
145
 * of the content.
146
 */
147
int flb_sds_trim(flb_sds_t s)
148
0
{
149
0
    unsigned int i;
150
0
    unsigned int len;
151
0
    char *left = 0, *right = 0;
152
0
    char *buf;
153
154
0
    if (!s) {
155
0
        return -1;
156
0
    }
157
158
0
    len = flb_sds_len(s);
159
0
    if (len == 0) {
160
0
        return 0;
161
0
    }
162
163
0
    buf = s;
164
0
    left = buf;
165
166
    /* left spaces */
167
0
    while (left) {
168
0
        if (isspace(*left)) {
169
0
            left++;
170
0
        }
171
0
        else {
172
0
            break;
173
0
        }
174
0
    }
175
176
0
    right = buf + (len - 1);
177
    /* Validate right v/s left */
178
0
    if (right < left) {
179
0
        buf[0] = '\0';
180
0
        return -1;
181
0
    }
182
183
    /* Move back */
184
0
    while (right != buf){
185
0
        if (isspace(*right)) {
186
0
            right--;
187
0
        }
188
0
        else {
189
0
            break;
190
0
        }
191
0
    }
192
193
0
    len = (right - left) + 1;
194
0
    for (i=0; i<len; i++) {
195
0
        buf[i] = (char) left[i];
196
0
    }
197
0
    buf[i] = '\0';
198
0
    flb_sds_len_set(buf, i);
199
200
0
    return i;
201
0
}
202
203
int flb_sds_cat_safe(flb_sds_t *buf, const char *str, int len)
204
0
{
205
0
    flb_sds_t tmp;
206
207
0
    tmp = flb_sds_cat(*buf, str, len);
208
0
    if (!tmp) {
209
0
        return -1;
210
0
    }
211
0
    *buf = tmp;
212
0
    return 0;
213
0
}
214
215
flb_sds_t flb_sds_cat_esc(flb_sds_t s, const char *str, int len,
216
                                       char *esc, size_t esc_size)
217
0
{
218
0
    size_t avail;
219
0
    struct flb_sds *head;
220
0
    flb_sds_t tmp = NULL;
221
0
    uint32_t c;
222
0
    int i;
223
224
0
    avail = flb_sds_avail(s);
225
0
    if (avail < len) {
226
0
        tmp = flb_sds_increase(s, len);
227
0
        if (!tmp) {
228
0
            return NULL;
229
0
        }
230
0
        s = tmp;
231
0
    }
232
0
    head = FLB_SDS_HEADER(s);
233
234
0
    for (i = 0; i < len; i++) {
235
0
        if (flb_sds_avail(s) < 8) {
236
0
            tmp = flb_sds_increase(s, 8);
237
0
            if (tmp == NULL) {
238
0
                return NULL;
239
0
            }
240
0
            s = tmp;
241
0
            head = FLB_SDS_HEADER(s);
242
0
        }
243
0
        c = (unsigned char) str[i];
244
0
        if (esc != NULL && c < esc_size && esc[c] != 0) {
245
0
            s[head->len++] = '\\';
246
0
            s[head->len++] = esc[c];
247
0
        }
248
0
        else {
249
0
            s[head->len++] = c;
250
0
        }
251
0
    }
252
253
0
    s[head->len] = '\0';
254
255
0
    return s;
256
0
}
257
258
259
flb_sds_t flb_sds_copy(flb_sds_t s, const char *str, int len)
260
35
{
261
35
    size_t avail;
262
35
    struct flb_sds *head;
263
35
    flb_sds_t tmp = NULL;
264
265
35
    avail = flb_sds_alloc(s);
266
35
    if (avail < len) {
267
0
        tmp = flb_sds_increase(s, len);
268
0
        if (!tmp) {
269
0
            return NULL;
270
0
        }
271
0
        s = tmp;
272
0
    }
273
35
    memcpy((char *) s, str, len);
274
275
35
    head = FLB_SDS_HEADER(s);
276
35
    head->len = len;
277
35
    s[head->len] = '\0';
278
279
35
    return s;
280
35
}
281
282
flb_sds_t flb_sds_cat_utf8 (flb_sds_t *sds, const char *str, int str_len)
283
0
{
284
0
    static const char int2hex[] = "0123456789abcdef";
285
0
    int i;
286
0
    int b;
287
0
    int ret;
288
0
    int hex_bytes;
289
0
    uint32_t cp;
290
0
    uint32_t state = 0;
291
0
    unsigned char c;
292
0
    const uint8_t *p;
293
0
    struct flb_sds *head;
294
0
    flb_sds_t tmp;
295
0
    flb_sds_t s;
296
297
0
    s = *sds;
298
0
    head = FLB_SDS_HEADER(s);
299
300
0
    if (flb_sds_avail(s) <= str_len) {
301
0
        tmp = flb_sds_increase(s, str_len);
302
0
        if (tmp == NULL) {
303
0
            return NULL;
304
0
        }
305
0
        *sds = s = tmp;
306
0
        head = FLB_SDS_HEADER(s);
307
0
    }
308
309
0
    for (i = 0; i < str_len; i++) {
310
0
        if (flb_sds_avail(s) < 8) {
311
0
            tmp = flb_sds_increase(s, 8);
312
0
            if (tmp == NULL) {
313
0
                return NULL;
314
0
            }
315
0
            *sds = s = tmp;
316
0
            head = FLB_SDS_HEADER(s);
317
0
        }
318
319
0
        c = (unsigned char)str[i];
320
0
        if (c == '\\' || c == '"') {
321
0
            s[head->len++] = '\\';
322
0
            s[head->len++] = c;
323
0
        }
324
0
        else if (c >= '\b' && c <= '\r') {
325
0
            s[head->len++] = '\\';
326
0
            switch (c) {
327
0
            case '\n':
328
0
                s[head->len++] = 'n';
329
0
                break;
330
0
            case '\t':
331
0
                s[head->len++] = 't';
332
0
                break;
333
0
            case '\b':
334
0
                s[head->len++] = 'b';
335
0
                break;
336
0
            case '\f':
337
0
                s[head->len++] = 'f';
338
0
                break;
339
0
            case '\r':
340
0
                s[head->len++] = 'r';
341
0
                break;
342
0
            case '\v':
343
0
                s[head->len++] = 'u';
344
0
                s[head->len++] = '0';
345
0
                s[head->len++] = '0';
346
0
                s[head->len++] = '0';
347
0
                s[head->len++] = 'b';
348
0
                break;
349
0
            }
350
0
        }
351
0
        else if (c < 32 || c == 0x7f) {
352
0
            s[head->len++] = '\\';
353
0
            s[head->len++] = 'u';
354
0
            s[head->len++] = '0';
355
0
            s[head->len++] = '0';
356
0
            s[head->len++] = int2hex[ (unsigned char) ((c & 0xf0) >> 4)];
357
0
            s[head->len++] = int2hex[ (unsigned char) (c & 0x0f)];
358
0
        }
359
0
        else if (c >= 0x80) {
360
0
            hex_bytes = flb_utf8_len(str + i);
361
0
            state = FLB_UTF8_ACCEPT;
362
0
            cp = 0;
363
0
            for (b = 0; b < hex_bytes; b++) {
364
0
                p = (const unsigned char *) str + i + b;
365
0
                if (p >= (unsigned char *) (str + str_len)) {
366
0
                    break;
367
0
                }
368
0
                ret = flb_utf8_decode(&state, &cp, *p);
369
0
                if (ret == 0) {
370
0
                    break;
371
0
                }
372
0
            }
373
374
0
            if (state != FLB_UTF8_ACCEPT) {
375
                /* Invalid UTF-8 hex, just skip utf-8 bytes */
376
0
                flb_warn("[pack] invalid UTF-8 bytes, skipping");
377
0
                break;
378
0
            }
379
380
0
            s[head->len++] = '\\';
381
0
            s[head->len++] = 'u';
382
0
            if (cp > 0xFFFF) {
383
0
                c = (unsigned char) ((cp & 0xf00000) >> 20);
384
0
                if (c > 0) {
385
0
                    s[head->len++] = int2hex[c];
386
0
                }
387
0
                c = (unsigned char) ((cp & 0x0f0000) >> 16);
388
0
                if (c > 0) {
389
0
                    s[head->len++] = int2hex[c];
390
0
                }
391
0
            }
392
0
            s[head->len++] = int2hex[ (unsigned char) ((cp & 0xf000) >> 12)];
393
0
            s[head->len++] = int2hex[ (unsigned char) ((cp & 0x0f00) >> 8)];
394
0
            s[head->len++] = int2hex[ (unsigned char) ((cp & 0xf0) >> 4)];
395
0
            s[head->len++] = int2hex[ (unsigned char) (cp & 0x0f)];
396
0
            i += (hex_bytes - 1);
397
0
        }
398
0
        else {
399
0
            s[head->len++] = c;
400
0
        }
401
0
    }
402
403
0
    s[head->len] = '\0';
404
405
0
    return s;
406
0
}
407
408
flb_sds_t flb_sds_printf(flb_sds_t *sds, const char *fmt, ...)
409
0
{
410
0
    va_list ap;
411
0
    int len = strlen(fmt)*2;
412
0
    int size;
413
0
    flb_sds_t tmp = NULL;
414
0
    flb_sds_t s;
415
0
    struct flb_sds *head;
416
417
0
    if (len < 64) len = 64;
418
419
0
    s = *sds;
420
0
    if (flb_sds_avail(s)< len) {
421
0
        tmp = flb_sds_increase(s, len);
422
0
        if (!tmp) {
423
0
            return NULL;
424
0
        }
425
0
        *sds = s = tmp;
426
0
    }
427
428
0
    va_start(ap, fmt);
429
0
    size = vsnprintf((char *) (s + flb_sds_len(s)), flb_sds_avail(s), fmt, ap);
430
0
    if (size < 0) {
431
0
        flb_warn("[%s] buggy vsnprintf return %d", __FUNCTION__, size);
432
0
        va_end(ap);
433
0
        return NULL;
434
0
    }
435
0
    va_end(ap);
436
437
0
    if (size > flb_sds_avail(s)) {
438
0
        tmp = flb_sds_increase(s, size);
439
0
        if (!tmp) {
440
0
            return NULL;
441
0
        }
442
0
        *sds = s = tmp;
443
444
0
        va_start(ap, fmt);
445
0
        size = vsnprintf((char *) (s + flb_sds_len(s)), flb_sds_avail(s), fmt, ap);
446
0
        if (size > flb_sds_avail(s)) {
447
0
            flb_warn("[%s] vsnprintf is insatiable ", __FUNCTION__);
448
0
            va_end(ap);
449
0
            return NULL;
450
0
        }
451
0
        va_end(ap);
452
0
    }
453
454
0
    head = FLB_SDS_HEADER(s);
455
0
    head->len += size;
456
0
    s[head->len] = '\0';
457
458
0
    return s;
459
0
}
460
461
void flb_sds_destroy(flb_sds_t s)
462
4
{
463
4
    struct flb_sds *head;
464
465
4
    if (!s) {
466
0
        return;
467
0
    }
468
469
4
    head = FLB_SDS_HEADER(s);
470
4
    flb_free(head);
471
4
}
472
473
/*
474
 * flb_sds_snprintf is a wrapper of snprintf.
475
 * The difference is that this function can increase the buffer of flb_sds_t.
476
 */
477
int flb_sds_snprintf(flb_sds_t *str, size_t size, const char *fmt, ...)
478
0
{
479
0
    va_list va;
480
0
    flb_sds_t tmp;
481
0
    int ret;
482
483
0
 retry_snprintf:
484
0
    va_start(va, fmt);
485
0
    ret = vsnprintf(*str, size, fmt, va);
486
0
    if (ret > size) {
487
0
        tmp = flb_sds_increase(*str, ret-size);
488
0
        if (tmp == NULL) {
489
0
            return -1;
490
0
        }
491
0
        *str = tmp;
492
0
        size = ret;
493
0
        va_end(va);
494
0
        goto retry_snprintf;
495
0
    }
496
0
    va_end(va);
497
498
0
    flb_sds_len_set(*str, ret);
499
0
    return ret;
500
0
}