Coverage Report

Created: 2023-09-25 06:15

/src/cppcheck/oss-fuzz/type2.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Cppcheck - A tool for static C/C++ code analysis
3
 * Copyright (C) 2007-2022 Cppcheck team.
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "type2.h"
20
21
#include <cstring>
22
#include <sstream>
23
24
static int getValue(const uint8_t *data, size_t dataSize, uint8_t maxValue, bool *done = nullptr)
25
41.5k
{
26
41.5k
    static size_t pos;    // current "data" position
27
41.5k
    static int dataValue; // value extracted from data
28
41.5k
    static int ones;      // ones. This variable tracks if we need to add more stuff in "dataValue".
29
30
    // Shift more bits from "data" into "dataValue" if needed
31
51.5k
    while (pos < dataSize && ones < 0xFFFF) {
32
9.98k
        ones = (ones << 8) | 0xff;
33
9.98k
        dataValue = (dataValue << 8) | data[pos];
34
9.98k
        pos++;
35
9.98k
    }
36
37
41.5k
    if (done)
38
6.50k
        *done = (ones == 0);
39
40
41.5k
    if (maxValue == 0)
41
1.47k
        return 0;
42
43
    // Shift out info from "dataValue" using % . Using & and >> would work but then we are limited to "power of 2" max value.
44
40.0k
    const int ret = dataValue % maxValue;
45
40.0k
    ones /= maxValue;
46
40.0k
    dataValue /= maxValue;
47
40.0k
    return ret;
48
41.5k
}
49
50
static std::string generateExpression2_lvalue(const uint8_t *data, size_t dataSize)
51
5.08k
{
52
5.08k
    return "var" + std::to_string(1 + getValue(data, dataSize, 5));
53
5.08k
}
54
55
static std::string generateExpression2_Op(const uint8_t *data, size_t dataSize, uint8_t numberOfGlobalConstants)
56
6.15k
{
57
6.15k
    std::ostringstream code;
58
6.15k
    switch (getValue(data, dataSize, 3)) {
59
3.26k
    case 0:
60
3.26k
        code << generateExpression2_lvalue(data, dataSize);
61
3.26k
        break;
62
1.47k
    case 1:
63
1.47k
        code << "globalconstant" << (1 + getValue(data, dataSize, numberOfGlobalConstants));
64
1.47k
        break;
65
1.41k
    case 2:
66
1.41k
        code << (getValue(data, dataSize, 0x80) * 0x80 + getValue(data, dataSize, 0x80));
67
1.41k
        break;
68
6.15k
    }
69
6.15k
    return code.str();
70
6.15k
}
71
72
static std::string generateExpression2_Expr(const uint8_t *data, size_t dataSize, uint8_t numberOfGlobalConstants, int depth=0)
73
12.2k
{
74
12.2k
    ++depth;
75
12.2k
    const int type = (depth > 3) ? 0 : getValue(data, dataSize, 3);
76
12.2k
    const char binop[] = "=<>+-*/%&|^";
77
12.2k
    const char *unop[] = {"++","--","()","~"};
78
79
12.2k
    switch (type) {
80
6.15k
    case 0:
81
6.15k
        return generateExpression2_Op(data, dataSize, numberOfGlobalConstants);
82
3.11k
    case 1: {
83
3.11k
        const char op = binop[getValue(data,dataSize,sizeof(binop)-1)];
84
3.11k
        const std::string lhs = (op == '=') ?
85
374
                                generateExpression2_lvalue(data, dataSize) :
86
3.11k
                                generateExpression2_Expr(data, dataSize, numberOfGlobalConstants, depth);
87
3.11k
        const std::string rhs = generateExpression2_Expr(data, dataSize, numberOfGlobalConstants, depth);
88
89
3.11k
        std::string ret = lhs + op + rhs;
90
3.11k
        if (depth > 1 && op == '=')
91
197
            ret = "(" + ret + ")";
92
93
3.11k
        return ret;
94
0
    }
95
2.94k
    case 2: {
96
2.94k
        const char *u = unop[getValue(data,dataSize,sizeof(unop)/sizeof(*unop))];
97
2.94k
        if (strcmp(u, "()") == 0)
98
725
            return "(" + generateExpression2_Expr(data, dataSize, numberOfGlobalConstants, depth) + ")";
99
2.21k
        else if (strcmp(u, "++") == 0 || strcmp(u, "--") == 0)
100
1.44k
            return u + generateExpression2_lvalue(data, dataSize);
101
771
        return u + generateExpression2_Expr(data, dataSize, numberOfGlobalConstants, depth);
102
2.94k
    }
103
0
    default:
104
0
        break;
105
12.2k
    }
106
107
0
    return "0";
108
12.2k
}
109
110
111
static std::string generateExpression2_Cond(const uint8_t *data, size_t dataSize, uint8_t numberOfGlobalConstants)
112
1.38k
{
113
1.38k
    const char *comp[] = {"==", "!=", "<", "<=", ">", ">="};
114
1.38k
    const int i = getValue(data, dataSize, 6);
115
1.38k
    const std::string lhs = generateExpression2_Expr(data, dataSize, numberOfGlobalConstants);
116
1.38k
    const std::string rhs = generateExpression2_Expr(data, dataSize, numberOfGlobalConstants);
117
1.38k
    return lhs + comp[i] + rhs;
118
1.38k
}
119
120
121
static std::string functionStart()
122
1.74k
{
123
1.74k
    static int functionNumber;
124
1.74k
    return "int f" + std::to_string(++functionNumber) + "()\n"
125
1.74k
           "{\n";
126
1.74k
}
127
128
static std::string generateExpression2_conditionalCode(const std::string &indent,
129
                                                       const uint8_t *data,
130
                                                       size_t dataSize,
131
                                                       uint8_t numberOfGlobalConstants)
