present: validate background directive arguments

The .background directive assumes that an image argument is always
present and accesses args[1] without first checking the argument count.
As a result, a directive with no argument causes Parse to panic, while
extra arguments are silently ignored.

Require exactly one argument and return a parsing error for malformed
.background directives. Add tests for missing and extra arguments.

Fixes golang/go#80570

Change-Id: Iefeab0fd706fc11de6c2134d98fe4e3e9c836169
Reviewed-on: https://go-review.googlesource.com/c/tools/+/805940
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Sean Liao <sean@liao.dev>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
diff --git a/present/parse.go b/present/parse.go
index 8b41dd2..a0e1d58 100644
--- a/present/parse.go
+++ b/present/parse.go
@@ -458,6 +458,9 @@
 			case strings.HasPrefix(text, "."):
 				args := strings.Fields(text)
 				if args[0] == ".background" {
+					if len(args) != 2 {
+						return nil, fmt.Errorf("%s:%d: .background expects exactly one argument", name, lines.line)
+					}
 					section.Classes = append(section.Classes, "background")
 					section.Styles = append(section.Styles, "background-image: url('"+args[1]+"')")
 					break
diff --git a/present/parse_test.go b/present/parse_test.go
index bb0fe72..064fc23 100644
--- a/present/parse_test.go
+++ b/present/parse_test.go
@@ -12,9 +12,35 @@
 	"os/exec"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"testing"
 )
 
+func TestBackgroundErrors(t *testing.T) {
+	const input = `Title
+
+* Slide
+
+%s
+`
+	const want = "test.slide:5: .background expects exactly one argument"
+
+	for _, directive := range []string{
+		".background",
+		".background a.png b.png",
+	} {
+		t.Run(directive, func(t *testing.T) {
+			_, err := Parse(strings.NewReader(fmt.Sprintf(input, directive)), "test.slide", 0)
+			if err == nil {
+				t.Fatalf("Parse did not return an error")
+			}
+			if got := err.Error(); got != want {
+				t.Errorf("Parse error = %q, want %q", got, want)
+			}
+		})
+	}
+}
+
 func TestTestdata(t *testing.T) {
 	tmpl := template.Must(Template().Parse(testTmpl))
 	filesP, err := filepath.Glob("testdata/*.p")