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