/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 | | |