From 2aea4d068fd280bbd0a1a9cdc67e4d1ca75028ce Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Tue, 30 Jul 2024 18:24:20 +0530 Subject: [PATCH] Detector: Storage signed integer array (#624) Co-authored-by: Alex Roan --- Cargo.lock | 24 ++ aderyn_core/Cargo.toml | 3 +- aderyn_core/src/detect/detector.rs | 32 +-- aderyn_core/src/detect/high/mod.rs | 2 + .../high/storage_signed_integer_array.rs | 206 ++++++++++++++++++ .../adhoc-sol-files-highs-only-report.json | 1 + reports/report.json | 42 +++- reports/report.md | 61 +++++- reports/report.sarif | 53 +++++ .../CompilerBugStorageSignedIntegerArray.sol | 17 ++ 10 files changed, 398 insertions(+), 43 deletions(-) create mode 100644 aderyn_core/src/detect/high/storage_signed_integer_array.rs create mode 100644 tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol diff --git a/Cargo.lock b/Cargo.lock index 6db72ae99..d7ac1aa65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,7 @@ dependencies = [ "derive_more", "eyre", "ignore", + "lazy-regex", "once_cell", "phf", "prettytable", @@ -1968,6 +1969,29 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "lazy-regex" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576c8060ecfdf2e56995cf3274b4f2d71fa5e4fa3607c1c0b63c10180ee58741" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9efb9e65d4503df81c615dc33ff07042a9408ac7f26b45abee25566f7fbfd12c" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.67", +] + [[package]] name = "lazy_static" version = "1.5.0" diff --git a/aderyn_core/Cargo.toml b/aderyn_core/Cargo.toml index 5465f15b1..008e4c1d5 100644 --- a/aderyn_core/Cargo.toml +++ b/aderyn_core/Cargo.toml @@ -23,8 +23,9 @@ serde_repr = "0.1.12" strum = { version = "0.26", features = ["derive"] } toml = "0.8.2" cyfrin-foundry-compilers = { version = "0.3.20-aderyn", features = ["svm-solc"] } +lazy-regex = "3.2.0" derive_more = "0.99.18" [dev-dependencies] serial_test = "3.0.0" -once_cell = "1.19.0" \ No newline at end of file +once_cell = "1.19.0" diff --git a/aderyn_core/src/detect/detector.rs b/aderyn_core/src/detect/detector.rs index c2f5dd464..048fdef7e 100644 --- a/aderyn_core/src/detect/detector.rs +++ b/aderyn_core/src/detect/detector.rs @@ -5,33 +5,6 @@ use crate::{ ast::NodeID, context::workspace_context::WorkspaceContext, detect::{high::*, low::*}, - detect::{ - high::{ - ArbitraryTransferFromDetector, AvoidAbiEncodePackedDetector, - BlockTimestampDeadlineDetector, DangerousUnaryOperatorDetector, - DelegateCallInLoopDetector, DynamicArrayLengthAssignmentDetector, - EnumerableLoopRemovalDetector, ExperimentalEncoderDetector, - IncorrectShiftOrderDetector, IncorrectUseOfCaretOperatorDetector, - MultipleConstructorsDetector, NestedStructInMappingDetector, RTLODetector, - ReusedContractNameDetector, SelfdestructIdentifierDetector, - StateVariableShadowingDetector, StorageArrayEditWithMemoryDetector, - TautologicalCompareDetector, UncheckedReturnDetector, - UninitializedStateVariableDetector, UnprotectedInitializerDetector, - UnsafeCastingDetector, YulReturnDetector, - }, - low::{ - CentralizationRiskDetector, ConstantsInsteadOfLiteralsDetector, - ContractsWithTodosDetector, DeprecatedOZFunctionsDetector, - DivisionBeforeMultiplicationDetector, EcrecoverDetector, EmptyBlockDetector, - InconsistentTypeNamesDetector, LargeLiteralValueDetector, - NonReentrantBeforeOthersDetector, PushZeroOpcodeDetector, RedundantStatementsDetector, - RequireWithStringDetector, RevertsAndRequiresInLoopsDetector, - SolmateSafeTransferLibDetector, UnindexedEventsDetector, UnsafeERC20FunctionsDetector, - UnsafeERC721MintDetector, UnspecificSolidityPragmaDetector, UselessErrorDetector, - UselessInternalFunctionDetector, UselessModifierDetector, - UselessPublicFunctionDetector, ZeroAddressCheckDetector, - }, - }, }; use std::{ @@ -93,6 +66,7 @@ pub fn get_all_issue_detectors() -> Vec> { Box::::default(), Box::::default(), Box::::default(), + Box::::default(), Box::::default(), Box::::default(), Box::::default(), @@ -160,6 +134,7 @@ pub(crate) enum IssueDetectorNamePool { RTLO, UncheckedReturn, DangerousUnaryOperator, + SignedStorageArray, RedundantStatements, PublicVariableReadInExternalContext, WeakRandomness, @@ -301,6 +276,9 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option { Some(Box::::default()) } + IssueDetectorNamePool::SignedStorageArray => { + Some(Box::::default()) + } IssueDetectorNamePool::RedundantStatements => { Some(Box::::default()) } diff --git a/aderyn_core/src/detect/high/mod.rs b/aderyn_core/src/detect/high/mod.rs index 1e9e9912f..2021881f2 100644 --- a/aderyn_core/src/detect/high/mod.rs +++ b/aderyn_core/src/detect/high/mod.rs @@ -20,6 +20,7 @@ pub(crate) mod selfdestruct; pub(crate) mod send_ether_no_checks; pub(crate) mod state_variable_shadowing; pub(crate) mod storage_array_edit_with_memory; +pub(crate) mod storage_signed_integer_array; pub(crate) mod tautological_compare; pub(crate) mod unchecked_return; pub(crate) mod unchecked_send; @@ -51,6 +52,7 @@ pub use selfdestruct::SelfdestructIdentifierDetector; pub use send_ether_no_checks::SendEtherNoChecksDetector; pub use state_variable_shadowing::StateVariableShadowingDetector; pub use storage_array_edit_with_memory::StorageArrayEditWithMemoryDetector; +pub use storage_signed_integer_array::StorageSignedIntegerArrayDetector; pub use tautological_compare::TautologicalCompareDetector; pub use unchecked_return::UncheckedReturnDetector; pub use unchecked_send::UncheckedSendDetector; diff --git a/aderyn_core/src/detect/high/storage_signed_integer_array.rs b/aderyn_core/src/detect/high/storage_signed_integer_array.rs new file mode 100644 index 000000000..e1acde91d --- /dev/null +++ b/aderyn_core/src/detect/high/storage_signed_integer_array.rs @@ -0,0 +1,206 @@ +use std::collections::BTreeMap; +use std::error::Error; +use std::str::FromStr; + +use crate::ast::{ + ASTNode, Expression, Identifier, NodeID, TupleExpression, TypeDescriptions, UnaryOperation, +}; + +use crate::capture; +use crate::context::browser::{ + ExtractPragmaDirectives, ExtractTupleExpressions, GetImmediateParent, +}; +use crate::detect::detector::IssueDetectorNamePool; +use crate::detect::helpers; +use crate::{ + context::workspace_context::WorkspaceContext, + detect::detector::{IssueDetector, IssueSeverity}, +}; +use eyre::Result; +use lazy_regex::regex; +use semver::{Version, VersionReq}; + +#[derive(Default)] +pub struct StorageSignedIntegerArrayDetector { + // Keys are: [0] source file name, [1] line number, [2] character location of node. + // Do not add items manually, use `capture!` to add nodes to this BTreeMap. + found_instances: BTreeMap<(String, usize, String), NodeID>, +} + +impl IssueDetector for StorageSignedIntegerArrayDetector { + fn detect(&mut self, context: &WorkspaceContext) -> Result> { + for source_unit in context.source_units() { + let tuple_expressions = ExtractTupleExpressions::from(source_unit).extracted; + let pragma_directives = ExtractPragmaDirectives::from(source_unit).extracted; + + if let Some(pragma_directive) = pragma_directives.first() { + if let Ok(pragma_semver) = helpers::pragma_directive_to_semver(pragma_directive) { + if version_req_allows_below_0_5_10(&pragma_semver) { + // Search for a literal array with one negative value in it + for tuple_expression in tuple_expressions + .into_iter() + .filter(|tuple_expression| tuple_expression.is_inline_array) + { + // First, make sure it's being assigned to an array pointer to storage + if !is_tuple_being_assigned_to_storage_array(&tuple_expression, context) + { + continue; + } + + // Now, make sure there is at least 1 negative value in the tuple array + let negative_component_present = + tuple_expression.components.iter().any(|c| { + if let Some(Expression::UnaryOperation(UnaryOperation { + operator, + .. + })) = c + { + return operator == "-"; + } + false + }); + + if negative_component_present { + capture!(self, context, tuple_expression); + } + } + } + } + } + } + + Ok(!self.found_instances.is_empty()) + } + + fn severity(&self) -> IssueSeverity { + IssueSeverity::High + } + + fn title(&self) -> String { + String::from( + "Compiler Bug: Signed array in storage detected for compiler version `<0.5.10`", + ) + } + + fn description(&self) -> String { + String::from("If you want to leverage signed arrays in storage by assigning a literal array with at least one negative \ + number, then you mus use solidity version 0.5.10 or above. This is because of a bug in older compilers.") + } + + fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> { + self.found_instances.clone() + } + + fn name(&self) -> String { + IssueDetectorNamePool::SignedStorageArray.to_string() + } +} + +fn version_req_allows_below_0_5_10(version_req: &VersionReq) -> bool { + // If it matches any 0.4.0 to 0.4.26, return true + for i in 0..=26 { + let version = Version::from_str(&format!("0.4.{}", i)).unwrap(); + if version_req.matches(&version) { + return true; + } + } + + // If it matches any 0.5.0 to 0.5.9 return true + for i in 0..=9 { + let version = Version::from_str(&format!("0.5.{}", i)).unwrap(); + if version_req.matches(&version) { + return true; + } + } + + // Else, return false + false +} + +// Build a regular expression to catch type names that correspond to pointers to storage arrays +static SIGNED_STORAGE_ARRAY_POINTER: &lazy_regex::Lazy = + regex!(r"^int[0-9]*\[[0-9]*] storage ref$"); + +fn is_tuple_being_assigned_to_storage_array( + tuple_expression: &TupleExpression, + context: &WorkspaceContext, +) -> bool { + if let Some(ASTNode::Assignment(assignment)) = tuple_expression.parent(context) { + if let Expression::Identifier(Identifier { + type_descriptions: + TypeDescriptions { + type_string: Some(type_string), + .. + }, + .. + }) = assignment.left_hand_side.as_ref() + { + if SIGNED_STORAGE_ARRAY_POINTER.is_match(type_string) { + return true; + } + } + } + false +} + +#[cfg(test)] +mod storage_signed_array_detector { + use serial_test::serial; + + use crate::detect::{ + detector::IssueDetector, + high::storage_signed_integer_array::{ + StorageSignedIntegerArrayDetector, SIGNED_STORAGE_ARRAY_POINTER, + }, + }; + + #[test] + #[serial] + fn test_storage_signed_array() { + let context = crate::detect::test_utils::load_solidity_source_unit( + "../tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol", + ); + + let mut detector = StorageSignedIntegerArrayDetector::default(); + let found = detector.detect(&context).unwrap(); + + println!("{:?}", detector.instances()); + + // assert that the detector found an issue + assert!(found); + // assert that the detector found the correct number of instances + assert_eq!(detector.instances().len(), 1); + // assert the severity is high + assert_eq!( + detector.severity(), + crate::detect::detector::IssueSeverity::High + ); + // assert the title is correct + assert_eq!( + detector.title(), + String::from( + "Compiler Bug: Signed array in storage detected for compiler version `<0.5.10`", + ) + ); + // assert the description is correct + assert_eq!( + detector.description(), + String::from("If you want to leverage signed arrays in storage by assigning a literal array with at least one negative \ + number, then you mus use solidity version 0.5.10 or above. This is because of a bug in older compilers.") + ); + } + + #[test] + fn test_regular_expression_works() { + // TARGET signed storage array references + + assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int256[3] storage ref")); + assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int[1300] storage ref")); + assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int8[] storage ref")); + assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int[] storage ref")); + assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint256[3] storage ref")); + assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint[1300] storage ref")); + assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint8[] storage ref")); + assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint[] storage ref")); + } +} diff --git a/reports/adhoc-sol-files-highs-only-report.json b/reports/adhoc-sol-files-highs-only-report.json index 3f591e527..2363e9be8 100644 --- a/reports/adhoc-sol-files-highs-only-report.json +++ b/reports/adhoc-sol-files-highs-only-report.json @@ -189,6 +189,7 @@ "rtlo", "unchecked-return", "dangerous-unary-operator", + "signed-storage-array", "weak-randomness", "pre-declared-local-variable-usage", "delete-nested-mapping" diff --git a/reports/report.json b/reports/report.json index 6581acfc1..37c0f9e16 100644 --- a/reports/report.json +++ b/reports/report.json @@ -1,7 +1,7 @@ { "files_summary": { - "total_source_units": 70, - "total_sloc": 1968 + "total_source_units": 71, + "total_sloc": 1981 }, "files_details": { "files_details": [ @@ -29,6 +29,10 @@ "file_path": "src/Casting.sol", "n_sloc": 126 }, + { + "file_path": "src/CompilerBugStorageSignedIntegerArray.sol", + "n_sloc": 13 + }, { "file_path": "src/ConstantsLiterals.sol", "n_sloc": 28 @@ -288,7 +292,7 @@ ] }, "issue_count": { - "high": 30, + "high": 31, "low": 25 }, "high_issues": { @@ -1646,6 +1650,19 @@ } ] }, + { + "title": "Compiler Bug: Signed array in storage detected for compiler version `<0.5.10`", + "description": "If you want to leverage signed arrays in storage by assigning a literal array with at least one negative number, then you mus use solidity version 0.5.10 or above. This is because of a bug in older compilers.", + "detector_name": "signed-storage-array", + "instances": [ + { + "contract_path": "src/CompilerBugStorageSignedIntegerArray.sol", + "line_no": 9, + "src": "230:10", + "src_char": "230:10" + } + ] + }, { "title": "Weak Randomness", "description": "The use of keccak256 hash functions on predictable values like block.timestamp, block.number, or similar data, including modulo operations on these values, should be avoided for generating randomness, as they are easily predictable and manipulable. The `PREVRANDAO` opcode also should not be used as a source of randomness. Instead, utilize Chainlink VRF for cryptographically secure and provably random values to ensure protocol integrity.", @@ -1945,6 +1962,12 @@ "description": "Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;`", "detector_name": "unspecific-solidity-pragma", "instances": [ + { + "contract_path": "src/CompilerBugStorageSignedIntegerArray.sol", + "line_no": 2, + "src": "32:23", + "src_char": "32:23" + }, { "contract_path": "src/ContractWithTodo.sol", "line_no": 2, @@ -2266,6 +2289,18 @@ "src": "2103:18", "src_char": "2103:18" }, + { + "contract_path": "src/CompilerBugStorageSignedIntegerArray.sol", + "line_no": 9, + "src": "235:1", + "src_char": "235:1" + }, + { + "contract_path": "src/CompilerBugStorageSignedIntegerArray.sol", + "line_no": 14, + "src": "352:1", + "src_char": "352:1" + }, { "contract_path": "src/ConstantsLiterals.sol", "line_no": 25, @@ -3627,6 +3662,7 @@ "rtlo", "unchecked-return", "dangerous-unary-operator", + "signed-storage-array", "redundant-statements", "public-variable-read-in-external-context", "weak-randomness", diff --git a/reports/report.md b/reports/report.md index bd66f40d1..345aa4778 100644 --- a/reports/report.md +++ b/reports/report.md @@ -35,9 +35,10 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati - [H-25: RTLO character detected in file. \u{202e}](#h-25-rtlo-character-detected-in-file-u202e) - [H-26: Return value of the function call is not checked.](#h-26-return-value-of-the-function-call-is-not-checked) - [H-27: Dangerous unary operator found in assignment.](#h-27-dangerous-unary-operator-found-in-assignment) - - [H-28: Weak Randomness](#h-28-weak-randomness) - - [H-29: Usage of variable before declaration.](#h-29-usage-of-variable-before-declaration) - - [H-30: Deletion from a nested mappping.](#h-30-deletion-from-a-nested-mappping) + - [H-28: Compiler Bug: Signed array in storage detected for compiler version `<0.5.10`](#h-28-compiler-bug-signed-array-in-storage-detected-for-compiler-version-0510) + - [H-29: Weak Randomness](#h-29-weak-randomness) + - [H-30: Usage of variable before declaration.](#h-30-usage-of-variable-before-declaration) + - [H-31: Deletion from a nested mappping.](#h-31-deletion-from-a-nested-mappping) - [Low Issues](#low-issues) - [L-1: Centralization Risk for trusted owners](#l-1-centralization-risk-for-trusted-owners) - [L-2: Solmate's SafeTransferLib does not check for token contract's existence](#l-2-solmates-safetransferlib-does-not-check-for-token-contracts-existence) @@ -72,8 +73,8 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati | Key | Value | | --- | --- | -| .sol Files | 70 | -| Total nSLOC | 1968 | +| .sol Files | 71 | +| Total nSLOC | 1981 | ## Files Details @@ -86,6 +87,7 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati | src/AssemblyExample.sol | 9 | | src/CallGraphTests.sol | 49 | | src/Casting.sol | 126 | +| src/CompilerBugStorageSignedIntegerArray.sol | 13 | | src/ConstantsLiterals.sol | 28 | | src/ContractWithTodo.sol | 7 | | src/Counter.sol | 20 | @@ -150,14 +152,14 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati | src/reused_contract_name/ContractB.sol | 7 | | src/uniswap/UniswapV2Swapper.sol | 50 | | src/uniswap/UniswapV3Swapper.sol | 150 | -| **Total** | **1968** | +| **Total** | **1981** | ## Issue Summary | Category | No. of Issues | | --- | --- | -| High | 30 | +| High | 31 | | Low | 25 | @@ -1626,7 +1628,24 @@ Potentially mistakened `=+` for `+=` or `=-` for `-=`. Please include a space in -## H-28: Weak Randomness +## H-28: Compiler Bug: Signed array in storage detected for compiler version `<0.5.10` + +If you want to leverage signed arrays in storage by assigning a literal array with at least one negative number, then you mus use solidity version 0.5.10 or above. This is because of a bug in older compilers. + +
1 Found Instances + + +- Found in src/CompilerBugStorageSignedIntegerArray.sol [Line: 9](../tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol#L9) + + ```solidity + affectedArray = [-1, 5, 2]; + ``` + +
+ + + +## H-29: Weak Randomness The use of keccak256 hash functions on predictable values like block.timestamp, block.number, or similar data, including modulo operations on these values, should be avoided for generating randomness, as they are easily predictable and manipulable. The `PREVRANDAO` opcode also should not be used as a source of randomness. Instead, utilize Chainlink VRF for cryptographically secure and provably random values to ensure protocol integrity. @@ -1691,7 +1710,7 @@ The use of keccak256 hash functions on predictable values like block.timestamp, -## H-29: Usage of variable before declaration. +## H-30: Usage of variable before declaration. This is a bad practice that may lead to unintended consequences. Please declare the variable before using it. @@ -1708,7 +1727,7 @@ This is a bad practice that may lead to unintended consequences. Please declare -## H-30: Deletion from a nested mappping. +## H-31: Deletion from a nested mappping. A deletion in a structure containing a mapping will not delete the mapping. The remaining data may be used to compromise the contract. @@ -1957,9 +1976,15 @@ ERC20 functions may not behave as expected. For example: return values are not a Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;` -
17 Found Instances +
18 Found Instances +- Found in src/CompilerBugStorageSignedIntegerArray.sol [Line: 2](../tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol#L2) + + ```solidity + pragma solidity ^0.4.0; + ``` + - Found in src/ContractWithTodo.sol [Line: 2](../tests/contract-playground/src/ContractWithTodo.sol#L2) ```solidity @@ -2266,7 +2291,7 @@ Instead of marking a function as `public`, consider marking it as `external` if If the same constant literal value is used multiple times, create a constant state variable and reference it throughout the contract. -
34 Found Instances +
36 Found Instances - Found in src/Casting.sol [Line: 16](../tests/contract-playground/src/Casting.sol#L16) @@ -2293,6 +2318,18 @@ If the same constant literal value is used multiple times, create a constant sta int unspecificInt = -0x1234567890abcdef; ``` +- Found in src/CompilerBugStorageSignedIntegerArray.sol [Line: 9](../tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol#L9) + + ```solidity + affectedArray = [-1, 5, 2]; + ``` + +- Found in src/CompilerBugStorageSignedIntegerArray.sol [Line: 14](../tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol#L14) + + ```solidity + unaffectedArray[1] = 5; + ``` + - Found in src/ConstantsLiterals.sol [Line: 25](../tests/contract-playground/src/ConstantsLiterals.sol#L25) ```solidity diff --git a/reports/report.sarif b/reports/report.sarif index c9f3f841a..12a857671 100644 --- a/reports/report.sarif +++ b/reports/report.sarif @@ -2381,6 +2381,26 @@ }, "ruleId": "dangerous-unary-operator" }, + { + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "src/CompilerBugStorageSignedIntegerArray.sol" + }, + "region": { + "byteLength": 10, + "byteOffset": 230 + } + } + } + ], + "message": { + "text": "If you want to leverage signed arrays in storage by assigning a literal array with at least one negative number, then you mus use solidity version 0.5.10 or above. This is because of a bug in older compilers." + }, + "ruleId": "signed-storage-array" + }, { "level": "warning", "locations": [ @@ -2885,6 +2905,17 @@ { "level": "note", "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "src/CompilerBugStorageSignedIntegerArray.sol" + }, + "region": { + "byteLength": 23, + "byteOffset": 32 + } + } + }, { "physicalLocation": { "artifactLocation": { @@ -3462,6 +3493,28 @@ } } }, + { + "physicalLocation": { + "artifactLocation": { + "uri": "src/CompilerBugStorageSignedIntegerArray.sol" + }, + "region": { + "byteLength": 1, + "byteOffset": 235 + } + } + }, + { + "physicalLocation": { + "artifactLocation": { + "uri": "src/CompilerBugStorageSignedIntegerArray.sol" + }, + "region": { + "byteLength": 1, + "byteOffset": 352 + } + } + }, { "physicalLocation": { "artifactLocation": { diff --git a/tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol b/tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol new file mode 100644 index 000000000..27bbe2ab3 --- /dev/null +++ b/tests/contract-playground/src/CompilerBugStorageSignedIntegerArray.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.4.0; + +contract CompilerBugStorageSignedIntegerArray { + int256[3] affectedArray; + int256[4] unaffectedArray; + + function assignBadValue() private { + affectedArray = [-1, 5, 2]; + } + + function assignGoodValue() private { + unaffectedArray[0] = -1; + unaffectedArray[1] = 5; + unaffectedArray[2] = 2; + } +}