Compute static memory requirements of methods. #218
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This series of patches adds a few new verification steps. The first is that the stack must be balanced. The amount of stack space used must be equal across all incoming edges to a block. This has a few important implications:
The algorithm is simple: for each opcode, the stack balance is adjusted based on how much it adds or removes from the stack. When parsing each block, its initial stack balance is inherited from any predecessor, and it must be equal across all predecessors. Loop edges must be checked again later since they are cyclic.
In addition, a second verification step is that stack offsets must now be within each block's stack balance. Even if the stack offset is valid for some other block, it must also be valid locally.
These changes did cause a few new failures in my .smx corpus. Four copies of "THC RPG" [1], three dated 02/15/2014 and one dated 07/14/2013 (both using SourceMod 1.5.x) have an odd bug. One block references a local variable that does not exist, and it is quite clear from the bytecode that something is wrong. Lysis manages to assign a name to this stack offset, but the name isn't anywhere in the debug symbols. I don't know what happened, but this plugin is unsupported so I'm not too worried.
A plugin that used to fail verification, but now passes, is from the Lysis test suite. "anlol.smx" (dated 02/24/2016, SM 1.7.3) has a wildly huge stack offset, -1000000004, which we used to statically determine was impossible to satisfy. I removed this check because now it can be encapsulated in the runtime's stack space check, which I'll do as a separate patch when I go to optimize the JIT. This plugin has been heavily obfuscated so it is certainly not generated by a supported compiler.
Finally, a plugin called "PUNISHER old v34" [2] fails the new requirements. It is again heavily obfuscated by some third-party compiler. Unfortunately this compiler inserted an extra
pop.altinstruction on an empty stack, which is nonsensical and not allowed.[1] Attachments 114946, 130624, 130633, 122854
[2] Attachment 164723 (08/04/2017, SM 1.7)