1 /*
2 This file is part of solidity.
3
4 solidity is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 solidity is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with solidity. If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 /**
19 * Unit tests for Solidity's ABI decoder.
20 */
21
22 #include <functional>
23 #include <string>
24 #include <tuple>
25 #include <boost/test/unit_test.hpp>
26 #include <liblangutil/Exceptions.h>
27 #include <test/libsolidity/SolidityExecutionFramework.h>
28
29 #include <test/libsolidity/ABITestsCommon.h>
30
31 using namespace std;
32 using namespace std::placeholders;
33 using namespace solidity::test;
34
35 namespace solidity::frontend::test
36 {
37
BOOST_FIXTURE_TEST_SUITE(ABIDecoderTest,SolidityExecutionFramework)38 BOOST_FIXTURE_TEST_SUITE(ABIDecoderTest, SolidityExecutionFramework)
39
40 BOOST_AUTO_TEST_CASE(value_types)
41 {
42 string sourceCode = R"(
43 contract C {
44 function f(uint a, uint16 b, uint24 c, int24 d, bytes3 x, bool e, C g) public returns (uint) {
45 if (a != 1) return 1;
46 if (b != 2) return 2;
47 if (c != 3) return 3;
48 if (d != 4) return 4;
49 if (x != "abc") return 5;
50 if (e != true) return 6;
51 if (g != this) return 7;
52 return 20;
53 }
54 }
55 )";
56 BOTH_ENCODERS(
57 compileAndRun(sourceCode);
58 ABI_CHECK(callContractFunction(
59 "f(uint256,uint16,uint24,int24,bytes3,bool,address)",
60 1, 2, 3, 4, string("abc"), true, m_contractAddress
61 ), encodeArgs(u256(20)));
62 )
63 }
64
BOOST_AUTO_TEST_CASE(decode_from_memory_simple)65 BOOST_AUTO_TEST_CASE(decode_from_memory_simple)
66 {
67 string sourceCode = R"(
68 contract C {
69 uint public _a;
70 uint[] public _b;
71 constructor(uint a, uint[] memory b) {
72 _a = a;
73 _b = b;
74 }
75 }
76 )";
77 BOTH_ENCODERS(
78 compileAndRun(sourceCode, 0, "C", encodeArgs(
79 7, 0x40,
80 // b
81 3, 0x21, 0x22, 0x23
82 ));
83 ABI_CHECK(callContractFunction("_a()"), encodeArgs(7));
84 ABI_CHECK(callContractFunction("_b(uint256)", 0), encodeArgs(0x21));
85 ABI_CHECK(callContractFunction("_b(uint256)", 1), encodeArgs(0x22));
86 ABI_CHECK(callContractFunction("_b(uint256)", 2), encodeArgs(0x23));
87 ABI_CHECK(callContractFunction("_b(uint256)", 3), encodeArgs());
88 )
89 }
90
BOOST_AUTO_TEST_CASE(decode_function_type)91 BOOST_AUTO_TEST_CASE(decode_function_type)
92 {
93 string sourceCode = R"(
94 contract D {
95 function () external returns (uint) public _a;
96 constructor(function () external returns (uint) a) {
97 _a = a;
98 }
99 }
100 contract C {
101 function f() public returns (uint) {
102 return 3;
103 }
104 function g(function () external returns (uint) _f) public returns (uint) {
105 return _f();
106 }
107 // uses "decode from memory"
108 function test1() public returns (uint) {
109 D d = new D(this.f);
110 return d._a()();
111 }
112 // uses "decode from calldata"
113 function test2() public returns (uint) {
114 return this.g(this.f);
115 }
116 }
117 )";
118 BOTH_ENCODERS(
119 compileAndRun(sourceCode, 0, "C");
120 ABI_CHECK(callContractFunction("test1()"), encodeArgs(3));
121 ABI_CHECK(callContractFunction("test2()"), encodeArgs(3));
122 )
123 }
124
BOOST_AUTO_TEST_CASE(decode_function_type_array)125 BOOST_AUTO_TEST_CASE(decode_function_type_array)
126 {
127 string sourceCode = R"(
128 contract D {
129 function () external returns (uint)[] public _a;
130 constructor(function () external returns (uint)[] memory a) {
131 _a = a;
132 }
133 }
134 contract E {
135 function () external returns (uint)[3] public _a;
136 constructor(function () external returns (uint)[3] memory a) {
137 _a = a;
138 }
139 }
140 contract C {
141 function f1() public returns (uint) {
142 return 1;
143 }
144 function f2() public returns (uint) {
145 return 2;
146 }
147 function f3() public returns (uint) {
148 return 3;
149 }
150 function g(function () external returns (uint)[] memory _f, uint i) public returns (uint) {
151 return _f[i]();
152 }
153 function h(function () external returns (uint)[3] memory _f, uint i) public returns (uint) {
154 return _f[i]();
155 }
156 // uses "decode from memory"
157 function test1_dynamic() public returns (uint) {
158 function () external returns (uint)[] memory x = new function() external returns (uint)[](4);
159 x[0] = this.f1;
160 x[1] = this.f2;
161 x[2] = this.f3;
162 D d = new D(x);
163 return d._a(2)();
164 }
165 function test1_static() public returns (uint) {
166 E e = new E([this.f1, this.f2, this.f3]);
167 return e._a(2)();
168 }
169 // uses "decode from calldata"
170 function test2_dynamic() public returns (uint) {
171 function () external returns (uint)[] memory x = new function() external returns (uint)[](3);
172 x[0] = this.f1;
173 x[1] = this.f2;
174 x[2] = this.f3;
175 return this.g(x, 0);
176 }
177 function test2_static() public returns (uint) {
178 return this.h([this.f1, this.f2, this.f3], 0);
179 }
180 }
181 )";
182 BOTH_ENCODERS(
183 compileAndRun(sourceCode, 0, "C");
184 ABI_CHECK(callContractFunction("test1_static()"), encodeArgs(3));
185 ABI_CHECK(callContractFunction("test1_dynamic()"), encodeArgs(3));
186 ABI_CHECK(callContractFunction("test2_static()"), encodeArgs(1));
187 ABI_CHECK(callContractFunction("test2_dynamic()"), encodeArgs(1));
188 )
189 }
190
BOOST_AUTO_TEST_CASE(decode_from_memory_complex)191 BOOST_AUTO_TEST_CASE(decode_from_memory_complex)
192 {
193 string sourceCode = R"(
194 contract C {
195 uint public _a;
196 uint[] public _b;
197 bytes[2] public _c;
198 constructor(uint a, uint[] memory b, bytes[2] memory c) {
199 _a = a;
200 _b = b;
201 _c = c;
202 }
203 }
204 )";
205 NEW_ENCODER(
206 compileAndRun(sourceCode, 0, "C", encodeArgs(
207 7, 0x60, 7 * 0x20,
208 // b
209 3, 0x21, 0x22, 0x23,
210 // c
211 0x40, 0x80,
212 8, string("abcdefgh"),
213 52, string("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ")
214 ));
215 ABI_CHECK(callContractFunction("_a()"), encodeArgs(7));
216 ABI_CHECK(callContractFunction("_b(uint256)", 0), encodeArgs(0x21));
217 ABI_CHECK(callContractFunction("_b(uint256)", 1), encodeArgs(0x22));
218 ABI_CHECK(callContractFunction("_b(uint256)", 2), encodeArgs(0x23));
219 ABI_CHECK(callContractFunction("_b(uint256)", 3), encodeArgs());
220 ABI_CHECK(callContractFunction("_c(uint256)", 0), encodeArgs(0x20, 8, string("abcdefgh")));
221 ABI_CHECK(callContractFunction("_c(uint256)", 1), encodeArgs(0x20, 52, string("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ")));
222 ABI_CHECK(callContractFunction("_c(uint256)", 2), encodeArgs());
223 )
224 }
225
BOOST_AUTO_TEST_CASE(short_input_value_type)226 BOOST_AUTO_TEST_CASE(short_input_value_type)
227 {
228 string sourceCode = R"(
229 contract C {
230 function f(uint a, uint b) public pure returns (uint) { return a; }
231 }
232 )";
233 BOTH_ENCODERS(
234 compileAndRun(sourceCode);
235 ABI_CHECK(callContractFunction("f(uint256,uint256)", 1, 2), encodeArgs(1));
236 ABI_CHECK(callContractFunctionNoEncoding("f(uint256,uint256)", bytes(64, 0)), encodeArgs(0));
237 ABI_CHECK(callContractFunctionNoEncoding("f(uint256,uint256)", bytes(63, 0)), encodeArgs());
238 )
239 }
240
BOOST_AUTO_TEST_CASE(short_input_array)241 BOOST_AUTO_TEST_CASE(short_input_array)
242 {
243 string sourceCode = R"(
244 contract C {
245 function f(uint[] memory a) public pure returns (uint) { return 7; }
246 }
247 )";
248 BOTH_ENCODERS(
249 compileAndRun(sourceCode);
250 ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 0)), encodeArgs(7));
251 ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1)), encodeArgs());
252 ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1) + bytes(31, 0)), encodeArgs());
253 ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 1) + bytes(32, 0)), encodeArgs(7));
254 ABI_CHECK(callContractFunctionNoEncoding("f(uint256[])", encodeArgs(0x20, 2, 5, 6)), encodeArgs(7));
255 )
256 }
257
BOOST_AUTO_TEST_CASE(short_dynamic_input_array)258 BOOST_AUTO_TEST_CASE(short_dynamic_input_array)
259 {
260 string sourceCode = R"(
261 contract C {
262 function f(bytes[1] memory a) public pure returns (uint) { return 7; }
263 }
264 )";
265 NEW_ENCODER(
266 compileAndRun(sourceCode);
267 ABI_CHECK(callContractFunctionNoEncoding("f(bytes[1])", encodeArgs(0x20)), encodeArgs());
268 )
269 }
270
BOOST_AUTO_TEST_CASE(short_input_bytes)271 BOOST_AUTO_TEST_CASE(short_input_bytes)
272 {
273 string sourceCode = R"(
274 contract C {
275 function e(bytes memory a) public pure returns (uint) { return 7; }
276 function f(bytes[] memory a) public pure returns (uint) { return 7; }
277 }
278 )";
279 NEW_ENCODER(
280 compileAndRun(sourceCode);
281 ABI_CHECK(callContractFunctionNoEncoding("e(bytes)", encodeArgs(0x20, 7) + bytes(5, 0)), encodeArgs());
282 ABI_CHECK(callContractFunctionNoEncoding("e(bytes)", encodeArgs(0x20, 7) + bytes(6, 0)), encodeArgs());
283 ABI_CHECK(callContractFunctionNoEncoding("e(bytes)", encodeArgs(0x20, 7) + bytes(7, 0)), encodeArgs(7));
284 ABI_CHECK(callContractFunctionNoEncoding("e(bytes)", encodeArgs(0x20, 7) + bytes(8, 0)), encodeArgs(7));
285 ABI_CHECK(callContractFunctionNoEncoding("f(bytes[])", encodeArgs(0x20, 1, 0x20, 7) + bytes(5, 0)), encodeArgs());
286 ABI_CHECK(callContractFunctionNoEncoding("f(bytes[])", encodeArgs(0x20, 1, 0x20, 7) + bytes(6, 0)), encodeArgs());
287 ABI_CHECK(callContractFunctionNoEncoding("f(bytes[])", encodeArgs(0x20, 1, 0x20, 7) + bytes(7, 0)), encodeArgs(7));
288 ABI_CHECK(callContractFunctionNoEncoding("f(bytes[])", encodeArgs(0x20, 1, 0x20, 7) + bytes(8, 0)), encodeArgs(7));
289 )
290 }
291
BOOST_AUTO_TEST_CASE(validation_int_inside_arrays)292 BOOST_AUTO_TEST_CASE(validation_int_inside_arrays)
293 {
294 string sourceCode = R"(
295 contract C {
296 enum E { A, B }
297 function f(uint16[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } }
298 function g(int16[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } }
299 function h(E[] memory a) public pure returns (uint r) { assembly { r := mload(add(a, 0x20)) } }
300 }
301 )";
302 NEW_ENCODER(
303 compileAndRun(sourceCode);
304 ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, 7), encodeArgs(7));
305 ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, 7), encodeArgs(7));
306 ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, u256("0xffff")), encodeArgs(u256("0xffff")));
307 ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0xffff")), encodeArgs());
308 ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, u256("0x1ffff")), encodeArgs());
309 ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0x10fff")), encodeArgs());
310 ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 0), encodeArgs(u256(0)));
311 ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 1), encodeArgs(u256(1)));
312 ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 2), encodeArgs());
313 )
314 }
315
BOOST_AUTO_TEST_CASE(validation_function_type)316 BOOST_AUTO_TEST_CASE(validation_function_type)
317 {
318 string sourceCode = R"(
319 contract C {
320 function f(function () external) public pure returns (uint r) { r = 1; }
321 function g(function () external[] memory) public pure returns (uint r) { r = 2; }
322 function h(function () external[] calldata) external pure returns (uint r) { r = 3; }
323 function i(function () external[] calldata a) external pure returns (uint r) { a[0]; r = 4; }
324 }
325 )";
326 bool newDecoder = false;
327 string validFun{"01234567890123456789abcd"};
328 string invalidFun{"01234567890123456789abcdX"};
329 BOTH_ENCODERS(
330 compileAndRun(sourceCode);
331 ABI_CHECK(callContractFunction("f(function)", validFun), encodeArgs(1));
332 ABI_CHECK(callContractFunction("f(function)", invalidFun), newDecoder ? bytes{} : encodeArgs(1));
333 ABI_CHECK(callContractFunction("g(function[])", 0x20, 1, validFun), encodeArgs(2));
334 ABI_CHECK(callContractFunction("g(function[])", 0x20, 1, invalidFun), newDecoder ? bytes{} : encodeArgs(2));
335 ABI_CHECK(callContractFunction("h(function[])", 0x20, 1, validFun), encodeArgs(3));
336 // No failure because the data is not accessed.
337 ABI_CHECK(callContractFunction("h(function[])", 0x20, 1, invalidFun), encodeArgs(3));
338 ABI_CHECK(callContractFunction("i(function[])", 0x20, 1, validFun), encodeArgs(4));
339 ABI_CHECK(callContractFunction("i(function[])", 0x20, 1, invalidFun), newDecoder ? bytes{} : encodeArgs(4));
340 newDecoder = true;
341 )
342 }
343
BOOST_AUTO_TEST_CASE(struct_short)344 BOOST_AUTO_TEST_CASE(struct_short)
345 {
346 string sourceCode = R"(
347 contract C {
348 struct S { int a; uint b; bytes16 c; }
349 function f(S memory s) public pure returns (S memory q) {
350 q = s;
351 }
352 }
353 )";
354 NEW_ENCODER(
355 compileAndRun(sourceCode, 0, "C");
356 ABI_CHECK(
357 callContractFunction("f((int256,uint256,bytes16))", 0xff010, 0xff0002, "abcd"),
358 encodeArgs(0xff010, 0xff0002, "abcd")
359 );
360 ABI_CHECK(
361 callContractFunctionNoEncoding("f((int256,uint256,bytes16))", encodeArgs(0xff010, 0xff0002) + bytes(32, 0)),
362 encodeArgs(0xff010, 0xff0002, 0)
363 );
364 ABI_CHECK(
365 callContractFunctionNoEncoding("f((int256,uint256,bytes16))", encodeArgs(0xff010, 0xff0002) + bytes(31, 0)),
366 encodeArgs()
367 );
368 )
369 }
370
BOOST_AUTO_TEST_CASE(complex_struct)371 BOOST_AUTO_TEST_CASE(complex_struct)
372 {
373 string sourceCode = R"(
374 contract C {
375 enum E {A, B, C}
376 struct T { uint x; E e; uint8 y; }
377 struct S { C c; T[] t;}
378 function f(uint a, S[2] memory s1, S[] memory s2, uint b) public returns
379 (uint r1, C r2, uint r3, uint r4, C r5, uint r6, E r7, uint8 r8) {
380 r1 = a;
381 r2 = s1[0].c;
382 r3 = b;
383 r4 = s2.length;
384 r5 = s2[1].c;
385 r6 = s2[1].t.length;
386 r7 = s2[1].t[1].e;
387 r8 = s2[1].t[1].y;
388 }
389 }
390 )";
391 NEW_ENCODER(
392 compileAndRun(sourceCode, 0, "C");
393 string sig = "f(uint256,(address,(uint256,uint8,uint8)[])[2],(address,(uint256,uint8,uint8)[])[],uint256)";
394 bytes args = encodeArgs(
395 7, 0x80, 0x1e0, 8,
396 // S[2] s1
397 0x40,
398 0x100,
399 // S s1[0]
400 m_contractAddress,
401 0x40,
402 // T s1[0].t
403 1, // length
404 // s1[0].t[0]
405 0x11, 1, 0x12,
406 // S s1[1]
407 0, 0x40,
408 // T s1[1].t
409 0,
410 // S[] s2 (0x1e0)
411 2, // length
412 0x40, 0xa0,
413 // S s2[0]
414 0, 0x40, 0,
415 // S s2[1]
416 0x1234, 0x40,
417 // s2[1].t
418 3, // length
419 0, 0, 0,
420 0x21, 2, 0x22,
421 0, 0, 0
422 );
423 ABI_CHECK(callContractFunction(sig, args), encodeArgs(7, m_contractAddress, 8, 2, 0x1234, 3, 2, 0x22));
424 // invalid enum value
425 args.data()[0x20 * 28] = 3;
426 ABI_CHECK(callContractFunction(sig, args), encodeArgs());
427 )
428 }
429
430 BOOST_AUTO_TEST_SUITE_END()
431
432 } // end namespaces
433