132
3.20k
{
133
3.20k
    std::ostringstream code;
134
135
3.20k
    if (indent.empty())
136
1.36k
        code << functionStart();
137
1.84k
    else
138
1.84k
        code << indent << "{\n";
139
140
6.50k
    for (int line = 0; line < 4 || indent.empty(); ++line) {
141
6.50k
        bool done = false;
142
6.50k
        const int type1 = getValue(data, dataSize, 8, &done);
143
6.50k
        if (done)
144
3.02k
            break;
145
146
3.47k
        const int mostLikelyType = (line >= 2) ? 4 : 0;  // should var assignment or return be more likely?
147
148
3.47k
        const int type2 = (indent.size() >= 12) ?
149
162
                          mostLikelyType :  // max indentation, no inner conditions
150
3.47k
                          ((type1 >= 5) ? mostLikelyType : type1);
151
152
3.47k
        if (type2 == 0) {
153
1.53k
            code << indent << "    var" << getValue(data, dataSize, 5) << "=" << generateExpression2_Expr(data, dataSize, numberOfGlobalConstants) << ";\n";
154
1.94k
        } else if (type2 == 1) {
155
462
            code << indent << "    if (" << generateExpression2_Cond(data, dataSize, numberOfGlobalConstants) << ")\n";
156
462
            code << generateExpression2_conditionalCode(indent + "    ", data, dataSize, numberOfGlobalConstants);
157
1.48k
        } else if (type2 == 2) {
158
458
            code << indent << "    if (" << generateExpression2_Cond(data, dataSize, numberOfGlobalConstants) << ")\n";
159
458
            code << generateExpression2_conditionalCode(indent + "    ", data, dataSize, numberOfGlobalConstants);
160
458
            code << indent << "    else\n";
161
458
            code << generateExpression2_conditionalCode(indent + "    ", data, dataSize, numberOfGlobalConstants);
162
1.02k
        } else if (type2 == 3) {
163
468
            code << indent << "    while (" << generateExpression2_Cond(data, dataSize, numberOfGlobalConstants) << ")\n";
164
468
            code << generateExpression2_conditionalCode(indent + "    ", data, dataSize, numberOfGlobalConstants);
165
554
        } else if (type2 == 4) {
166
554
            code << indent << "    return " << generateExpression2_Expr(data, dataSize, numberOfGlobalConstants) << ";\n";
167
554
            if (indent.empty())
168
378
                code << "}\n\n" << functionStart();
169
176
            else
170
176
                break;
171
554
        }
172
3.47k
    }
173
174
3.20k
    if (!indent.empty())
175
1.84k
        code << indent << "}\n";
176
1.36k
    else
177
1.36k
        code << "    return 0;\n}\n";
178
3.20k
    return code.str();
179
3.20k
}
180
181
std::string generateCode2(const uint8_t *data, size_t dataSize)
182
1.36k
{
183
1.36k
    std::ostringstream code;
184
185
    // create global constants
186
1.36k
    constexpr uint8_t numberOfGlobalConstants = 0;
187
    /*
188
       const int numberOfGlobalConstants = getValue(data, dataSize, 5);
189
       for (int nr = 1; nr <= numberOfGlobalConstants; nr++) {
190
        const char *types[4] = {"char", "int", "long long", "float"};
191
        code << "const " << types[getValue(data, dataSize, 4)] << " globalconstant" << nr << " = " << generateExpression2_Expr(data, dataSize, nr - 1) << ";\n";
192
       }
193
     */
194
195
1.36k
    code << "int var1 = 1;\n"
196
1.36k
        "int var2 = 0;\n"
197
1.36k
        "int var3 = 1;\n"
198
1.36k
        "int var4 = 0;\n"
199
1.36k
        "int var5 = -1;\n\n";
200
201
1.36k
    code << generateExpression2_conditionalCode("", data, dataSize, numberOfGlobalConstants);
202
203
1.36k
    return code.str();
204
1.36k
}
205
206