From 44e03187a73770f0abb119df5ee1d928528fd119 Mon Sep 17 00:00:00 2001 From: David Majda Date: Sat, 7 Dec 2013 16:38:49 +0100 Subject: [PATCH] Assert that generated bytecode manipulates stack correctly There are two invariants in generated bytecode related to the stack: 1. Branches of a condition must move the stack pointer in the same way. 2. Body of a loop can't move the stack pointer. These invariants were always true, but they were not checked. Now we check them at least when compiling with optimization for speed, because there we analyze the stack pointer movements statically. --- lib/compiler/passes/generate-javascript.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/compiler/passes/generate-javascript.js b/lib/compiler/passes/generate-javascript.js index 41ba34e..6de510c 100644 --- a/lib/compiler/passes/generate-javascript.js +++ b/lib/compiler/passes/generate-javascript.js @@ -379,15 +379,24 @@ module.exports = function(ast, options) { thenLength = bc[ip + baseLength - 2], elseLength = bc[ip + baseLength - 1], baseSp = stack.sp, - thenCode, elseCode; + thenCode, elseCode, thenSp, elseSp; ip += baseLength; thenCode = compile(bc.slice(ip, ip + thenLength)); + thenSp = stack.sp; ip += thenLength; + if (elseLength > 0) { stack.sp = baseSp; elseCode = compile(bc.slice(ip, ip + elseLength)); + elseSp = stack.sp; ip += elseLength; + + if (thenSp !== elseSp) { + throw new Error( + "Branches of a condition must move the stack pointer in the same way." + ); + } } parts.push('if (' + cond + ') {'); @@ -402,12 +411,18 @@ module.exports = function(ast, options) { function compileLoop(cond) { var baseLength = 2, bodyLength = bc[ip + baseLength - 1], - bodyCode; + baseSp = stack.sp, + bodyCode, bodySp; ip += baseLength; bodyCode = compile(bc.slice(ip, ip + bodyLength)); + bodySp = stack.sp; ip += bodyLength; + if (bodySp !== baseSp) { + throw new Error("Body of a loop can't move the stack pointer."); + } + parts.push('while (' + cond + ') {'); parts.push(indent2(bodyCode)); parts.push('}');