1882: fix infinite loop in the parser r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-09-20 13:58:09 +00:00 committed by GitHub
commit 24ac228c39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 7 deletions

View file

@ -3,7 +3,7 @@ use super::*;
pub(super) fn use_item(p: &mut Parser, m: Marker) { pub(super) fn use_item(p: &mut Parser, m: Marker) {
assert!(p.at(T![use])); assert!(p.at(T![use]));
p.bump(T![use]); p.bump(T![use]);
use_tree(p); use_tree(p, true);
p.expect(T![;]); p.expect(T![;]);
m.complete(p, USE_ITEM); m.complete(p, USE_ITEM);
} }
@ -12,7 +12,7 @@ pub(super) fn use_item(p: &mut Parser, m: Marker) {
/// Note that this is called both by `use_item` and `use_tree_list`, /// Note that this is called both by `use_item` and `use_tree_list`,
/// so handles both `some::path::{inner::path}` and `inner::path` in /// so handles both `some::path::{inner::path}` and `inner::path` in
/// `use some::path::{inner::path};` /// `use some::path::{inner::path};`
fn use_tree(p: &mut Parser) { fn use_tree(p: &mut Parser, top_level: bool) {
let m = p.start(); let m = p.start();
match p.current() { match p.current() {
// Finish the use_tree for cases of e.g. // Finish the use_tree for cases of e.g.
@ -101,10 +101,14 @@ fn use_tree(p: &mut Parser) {
} }
_ => { _ => {
m.abandon(p); m.abandon(p);
p.err_recover( let msg = "expected one of `*`, `::`, `{`, `self`, `super` or an identifier";
"expected one of `*`, `::`, `{`, `self`, `super` or an identifier", if top_level {
ITEM_RECOVERY_SET, p.err_recover(msg, ITEM_RECOVERY_SET);
); } else {
// if we are parsing a nested tree, we have to eat a token to
// main balanced `{}`
p.err_and_bump(msg);
}
return; return;
} }
} }
@ -116,7 +120,7 @@ pub(crate) fn use_tree_list(p: &mut Parser) {
let m = p.start(); let m = p.start();
p.bump(T!['{']); p.bump(T!['{']);
while !p.at(EOF) && !p.at(T!['}']) { while !p.at(EOF) && !p.at(T!['}']) {
use_tree(p); use_tree(p, false);
if !p.at(T!['}']) { if !p.at(T!['}']) {
p.expect(T![,]); p.expect(T![,]);
} }

View file

@ -0,0 +1,2 @@
use std::{error::Error;
use std::io;

View file

@ -0,0 +1,51 @@
SOURCE_FILE@[0; 37)
USE_ITEM@[0; 36)
USE_KW@[0; 3) "use"
WHITESPACE@[3; 4) " "
USE_TREE@[4; 36)
PATH@[4; 7)
PATH_SEGMENT@[4; 7)
NAME_REF@[4; 7)
IDENT@[4; 7) "std"
COLONCOLON@[7; 9) "::"
USE_TREE_LIST@[9; 36)
L_CURLY@[9; 10) "{"
USE_TREE@[10; 22)
PATH@[10; 22)
PATH@[10; 15)
PATH_SEGMENT@[10; 15)
NAME_REF@[10; 15)
IDENT@[10; 15) "error"
COLONCOLON@[15; 17) "::"
PATH_SEGMENT@[17; 22)
NAME_REF@[17; 22)
IDENT@[17; 22) "Error"
ERROR@[22; 23)
SEMI@[22; 23) ";"
WHITESPACE@[23; 24) "\n"
ERROR@[24; 27)
USE_KW@[24; 27) "use"
WHITESPACE@[27; 28) " "
USE_TREE@[28; 35)
PATH@[28; 35)
PATH@[28; 31)
PATH_SEGMENT@[28; 31)
NAME_REF@[28; 31)
IDENT@[28; 31) "std"
COLONCOLON@[31; 33) "::"
PATH_SEGMENT@[33; 35)
NAME_REF@[33; 35)
IDENT@[33; 35) "io"
ERROR@[35; 36)
SEMI@[35; 36) ";"
WHITESPACE@[36; 37) "\n"
error 22: expected COMMA
error 22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 23: expected COMMA
error 24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 27: expected COMMA
error 35: expected COMMA
error 35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 36: expected COMMA
error 36: expected R_CURLY
error 36: expected SEMI