Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Get out of the infinite loop by allowing to scan backwards when the current token is a comment. #9006

Merged
merged 3 commits into from
Sep 25, 2014

Conversation

RaymondLim
Copy link
Contributor

This fixes issue #9002.

@Mark-Simulacrum
Copy link
Contributor

Can confirm that this fix works, just tested using @RaymondLim test case from #9002 - on Ubuntu 64bit 14.04.

@peterflynn
Copy link
Member

@RaymondLim Could we add a unit test for this?

@RaymondLim
Copy link
Contributor Author

Sure! It should be easy as the issue is caused by having the cursor right after { or } inside a comment.

if (ctx.token.string !== "{" && ctx.token.string !== "}" && !TokenUtils.movePrevToken(ctx)) {
if ((ctx.token.type === "comment" ||
(ctx.token.string !== "{" && ctx.token.string !== "}")) &&
!TokenUtils.movePrevToken(ctx)) {
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if it would be more clear to structure it like this:

if (ctx.token.type !== "comment") {
    if (ctx.token.string === "}") {
        // (same as master)
    } else if (ctx.token.string === "{") {
        // (same as master)
    } else {
        // (same as master, plus...)
        if (!TokenUtils.movePrevToken(ctx)) {
            break;
        }
    }
} else {
    if (!TokenUtils.movePrevToken(ctx)) {
        break;
    }
}

This makes it a little more obvious how we guarantee that the loop makes progress every iteration in all cases, and it eliminates the if statement in this diff, which I think has somewhat tricky to follow logic since it's basically covering two independent cases.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, an even nicer improvement would be to change while (true) { } to do { } while (!(ctx.pos.line === 0 && ctx.pos.ch === 0)). This way we wouldn't need the manual break calls after each movePrevToken(), and we get a little more safety in case this code changes more in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@peterflynn do { } while (!(ctx.pos.line === 0 && ctx.pos.ch === 0)) logic is not the same as the current logic which stops as soon as hitting a { or } for a normal css file, or a } in the top level for a preprocessor file. So I'll use your prior suggested code.

Copy link
Member

Choose a reason for hiding this comment

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

@RaymondLim I didn't mean to remove the break statements in those cases -- just remove the break statements that go with the movePrevToken() calls. That should preserve the existing behavior precisely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@marcelgerber
Copy link
Contributor

It looks like these unit tests pass on master, too. (While they shouldn't)

@RaymondLim
Copy link
Contributor Author

@marcelgerber You will get into infinite loop when running these unit tests.

@peterflynn
Copy link
Member

@marcelgerber is correct: the test passes even on master, without the fix -- it doesn't get into the infinite loop. To hit the bug, you need a comment token whose value is exactly equal to "{" or "}", and afaik that can only happen when the { or } is alone on a line. In the offsets.css testcase file, the braces are together on a line with other text instead: /* p { color: "black" } */.

This is a good reminder of why it's always important to run testcases with your fix disabled to verify that the testcase itself is covering what you want it to cover.

@peterflynn
Copy link
Member

@RaymondLim Done re-reviewing. We need to fix the test for sure. The loop cleanup I think would be nice, but it's not critical -- so it's up to you if you want to bother with that change or not.

@RaymondLim
Copy link
Contributor Author

@peterflynn and @marcelgerber Thanks for catching the unit test issue. I might have tested with my own commented rule and later switched to use the existing one without retesting.

@RaymondLim
Copy link
Contributor Author

@peterflynn Changes are pushed. Ready for final review (I hope).

@peterflynn peterflynn self-assigned this Sep 25, 2014
@peterflynn peterflynn added this to the Release 0.44 milestone Sep 25, 2014
@peterflynn
Copy link
Member

Looks good -- thanks @RaymondLim!

peterflynn added a commit that referenced this pull request Sep 25, 2014
Fix infinite loop by ensuring loop always makes progress when the current token is a comment.
@peterflynn peterflynn merged commit 03ab969 into master Sep 25, 2014
@peterflynn peterflynn removed the Review label Sep 25, 2014
@peterflynn peterflynn deleted the rlim/hang-in-css-comment branch September 25, 2014 05:26
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants