Skip to content

Commit 1b669d9

Browse files
cdlearycopybara-github
authored andcommitted
[DSLX:parser] Avoid bad down cast in parser.
Found via coverage-guided fuzzing. PiperOrigin-RevId: 559754379
1 parent 95afe6a commit 1b669d9

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

xls/dslx/frontend/parser.cc

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,7 +1632,7 @@ absl::StatusOr<Expr*> Parser::ParseTerm(Bindings& outer_bindings,
16321632
lhs, std::move(args)));
16331633
break;
16341634
}
1635-
case TokenKind::kDot: {
1635+
case TokenKind::kDot: { // Attribute or tuple index access.
16361636
DropTokenOrDie();
16371637
XLS_ASSIGN_OR_RETURN(Token tok, PopToken());
16381638
const Span span(new_pos, GetPos());
@@ -1651,15 +1651,19 @@ absl::StatusOr<Expr*> Parser::ParseTerm(Bindings& outer_bindings,
16511651
}
16521652
break;
16531653
}
1654-
case TokenKind::kOBrack: {
1654+
case TokenKind::kOBrack: { // Indexing.
16551655
DropTokenOrDie();
1656+
16561657
XLS_ASSIGN_OR_RETURN(bool dropped_colon,
16571658
TryDropToken(TokenKind::kColon));
16581659
if (dropped_colon) { // Slice-from-beginning.
16591660
XLS_ASSIGN_OR_RETURN(lhs, ParseBitSlice(new_pos, lhs, outer_bindings,
16601661
/*start=*/nullptr));
16611662
break;
16621663
}
1664+
1665+
// Index may be followed by a `:` for a slice, or a `+:` for a
1666+
// type-sized slice.
16631667
XLS_ASSIGN_OR_RETURN(Expr * index, ParseExpression(outer_bindings));
16641668
XLS_ASSIGN_OR_RETURN(peek, PeekToken());
16651669
switch (peek->kind()) {
@@ -1680,20 +1684,34 @@ absl::StatusOr<Expr*> Parser::ParseTerm(Bindings& outer_bindings,
16801684
lhs, ParseBitSlice(new_pos, lhs, outer_bindings, index));
16811685
break;
16821686
}
1683-
default:
1687+
default: {
16841688
XLS_RETURN_IF_ERROR(DropTokenOrError(TokenKind::kCBrack));
16851689

16861690
// It's either an Index if the LHS is a NameRef or
16871691
// ColonRef-to-ConstantDef, or an Array if lhs is a
16881692
// ColonRef-to-type.
1689-
Span span(new_pos, GetPos());
1693+
const Span span(new_pos, GetPos());
16901694
XLS_ASSIGN_OR_RETURN(peek, PeekToken());
1695+
// Array type before literal, e.g. Foo[2]:[...]
1696+
// this colon ----------^
16911697
if (peek->kind() == TokenKind::kColon) {
16921698
DropTokenOrDie();
1699+
absl::StatusOr<TypeDefinition> type_definition_or =
1700+
ToTypeDefinition(lhs);
1701+
if (!type_definition_or.ok()) {
1702+
const Span error_span(lhs->span().start(),
1703+
index->span().limit());
1704+
return ParseErrorStatus(
1705+
error_span,
1706+
absl::StrFormat(
1707+
"Type before ':' for presumed array literal was not a "
1708+
"type definition; got `%s` (kind: %v)",
1709+
lhs->ToString(), lhs->kind()));
1710+
}
16931711
// TODO(rspringer): We can't currently support parameterized
16941712
// ColonRef-to-types with this function structure.
16951713
auto* type_ref =
1696-
module_->Make<TypeRef>(span, down_cast<ColonRef*>(lhs));
1714+
module_->Make<TypeRef>(span, type_definition_or.value());
16971715
auto* type_ref_type = module_->Make<TypeRefTypeAnnotation>(
16981716
span, type_ref, /*parametrics=*/std::vector<ExprOrType>());
16991717
auto* array_type = module_->Make<ArrayTypeAnnotation>(
@@ -1705,6 +1723,7 @@ absl::StatusOr<Expr*> Parser::ParseTerm(Bindings& outer_bindings,
17051723
} else {
17061724
lhs = module_->Make<Index>(span, lhs, index);
17071725
}
1726+
}
17081727
}
17091728
break;
17101729
}

xls/dslx/frontend/parser_test.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,4 +1923,17 @@ TEST_F(ParserTest, UnreasonablyDeepExpr) {
19231923
<< module_or.status();
19241924
}
19251925

1926+
TEST_F(ParserTest, NonTypeDefinitionBeforeArrayLiteralColon) {
1927+
constexpr std::string_view kProgram = "const A=4[5]:[";
1928+
Scanner s{"test.x", std::string(kProgram)};
1929+
Parser parser{"test", &s};
1930+
auto module_or = parser.ParseModule();
1931+
EXPECT_THAT(
1932+
module_or,
1933+
StatusIs(absl::StatusCode::kInvalidArgument,
1934+
HasSubstr("Type before ':' for presumed array literal was not a "
1935+
"type definition; got `4` (kind: number)")))
1936+
<< module_or.status();
1937+
}
1938+
19261939
} // namespace xls::dslx

0 commit comments

Comments
 (0)