mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Properly cleanup after copying dynamic-array to storage for packed types
This commit is contained in:
		
							parent
							
								
									87e1934bee
								
							
						
					
					
						commit
						1bdbc10110
					
				| @ -1,5 +1,8 @@ | |||||||
| ### 0.7.3 (unreleased) | ### 0.7.3 (unreleased) | ||||||
| 
 | 
 | ||||||
|  | Important Bugfixes: | ||||||
|  |  * Code Generator: Properly cleanup after copying dynamic-array to storage for packed types. | ||||||
|  | 
 | ||||||
| Compiler Features: | Compiler Features: | ||||||
|  * SMTChecker: Support ``addmod`` and ``mulmod``. |  * SMTChecker: Support ``addmod`` and ``mulmod``. | ||||||
|  * SMTChecker: Support array slices. |  * SMTChecker: Support array slices. | ||||||
|  | |||||||
| @ -290,7 +290,10 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons | |||||||
| 			// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
 | 			// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
 | ||||||
| 			_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP; | 			_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP; | ||||||
| 			// stack: target_ref target_data_end target_data_pos_updated
 | 			// stack: target_ref target_data_end target_data_pos_updated
 | ||||||
| 			utils.clearStorageLoop(targetBaseType); | 			if (targetBaseType->storageBytes() < 32) | ||||||
|  | 				utils.clearStorageLoop(TypeProvider::uint256()); | ||||||
|  | 			else | ||||||
|  | 				utils.clearStorageLoop(targetBaseType); | ||||||
| 			_context << Instruction::POP; | 			_context << Instruction::POP; | ||||||
| 		} | 		} | ||||||
| 	); | 	); | ||||||
| @ -922,6 +925,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const | |||||||
| 
 | 
 | ||||||
| void ArrayUtils::clearStorageLoop(TypePointer _type) const | void ArrayUtils::clearStorageLoop(TypePointer _type) const | ||||||
| { | { | ||||||
|  | 	solAssert(_type->storageBytes() >= 32, ""); | ||||||
| 	m_context.callLowLevelFunction( | 	m_context.callLowLevelFunction( | ||||||
| 		"$clearStorageLoop_" + _type->identifier(), | 		"$clearStorageLoop_" + _type->identifier(), | ||||||
| 		2, | 		2, | ||||||
|  | |||||||
| @ -633,8 +633,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores) | |||||||
| 	)"; | 	)"; | ||||||
| 	compileBothVersions(sourceCode); | 	compileBothVersions(sourceCode); | ||||||
| 	compareVersions("f()"); | 	compareVersions("f()"); | ||||||
| 	BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9); | 	BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8); | ||||||
| 	BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 8); | 	BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy) | BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy) | ||||||
|  | |||||||
| @ -0,0 +1,23 @@ | |||||||
|  | // Test to see if cleanup is performed properly during array copying | ||||||
|  | contract C { | ||||||
|  |     uint128[] x; | ||||||
|  |     function f() public returns(bool) { | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  |         uint128[] memory y = new uint128[](1); | ||||||
|  |         y[0] = 23; | ||||||
|  |         x = y; | ||||||
|  |         assembly { sstore(x.slot, 4) } | ||||||
|  | 
 | ||||||
|  |         assert(x[0] == 23); | ||||||
|  |         assert(x[1] == 0); | ||||||
|  | 
 | ||||||
|  |         assert(x[2] == 0); | ||||||
|  |         // Issue 9832: the cleanup was only performed for the first packed type leaving the rest of | ||||||
|  |         // the slot dirty. | ||||||
|  |         assert(x[3] == 0); | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // f() -> true | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | // Issue 9832: Test to see if cleanup is performed properly after array copying | ||||||
|  | contract C { | ||||||
|  |     uint40[] x; | ||||||
|  |     function f() public returns(bool) { | ||||||
|  | 
 | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  |         x.push(42); x.push(42); x.push(42); x.push(42); | ||||||
|  | 
 | ||||||
|  |         uint40[] memory y = new uint40[](1); | ||||||
|  |         y[0] = 23; | ||||||
|  |         x = y; | ||||||
|  | 
 | ||||||
|  |         assembly { sstore(x.slot, 20) } | ||||||
|  | 
 | ||||||
|  |         assert(x[0] == 23); | ||||||
|  |         assert(x[1] == 0); | ||||||
|  |         assert(x[2] == 0); | ||||||
|  |         assert(x[3] == 0); | ||||||
|  | 
 | ||||||
|  |         assert(x[4] == 0); | ||||||
|  |         assert(x[5] == 0); | ||||||
|  |         assert(x[6] == 0); | ||||||
|  |         assert(x[7] == 0); | ||||||
|  | 
 | ||||||
|  |         assert(x[8] == 0); | ||||||
|  |         assert(x[9] == 0); | ||||||
|  |         assert(x[10] == 0); | ||||||
|  |         assert(x[11] == 0); | ||||||
|  | 
 | ||||||
|  |         assert(x[12] == 0); | ||||||
|  |         assert(x[13] == 0); | ||||||
|  |         assert(x[14] == 0); | ||||||
|  |         assert(x[15] == 0); | ||||||
|  | 
 | ||||||
|  |         assert(x[16] == 0); | ||||||
|  |         assert(x[17] == 0); | ||||||
|  |         assert(x[18] == 0); | ||||||
|  |         assert(x[19] == 0); | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // f() -> true | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user