diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 06220dcac74..62f88759358 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -2536,12 +2536,27 @@ impl ty::TyExpression { full_span_for_error = Span::join(full_span_for_error, index_span); } ( - TypeInfo::Array(elem_ty, _), - ty::ProjectionKind::ArrayIndex { index_span, .. }, + TypeInfo::Array(elem_ty, array_length), + ty::ProjectionKind::ArrayIndex { index, index_span }, ) => { parent_rover = symbol; symbol = elem_ty.type_id; symbol_span = index_span.clone(); + + if let Some(index_literal) = index + .expression + .as_literal() + .and_then(|x| x.cast_value_to_u64()) + { + if index_literal >= array_length.val() as u64 { + return Err(handler.emit_err(CompileError::ArrayOutOfBounds { + index: index_literal, + count: array_length.val() as u64, + span: index.span.clone(), + })); + } + } + // `index_span` does not contain the enclosing square brackets. // Which means, if this array index access is the last one before the // erroneous expression, the `full_span_for_error` will be missing the diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.lock new file mode 100644 index 00000000000..7f8a3338563 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.lock @@ -0,0 +1,8 @@ +[[package]] +name = "array_oob_reassignment" +source = "member" +dependencies = ["core"] + +[[package]] +name = "core" +source = "path+from-root-CC73096846C1E083" diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.toml new file mode 100644 index 00000000000..cc38134eea8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "array_oob_reassignment" +entry = "main.sw" +implicit-std = false + +[dependencies] +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/src/main.sw new file mode 100644 index 00000000000..cd5d7979225 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/src/main.sw @@ -0,0 +1,16 @@ +script; + +fn main() { + let mut a = [u64; 0]; + a[0] = 1; + + + let mut b = [[u64; 1]; 1]; + b[0][1] = 1; + + + b[1][0] = 1; + + + a[0] = return; +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/test.toml new file mode 100644 index 00000000000..e3c8288e736 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob_reassignment/test.toml @@ -0,0 +1,19 @@ +category = "fail" + +# check: $()let mut a = [u64; 0]; +# nextln: $()This declaration is never used. + +# check: $()let mut b = [[u64; 1]; 1]; +# nextln: $()This declaration is never used. + +# check: $()a[0] = 1; +# nextln: $()Index out of bounds; the length is 0 but the index is 0. + +# check: $()b[0][1] = 1; +# nextln: $()Index out of bounds; the length is 1 but the index is 1. + +# check: $()b[1][0] = 1; +# nextln: $()Index out of bounds; the length is 1 but the index is 1. + +# check: $()a[0] = return; +# nextln: $()Index out of bounds; the length is 0 but the index is 0. \ No newline at end of file