From def55e52ca6273d92014dabf8a08162b7c8f2c83 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 18 Nov 2016 17:59:07 -0500 Subject: [PATCH] An empty module in state can panic An empty module, or a module with an empty path can panic during graph traversal. Make sure we clear these out when reading and writing the state. --- terraform/state.go | 11 +++++++++++ terraform/state_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/terraform/state.go b/terraform/state.go index 30023fb29..a969357fa 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -644,6 +644,17 @@ func (s *State) init() { } s.ensureHasLineage() + // Filter out empty modules. + // A module is always assumed to have a path, and it's length isn't always + // bounds checked later on. Modules may be "emptied" during destroy, but we + // never want to store those in the state. + for i := 0; i < len(s.Modules); i++ { + if s.Modules[i] == nil || len(s.Modules[i].Path) == 0 { + s.Modules = append(s.Modules[:i], s.Modules[i+1:]...) + i-- + } + } + for _, mod := range s.Modules { mod.init() } diff --git a/terraform/state_test.go b/terraform/state_test.go index de84b8431..f66c2b324 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -1674,3 +1674,37 @@ func TestParseResourceStateKey(t *testing.T) { } } } + +func TestStateModuleOrphans_empty(t *testing.T) { + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: RootModulePath, + }, + &ModuleState{ + Path: []string{RootModuleName, "foo", "bar"}, + }, + &ModuleState{ + Path: []string{}, + }, + nil, + }, + } + + state.init() + + // just calling this to check for panic + state.ModuleOrphans(RootModulePath, nil) + + for _, mod := range state.Modules { + if mod == nil { + t.Fatal("found nil module") + } + if mod.Path == nil { + t.Fatal("found nil module path") + } + if len(mod.Path) == 0 { + t.Fatal("found empty module path") + } + } +}