-
Notifications
You must be signed in to change notification settings - Fork 310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature/label statement #467
base: main
Are you sure you want to change the base?
Conversation
Thanks! @vi3tL0u1s @Yi2255 Is #476 a superset of this PR as it also adds support in the JS -> FuzzIL compiler? I don't have a strong preference for which PR to review, but if #476 is more feature complete, I'd go for that one? |
- Implement compilable label statement functionality - Extend Continue statement to accept label string value - Add label context tracking in Context analyzer Performance Analysis: - Conducted 2-hour comparison test on V8 - Test environment: 16GB RAM, 8 Core CPU VM - Results: * 1% improvement in all coverage metrics (functions, lines, regions, branches) * Enhanced coverage in 252 source files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this, this is really cool!
So some high-level comments. I think the current approach won't work well with our mutation engine. IIUC, we rely on the LoadLabel
and LabelContinue
and LabelBreak
to get the same input variable, and on that being a string. However, we can no longer guarantee that as soon as our mutation engine kicks in (and changes inputs, or splices code, etc.). We would quickly get something like
v0 <- BeginFunctionDefinition
...
EndFunctionDefinition
LoopLabel v0
BeginWhileLoop
v3 <- CallFunction v1
LoopBreak v3
EndWhileLoop
Which we can't even properly lift anymore, so we'll generate invalid JS syntax, and that's one thing we try hard to avoid. I also think that something like
foo: <whatever>
while (true) {
break foo;
}
Is already a SyntaxError, and those are really bad because they can't be avoided with a try-catch and nothing will be executed at all. So we need to avoid that. On the other hand, it would be nice if we could also support something like
foo: if (true) {
while (true) {
break foo;
}
}
I.e. creating labels for things other than loops.
Finally, for fuzzing efficiency, it would be good to avoid "indirect" dependencies where e.g. a BreakLabel "foo"
operation only works if we also had a CreateLabel "foo"
operation prior to that (the indirect dependency here being the string "foo" that both would need to use). Those are generally tricky because mutating the code will quickly break them.
So overall, I'm wondering if we just want something like this instead:
BeginIf X
BeginWhileLoop
....
BreakNested 2
EndWhileLoop
EndIf
So we'd only add two new instructions: BreakNested <depth>
and ContinueNested <depth>
. We'd then allow <depth>
to be too large, in which case we could just use depth % actual_block_depth
as the real depth. And then we'd have to autogenerate the labels when necessary during lifting. I think for fuzzing efficiency, this will be optimal because we will always generate syntactically valid code and will only emit labels when necessary. The complexity then lies in the lifter, which needs to figure out where to place labels. For that, it would probably need to build up some helper datastructure that records all valid continue/break targets (BeginIf, BeginXYZLoop, BeginBlock, maybe some more?) and keeps track of the current depth at each point in time, then figures out where each BreakNested
and ContinueNested
goes, and then generates the labels (e.g. just label1:
, label2:
etc.) as necessary.
So the lifting will become somewhat complicated. But I think that's ok. In general, in Fuzzilli we prefer "local" complexity (e.g. in the Lifter) over "global" complexity (where multiple different parts of the engine have to work together for something to work).
WDYT? Would this work, and would this also work for the Compiler?
repeatLoop2: do { | ||
console.log("Running once"); | ||
break repeatLoop2; | ||
} while (false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: should this be while (true)
, otherwise we'll anyway only run once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.log("Looping..."); | ||
break outerLoop3; | ||
console.log("Cannot be printed..."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also add some tests with nested loops where we break out of two or more loops?
} | ||
console.log(`i = ${i}, j = ${j}`); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also something like
ifLabel: if (true) {
loopLabel: while (true) {
break ifLabel;
}
console.log("Never reached");
}
But it'll of course depend on whether we can support this type of code.
@@ -0,0 +1,27 @@ | |||
labelBlock: for (let i = 0; i < 1; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding these tests, that's great! I think it would also be good to add some LifterTests.
It seems that the current version of Fuzzilli lacks code generation for label statement. Its specification ref MDN. This PR aims to support the related features.
The logic implemented is:
loopLabelBreak
,loopLabelContinue
,loadLabel
, to support label statement.loadLabel
operation, randomly inserted just above every loop structures. This approach is taken because I found that using existing context mechanism cannot achieve this specific generation position. For example,break
andcontinue
statements can find the appropriate label operation in the current stack.My concerns are as follows, and I would appreciate any corrections:
Thanks a lot!