Skip to content

Commit 8092dd9

Browse files
committed
[Parser] Validate a collection element if its a subscript
1 parent c829703 commit 8092dd9

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ ERROR(extra_rbracket,PointsToFirstBadToken,
762762
"unexpected ']' in type; did you mean to write an array type?", ())
763763
ERROR(extra_colon,PointsToFirstBadToken,
764764
"unexpected ':' in type; did you mean to write a dictionary type?", ())
765+
WARNING(subscript_collection_element_invalid_index, none,
766+
"index '%0' in subscript expression is out of bounds", (StringRef))
765767

766768
// Tuple Types
767769
ERROR(expected_rparen_tuple_type_list,none,

include/swift/Parse/Parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,8 @@ class Parser {
14351435

14361436
UnresolvedDeclRefExpr *parseExprOperator();
14371437

1438+
void validateCollectionElement(ParserResult<Expr> element);
1439+
14381440
//===--------------------------------------------------------------------===//
14391441
// Statement Parsing
14401442

lib/Parse/ParseExpr.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3447,8 +3447,10 @@ Parser::parseExprCollectionElement(Optional<bool> &isDictionary) {
34473447
if (!isDictionary.hasValue())
34483448
isDictionary = Tok.is(tok::colon);
34493449

3450-
if (!*isDictionary)
3450+
if (!*isDictionary) {
3451+
validateCollectionElement(Element);
34513452
return Element;
3453+
}
34523454

34533455
if (Element.isNull())
34543456
return Element;
@@ -3471,6 +3473,46 @@ Parser::parseExprCollectionElement(Optional<bool> &isDictionary) {
34713473
TupleExpr::createImplicit(Context, {Element.get(), Value.get()}, {}));
34723474
}
34733475

3476+
/// validateCollectionElement - Check if a given collection element is valid.
3477+
///
3478+
/// At the moment, this checks whether a given collection element is a subscript
3479+
/// expression and whether we're subscripting into an array. If we are, then it
3480+
/// checks whether the subscript index is valid or not.
3481+
///
3482+
/// For example: `let array [ [0, 1] [42] ]`
3483+
void Parser::validateCollectionElement(ParserResult<Expr> element) {
3484+
if (element.isNull())
3485+
return;
3486+
3487+
auto elementExpr = element.get();
3488+
if (!isa<SubscriptExpr>(elementExpr))
3489+
return;
3490+
3491+
auto subscriptExpr = cast<SubscriptExpr>(elementExpr);
3492+
if (!isa<ArrayExpr>(subscriptExpr->getBase()))
3493+
return;
3494+
3495+
auto baseExpr = cast<ArrayExpr>(subscriptExpr->getBase());
3496+
auto index = subscriptExpr->getIndex()->getValueProvidingExpr();
3497+
3498+
if (!isa<IntegerLiteralExpr>(index))
3499+
return;
3500+
auto indexExpr = cast<IntegerLiteralExpr>(index);
3501+
3502+
int elementsCount = baseExpr->getNumElements();
3503+
int indexValue = atoi(indexExpr->getDigitsText().str().c_str());
3504+
3505+
auto withinBounds = indexValue >= 0 && indexValue < elementsCount;
3506+
3507+
if (!withinBounds) {
3508+
auto diag = diagnose(subscriptExpr->getLoc(),
3509+
diag::subscript_collection_element_invalid_index,
3510+
indexExpr->getDigitsText());
3511+
diag.highlight(subscriptExpr->getSourceRange());
3512+
element.setIsParseError();
3513+
}
3514+
}
3515+
34743516
void Parser::addPatternVariablesToScope(ArrayRef<Pattern *> Patterns) {
34753517
for (Pattern *Pat : Patterns) {
34763518
Pat->forEachVariable([&](VarDecl *VD) {

test/type/array.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,9 @@ func passAssocType<T : HasAssocType>(_ t: T) {
114114
takesAssocType(t, [T.A](), [T.A?]())
115115
}
116116

117+
// SR-11134
118+
119+
let sr_11134_1 = [["a"][0]] // Ok
120+
let sr_11134_2 = [["a"][1]] // expected-warning {{index '1' in subscript expression is out of bounds}}
121+
122+
let sr_11134_3 = [[1, 1, 1], [], [4, 5, 6, 7], [0], [], [] [42]] // expected-warning {{index '42' in subscript expression is out of bounds}}

0 commit comments

Comments
 (0)