Coverage Report

Created: 2024-11-20 16:51

/root/doris/be/src/gutil/stringprintf.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2002 and onwards Google Inc.
2
3
#include "gutil/stringprintf.h"
4
5
#include <stdarg.h> // For va_list and related operations
6
#include <stdio.h>  // MSVC requires this for _vsnprintf
7
#include <vector>
8
#include <ostream>
9
10
using std::vector;
11
#include "common/logging.h"
12
13
// IWYU pragma: no_include <butil/macros.h>
14
#include "gutil/macros.h" // IWYU pragma: keep
15
16
#ifdef _MSC_VER
17
enum { IS__MSC_VER = 1 };
18
#else
19
enum { IS__MSC_VER = 0 };
20
#endif
21
22
753
void StringAppendV(string* dst, const char* format, va_list ap) {
23
    // First try with a small fixed size buffer
24
753
    static const int kSpaceLength = 1024;
25
753
    char space[kSpaceLength];
26
27
    // It's possible for methods that use a va_list to invalidate
28
    // the data in it upon use.  The fix is to make a copy
29
    // of the structure before using it and use that copy instead.
30
753
    va_list backup_ap;
31
753
    va_copy(backup_ap, ap);
32
753
    int result = vsnprintf(space, kSpaceLength, format, backup_ap);
33
753
    va_end(backup_ap);
34
35
753
    if (result < kSpaceLength) {
36
753
        if (result >= 0) {
37
            // Normal case -- everything fit.
38
753
            dst->append(space, result);
39
753
            return;
40
753
        }
41
42
0
        if (IS__MSC_VER) {
43
            // Error or MSVC running out of space.  MSVC 8.0 and higher
44
            // can be asked about space needed with the special idiom below:
45
0
            va_copy(backup_ap, ap);
46
0
            result = vsnprintf(nullptr, 0, format, backup_ap);
47
0
            va_end(backup_ap);
48
0
        }
49
50
0
        if (result < 0) {
51
            // Just an error.
52
0
            return;
53
0
        }
54
0
    }
55
56
    // Increase the buffer size to the size requested by vsnprintf,
57
    // plus one for the closing \0.
58
0
    int length = result + 1;
59
0
    auto buf = new char[length];
60
61
    // Restore the va_list before we use it again
62
0
    va_copy(backup_ap, ap);
63
0
    result = vsnprintf(buf, length, format, backup_ap);
64
0
    va_end(backup_ap);
65
66
0
    if (result >= 0 && result < length) {
67
        // It fit
68
0
        dst->append(buf, result);
69
0
    }
70
0
    delete[] buf;
71
0
}
72
73
697
string StringPrintf(const char* format, ...) {
74
697
    va_list ap;
75
697
    va_start(ap, format);
76
697
    string result;
77
697
    StringAppendV(&result, format, ap);
78
697
    va_end(ap);
79
697
    return result;
80
697
}
81
82
0
const string& SStringPrintf(string* dst, const char* format, ...) {
83
0
    va_list ap;
84
0
    va_start(ap, format);
85
0
    dst->clear();
86
0
    StringAppendV(dst, format, ap);
87
0
    va_end(ap);
88
0
    return *dst;
89
0
}
90
91
56
void StringAppendF(string* dst, const char* format, ...) {
92
56
    va_list ap;
93
56
    va_start(ap, format);
94
56
    StringAppendV(dst, format, ap);
95
56
    va_end(ap);
96
56
}
97
98
// Max arguments supported by StringPrintVector
99
const int kStringPrintfVectorMaxArgs = 32;
100
101
// An empty block of zero for filler arguments.  This is const so that if
102
// printf tries to write to it (via %n) then the program gets a SIGSEGV
103
// and we can fix the problem or protect against an attack.
104
static const char string_printf_empty_block[256] = {'\0'};
105
106
0
string StringPrintfVector(const char* format, const vector<string>& v) {
107
0
    CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
108
0
            << "StringPrintfVector currently only supports up to " << kStringPrintfVectorMaxArgs
109
0
            << " arguments. "
110
0
            << "Feel free to add support for more if you need it.";
111
112
    // Add filler arguments so that bogus format+args have a harder time
113
    // crashing the program, corrupting the program (%n),
114
    // or displaying random chunks of memory to users.
115
116
0
    const char* cstr[kStringPrintfVectorMaxArgs];
117
0
    for (int i = 0; i < v.size(); ++i) {
118
0
        cstr[i] = v[i].c_str();
119
0
    }
120
0
    for (int i = v.size(); i < arraysize(cstr); ++i) {
121
0
        cstr[i] = &string_printf_empty_block[0];
122
0
    }
123
124
    // I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
125
    // or any way to build a va_list by hand, or any API for printf
126
    // that accepts an array of arguments.  The best I can do is stick
127
    // this COMPILE_ASSERT right next to the actual statement.
128
129
0
    COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
130
0
    return StringPrintf(format, cstr[0], cstr[1], cstr[2], cstr[3], cstr[4], cstr[5], cstr[6],
131
0
                        cstr[7], cstr[8], cstr[9], cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
132
0
                        cstr[15], cstr[16], cstr[17], cstr[18], cstr[19], cstr[20], cstr[21],
133
0
                        cstr[22], cstr[23], cstr[24], cstr[25], cstr[26], cstr[27], cstr[28],
134
0
                        cstr[29], cstr[30], cstr[31]);
135
0
}