diff --git a/brainfuck.go b/brainfuck.go index e7f1f4e..b719866 100644 --- a/brainfuck.go +++ b/brainfuck.go @@ -9,14 +9,26 @@ import ( ) const ( - MEM_MAX = 3000000 MEM_STD = 30000 ) +type ErrMemoryOverflow struct {} +func (e ErrMemoryOverflow) Error() string { return "Memory Overflow" } +type ErrMemoryUnderflow struct {} +func (e ErrMemoryUnderflow) Error() string { return "Memory Underflow" } +type ErrInstructionLimit struct {} +func (e ErrInstructionLimit) Error() string { return "Instruction Limit Reached" } + type Machine struct { array []byte ptr int reader *bufio.Reader + + // InstructionLimit prevents a runaway execution if running under a controlled environment + InstructionLimit int + + // MemMax is the limit of how large memory can expand + MemMax int } // Returns a new machine with standard memory size @@ -30,33 +42,34 @@ func New(in io.Reader) *Machine { array: bytes, ptr: 0, reader: bufio.NewReader(in), + InstructionLimit: 0, + MemMax: 3000000, } } // Implements '>' -func (m *Machine) PtrIncr() { +func (m *Machine) PtrIncr() error { if m.ptr >= len(m.array)-1 { m.array = append(m.array, 0) } m.ptr += 1 - if m.ptr > MEM_MAX { - panic("Memory overflow") + if m.ptr > m.MemMax { + return ErrMemoryOverflow{} } + return nil } // Implements '<' -func (m *Machine) PtrDecr() { +func (m *Machine) PtrDecr() error { if m.ptr == 0 { - panic("Memory underflow") + return ErrMemoryUnderflow{} } m.ptr -= 1 + return nil } // Implements '+' func (m *Machine) ByteIncr() { - if m.ptr > len(m.array)-1 { - fmt.Printf("Memory overflow, ptr=%d\n", m.ptr) - } m.array[m.ptr] += 1 } @@ -85,9 +98,13 @@ func (m *Machine) value() byte { } // Run the whole program specified by input -func (m *Machine) Run(input []byte) { - // execute the program +func (m *Machine) Run(input []byte) error { + instrCount := 0 for ip := 0; ip < len(input); ip++ { + instrCount++ + if m.InstructionLimit > 0 && instrCount > m.InstructionLimit { + return ErrInstructionLimit{} + } instr := input[ip] // if *ptr == 0, jump to ] if instr == '[' && m.value() == 0 { @@ -110,9 +127,13 @@ func (m *Machine) Run(input []byte) { } } } else if instr == '>' { - m.PtrIncr() + if err := m.PtrIncr(); err != nil { + return err + } } else if instr == '<' { - m.PtrDecr() + if err := m.PtrDecr(); err != nil { + return err + } } else if instr == '+' { m.ByteIncr() } else if instr == '-' { @@ -124,4 +145,6 @@ func (m *Machine) Run(input []byte) { } } + + return nil } diff --git a/gofuck/main.go b/gofuck/main.go index 27f1237..b0e5dc6 100644 --- a/gofuck/main.go +++ b/gofuck/main.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "fmt" "io/ioutil" "os" @@ -14,15 +15,19 @@ func main() { // read in the instructions if len(os.Args) < 2 { - panic("No input given") + fmt.Printf("No input given") + return } file, err := os.Open(os.Args[1]) reader := bufio.NewReader(file) instructions, err = ioutil.ReadAll(reader) if err != nil { - panic(err) + fmt.Printf("Error: %s\n", err) + return } - m.Run(instructions) + if err := m.Run(instructions); err != nil { + fmt.Printf("Error: %s\n", err) + } }