Repository: go-task/task
Pull request #573 (2021-09-18 04:06:20)

Fix segmentation fault on nil slice element for issue #534
This is to fix the issue #534 .
Only `cmds` attribute is pointed out in the issue, but I think other attributes such as `deps` and `preconditions` may have same problems, so I fix them as well.

Please let me know if there are any problems in fixed codes.


Patch:
diff --git a/variables.go b/variables.go
index 0e7ff4c0..99baddf2 100644
--- a/variables.go
+++ b/variables.go
@@ -90,34 +90,43 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
 	}
 
 	if len(origTask.Cmds) > 0 {
-		new.Cmds = make([]*taskfile.Cmd, len(origTask.Cmds))
-		for i, cmd := range origTask.Cmds {
-			new.Cmds[i] = &taskfile.Cmd{
+		new.Cmds = make([]*taskfile.Cmd, 0, len(origTask.Cmds))
+		for _, cmd := range origTask.Cmds {
+			if cmd == nil {
+				continue
+			}
+			new.Cmds = append(new.Cmds, &taskfile.Cmd{
 				Task:        r.Replace(cmd.Task),
 				Silent:      cmd.Silent,
 				Cmd:         r.Replace(cmd.Cmd),
 				Vars:        r.ReplaceVars(cmd.Vars),
 				IgnoreError: cmd.IgnoreError,
-			}
+			})
 		}
 	}
 	if len(origTask.Deps) > 0 {
-		new.Deps = make([]*taskfile.Dep, len(origTask.Deps))
-		for i, dep := range origTask.Deps {
-			new.Deps[i] = &taskfile.Dep{
+		new.Deps = make([]*taskfile.Dep, 0, len(origTask.Deps))
+		for _, dep := range origTask.Deps {
+			if dep == nil {
+				continue
+			}
+			new.Deps = append(new.Deps, &taskfile.Dep{
 				Task: r.Replace(dep.Task),
 				Vars: r.ReplaceVars(dep.Vars),
-			}
+			})
 		}
 	}
 
 	if len(origTask.Preconditions) > 0 {
-		new.Preconditions = make([]*taskfile.Precondition, len(origTask.Preconditions))
-		for i, precond := range origTask.Preconditions {
-			new.Preconditions[i] = &taskfile.Precondition{
+		new.Preconditions = make([]*taskfile.Precondition, 0, len(origTask.Preconditions))
+		for _, precond := range origTask.Preconditions {
+			if precond == nil {
+				continue
+			}
+			new.Preconditions = append(new.Preconditions, &taskfile.Precondition{
 				Sh:  r.Replace(precond.Sh),
 				Msg: r.Replace(precond.Msg),
-			}
+			})
 		}
 	}
 


Test patch:
diff --git a/task_test.go b/task_test.go
index d35b8a39..5243c62f 100644
--- a/task_test.go
+++ b/task_test.go
@@ -990,3 +990,29 @@ func TestRunOnlyRunsJobsHashOnce(t *testing.T) {
 	}
 	tt.Run(t)
 }
+
+func TestIgnoreNilElements(t *testing.T) {
+	tests := []struct {
+		name string
+		dir  string
+	}{
+		{"nil cmd", "testdata/ignore_nil_elements/cmds"},
+		{"nil dep", "testdata/ignore_nil_elements/deps"},
+		{"nil precondition", "testdata/ignore_nil_elements/preconditions"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			var buff bytes.Buffer
+			e := task.Executor{
+				Dir:    test.dir,
+				Stdout: &buff,
+				Stderr: &buff,
+				Silent: true,
+			}
+			assert.NoError(t, e.Setup())
+			assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
+			assert.Equal(t, "string-slice-1\n", buff.String())
+		})
+	}
+}
diff --git a/testdata/ignore_nil_elements/cmds/Taskfile.yml b/testdata/ignore_nil_elements/cmds/Taskfile.yml
new file mode 100644
index 00000000..a20cb706
--- /dev/null
+++ b/testdata/ignore_nil_elements/cmds/Taskfile.yml
@@ -0,0 +1,7 @@
+version: '3'
+
+tasks:
+  default:
+    cmds:
+      - echo "string-slice-1"
+      -
diff --git a/testdata/ignore_nil_elements/deps/Taskfile.yml b/testdata/ignore_nil_elements/deps/Taskfile.yml
new file mode 100644
index 00000000..aa7e2391
--- /dev/null
+++ b/testdata/ignore_nil_elements/deps/Taskfile.yml
@@ -0,0 +1,11 @@
+version: '3'
+
+tasks:
+  default:
+    deps:
+      -
+      - task: dep
+
+  dep:
+    cmds:
+      - echo "string-slice-1"
diff --git a/testdata/ignore_nil_elements/preconditions/Taskfile.yml b/testdata/ignore_nil_elements/preconditions/Taskfile.yml
new file mode 100644
index 00000000..261c7c58
--- /dev/null
+++ b/testdata/ignore_nil_elements/preconditions/Taskfile.yml
@@ -0,0 +1,9 @@
+version: '3'
+
+tasks:
+  default:
+    preconditions:
+      -
+      - sh: "[ 1 = 1 ]"
+    cmds:
+      - echo "string-slice-1"