lib/import/shake_grammar/lexer.rb in tracksperanto-1.7.1 vs lib/import/shake_grammar/lexer.rb in tracksperanto-1.7.2
- old
+ new
@@ -1,6 +1,8 @@
module Tracksperanto::ShakeGrammar
+ class WrongInput < RuntimeError; end
+
# Since Shake uses a C-like language for it's scripts we rig up a very sloppy
# but concise C-like lexer to cope
class Lexer
# Parsed stack
@@ -13,12 +15,12 @@
# The first argument is the IO handle to the data of the Shake script.
# The second argument is a "sentinel" that is going to be passed
# to the downstream lexers instantiated for nested data structures.
# You can use the sentinel to collect data from child nodes for example.
- def initialize(with_io, sentinel = nil, limit_to_one_stmt = false)
- @io, @stack, @buf, @sentinel, @limit_to_one_stmt = with_io, [], '', sentinel, @limit_to_one_stmt
+ def initialize(with_io, sentinel = nil, limit_to_one_stmt = false, stack_depth = 0)
+ @io, @stack, @buf, @sentinel, @limit_to_one_stmt, @stack_depth = with_io, [], '', sentinel, limit_to_one_stmt, stack_depth
catch(STOP_TOKEN) { parse until @io.eof? }
in_comment? ? consume_comment("\n") : consume_atom!
end
private
@@ -35,15 +37,25 @@
@buf << c
end
end
def parse
+
c = @io.read(1)
+
+ if @buf.length > 32000 # Wrong format and the buffer is filled up, bail
+ raise WrongInput, "Buffer overflow at 32K, this is definitely not a Shake script"
+ end
+
+ if @stack_depth > 127 # Wrong format - parentheses overload
+ raise WrongInput, "Stack overflow at level 128, this is probably a LISP program uploaded by accident"
+ end
+
return consume_comment(c) if in_comment?
if !@buf.empty? && (c == "(") # Funcall
- push([:funcall, @buf.strip] + self.class.new(@io, @sentinel).stack)
+ push([:funcall, @buf.strip] + self.class.new(@io, @sentinel, false, @stack_depth + 1).stack)
@buf = ''
elsif c == "[" # Array, booring
push([:arr, self.class.new(@io).stack])
elsif (c == "]" || c == ")" || c == ";" && @limit_to_one_stmt)
# Bailing out of a subexpression
@@ -55,10 +67,10 @@
consume_atom!
@buf << c
elsif (c == ";" || c == "\n")
# Skip these - the subexpression already is expanded anyway
elsif (c == "=")
- push [:assign, @buf.strip, self.class.new(@io, @sentinel, to_semicolon = true).stack.shift]
+ push [:assign, @buf.strip, self.class.new(@io, @sentinel, to_semicolon = true, @stack_depth + 1).stack.shift]
@buf = ''
else
@buf << c
end
end
\ No newline at end of file