Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

checking Eof before calling parseIdent #596

Merged
merged 5 commits into from
Jul 4, 2022

Conversation

Sehun0819
Copy link
Contributor

Handling #594.
Guards are added before parseIdent, to prevent it from calling Parser.next on Eof.

@cristianoc
Copy link
Contributor

Looking good.
Code duplication is fine as it's very very little compared to having parser.next return an option and having to check every single one.

A helper function for the error message should be more then enough to reduce boilerplate.

@Sehun0819
Copy link
Contributor Author

Thank you.
At first, I was thinking of fixing only apparent bugs(that is, found by fuzzer), so that innocent codes aren't affected. But it seems like more conservative(or aggressive) fixing is needed because there are so many Parser.next in res_core.ml.

syntax/src/res_core.ml

Lines 3603 to 3617 in 08029af

| Lident ident ->
Parser.next p;
let loc = mkLoc startPos p.prevEndPos in
let lident = buildLongident (ident :: acc) in
Ast_helper.Exp.ident ~loc (Location.mkloc lident loc)
| token ->
if acc = [] then (
Parser.next p;
Parser.err p (Diagnostics.unexpected token p.breadcrumbs);
Recover.defaultExpr ())
else
let loc = mkLoc startPos p.prevEndPos in
Parser.err p (Diagnostics.unexpected token p.breadcrumbs);
let lident = buildLongident ("_" :: acc) in
Ast_helper.Exp.ident ~loc (Location.mkloc lident loc)

Concretely, Parser.next in L3604 would be safe, while one in L3610 seems highly suspicious though I've seen no concrete example yet. Would you give me an opinion?

@cristianoc
Copy link
Contributor

There's no harm in doing all the non-obvious cases

For comparison there's a PR showing how horrible the code would look using exception analysis

@cristianoc
Copy link
Contributor

This PR: #543
which has over 1000 code changes, is what we're trying to avoid here.

@@ -1906,7 +1915,7 @@ and parseFirstClassModuleExpr ~startPos p =
and parseBracketAccess p expr startPos =
Parser.leaveBreadcrumb p Grammar.ExprArrayAccess;
let lbracket = p.startPos in
Parser.next p;
Parser.expect Lbracket p;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though just using Parser.next is safe as p is always Lbracket, this change would make it more clear.

@Sehun0819
Copy link
Contributor Author

I looked over every Parser.next usages in res_core.ml.

  • Because it is hard to fix skipTokensAndMaybeRetry directly(like parseIdent), I added guards right before call sites.
  • When it seems ok, I substituted Parser.next with Parser.nextUnsafe.

src/res_core.ml Outdated
with
| None -> Recover.defaultPattern ()
| Some () -> parsePattern p)
if p.Parser.token = Eof then Recover.defaultPattern ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message missing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be moved to case in pattern matching

src/res_core.ml Outdated
| Some () -> parseLident p
| None -> ("_", mkLoc startPos p.prevEndPos))
| token -> (
if token = Eof then (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move this to a case in pattern matching

src/res_core.ml Outdated
@@ -600,7 +604,11 @@ let parseHashIdent ~startPos p =
in
Parser.next p;
(i, mkLoc startPos p.prevEndPos)
| _ -> parseIdent ~startPos ~msg:ErrorMessages.variantIdent p
| token ->
if token = Eof then (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move this to a case in the pattern matching.

src/res_core.ml Outdated
@@ -1090,7 +1098,12 @@ let rec parsePattern ?(alias = true) ?(or_ = true) p =
in
Parser.next p;
(i, mkLoc startPos p.prevEndPos)
| _ -> parseIdent ~msg:ErrorMessages.variantIdent ~startPos p
| token ->
if token = Eof then (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case in pattern matching

src/res_core.ml Outdated
with
| None -> Recover.defaultExpr ()
| Some () -> parseAtomicExpr p)
if p.Parser.token = Eof then Recover.defaultExpr ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error missing

src/res_core.ml Outdated
Parser.err ~startPos:p.prevEndPos p
(Diagnostics.unexpected token p.breadcrumbs);
Recover.defaultType ())
if p.Parser.token = Eof then Recover.defaultType ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error missing

@Sehun0819
Copy link
Contributor Author

How about now?

src/res_core.ml Outdated
match recoverLident p with
| Some () -> parseLident p
| None -> ("_", mkLoc startPos p.prevEndPos))
| token when token = Eof ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simply | Eof

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😱

Copy link
Contributor

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great.

Any tests missing, that trigger the new cases?

@@ -556,6 +556,9 @@ let rec parseLident p =
Parser.next p;
let loc = mkLoc startPos p.prevEndPos in
(ident, loc)
| Eof ->
Parser.err ~startPos p (Diagnostics.unexpected p.Parser.token p.breadcrumbs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, perhaps put this line, which is repeated many times, in a function?

@cristianoc cristianoc merged commit 3e8bafb into rescript-lang:master Jul 4, 2022
@cristianoc
Copy link
Contributor

Merged as needed for release

@Sehun0819 Sehun0819 deleted the fixcrash2 branch July 7, 2022 06:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants