Skip to content

Commit 43ad07e

Browse files
authored
fix(flux-core): infinite loop protection in the parser (#5436)
Update all loops using self.more in the parser to detect if they get stuck attempting to process the same token multiple times. This has been observed to cause the parser to get into an infinite loop with some erroneus inputs. The protection code was copied from the parse_array_items_rest and applied everywhere the parser could conceivably get stuck. It is not clear that it is possible to get stuck in all the places that the protection was added.
1 parent a5f310a commit 43ad07e

File tree

6 files changed

+790
-1
lines changed

6 files changed

+790
-1
lines changed

libflux/flux-core/src/parser/mod.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,12 +734,23 @@ impl<'input> Parser<'input> {
734734
// Parameters = Parameter { "," Parameter } .
735735
fn parse_parameters(&mut self) -> Vec<ParameterType> {
736736
let mut params = Vec::<ParameterType>::new();
737+
// keep track of the last token's byte offsets
738+
let mut last = self.peek().start_offset;
737739
while self.more() {
738740
let parameter = self.parse_parameter_type();
739741
params.push(parameter);
740742
if self.peek().tok == TokenType::Comma {
741743
self.consume();
742744
}
745+
746+
// If we parse the same token twice in a row,
747+
// it means we've hit a parse error, and that
748+
// we're now in an infinite loop.
749+
let this = self.peek().start_offset;
750+
if last == this {
751+
break;
752+
}
753+
last = this;
743754
}
744755
params
745756
}
@@ -889,11 +900,22 @@ impl<'input> Parser<'input> {
889900
self.consume();
890901
}
891902
// check for more properties
903+
// keep track of the last token's byte offsets
904+
let mut last = self.peek().start_offset;
892905
while self.more() {
893906
properties.push(self.parse_property_type());
894907
if self.peek().tok == TokenType::Comma {
895908
self.consume();
896909
}
910+
911+
// If we parse the same token twice in a row,
912+
// it means we've hit a parse error, and that
913+
// we're now in an infinite loop.
914+
let this = self.peek().start_offset;
915+
if last == this {
916+
break;
917+
}
918+
last = this;
897919
}
898920
properties
899921
}
@@ -1928,6 +1950,8 @@ impl<'input> Parser<'input> {
19281950
val,
19291951
comma: comma.comments,
19301952
}];
1953+
// keep track of the last token's byte offsets
1954+
let mut last = self.peek().start_offset;
19311955
while self.more() {
19321956
let key = self.parse_expression();
19331957
self.expect(TokenType::Colon);
@@ -1940,6 +1964,15 @@ impl<'input> Parser<'input> {
19401964
_ => vec![],
19411965
};
19421966
items.push(DictItem { key, val, comma });
1967+
1968+
// If we parse the same token twice in a row,
1969+
// it means we've hit a parse error, and that
1970+
// we're now in an infinite loop.
1971+
let this = self.peek().start_offset;
1972+
if last == this {
1973+
break;
1974+
}
1975+
last = this;
19431976
}
19441977
let end = self.close(TokenType::RBrack);
19451978
Expression::Dict(Box::new(DictExpr {
@@ -2066,6 +2099,8 @@ impl<'input> Parser<'input> {
20662099
}
20672100
_ => {
20682101
let mut expr = self.parse_expression_suffix(Expression::Identifier(key));
2102+
// keep track of the last token's byte offsets
2103+
let mut last = self.peek().start_offset;
20692104
while self.more() {
20702105
let rhs = self.parse_expression();
20712106
if let Expression::Bad(_) = rhs {
@@ -2084,6 +2119,15 @@ impl<'input> Parser<'input> {
20842119
left: expr,
20852120
right: rhs,
20862121
}));
2122+
2123+
// If we parse the same token twice in a row,
2124+
// it means we've hit a parse error, and that
2125+
// we're now in an infinite loop.
2126+
let this = self.peek().start_offset;
2127+
if last == this {
2128+
break;
2129+
}
2130+
last = this;
20872131
}
20882132
let rparen = self.close(TokenType::RParen);
20892133
Expression::Paren(Box::new(ParenExpr {
@@ -2180,6 +2224,8 @@ impl<'input> Parser<'input> {
21802224
fn parse_property_list(&mut self) -> Vec<Property> {
21812225
let mut params = Vec::new();
21822226
let mut errs = Vec::new();
2227+
// keep track of the last token's byte offsets
2228+
let mut last = self.peek().start_offset;
21832229
while self.more() {
21842230
let t = self.peek();
21852231
let mut p: Property = match t.tok {
@@ -2198,6 +2244,15 @@ impl<'input> Parser<'input> {
21982244
}
21992245

22002246
params.push(p);
2247+
2248+
// If we parse the same token twice in a row,
2249+
// it means we've hit a parse error, and that
2250+
// we're now in an infinite loop.
2251+
let this = self.peek().start_offset;
2252+
if last == this {
2253+
break;
2254+
}
2255+
last = this;
22012256
}
22022257
self.errs.append(&mut errs);
22032258
params
@@ -2285,13 +2340,24 @@ impl<'input> Parser<'input> {
22852340
}
22862341
fn parse_parameter_list(&mut self) -> Vec<Property> {
22872342
let mut params = Vec::new();
2343+
// keep track of the last token's byte offsets
2344+
let mut last = self.peek().start_offset;
22882345
while self.more() {
22892346
let mut p = self.parse_parameter();
22902347
if self.peek().tok == TokenType::Comma {
22912348
let t = self.scan();
22922349
p.comma = t.comments;
22932350
};
22942351
params.push(p);
2352+
2353+
// If we parse the same token twice in a row,
2354+
// it means we've hit a parse error, and that
2355+
// we're now in an infinite loop.
2356+
let this = self.peek().start_offset;
2357+
if last == this {
2358+
break;
2359+
}
2360+
last = this;
22952361
}
22962362
params
22972363
}
@@ -2394,6 +2460,8 @@ impl<'input> Parser<'input> {
23942460
fn parse_attribute_params(&mut self) -> Vec<AttributeParam> {
23952461
let mut params = Vec::new();
23962462
let mut errs = Vec::new();
2463+
// keep track of the last token's byte offsets
2464+
let mut last = self.peek().start_offset;
23972465
while self.more() {
23982466
let value = self.parse_primary_expression();
23992467
let start_pos = value.base().location.start;
@@ -2420,6 +2488,15 @@ impl<'input> Parser<'input> {
24202488
comma: comments,
24212489
};
24222490
params.push(param);
2491+
2492+
// If we parse the same token twice in a row,
2493+
// it means we've hit a parse error, and that
2494+
// we're now in an infinite loop.
2495+
let this = self.peek().start_offset;
2496+
if last == this {
2497+
break;
2498+
}
2499+
last = this;
24232500
}
24242501
self.errs.append(&mut errs);
24252502
params

0 commit comments

Comments
 (0)