Skip to content

ExtractVariables does not report a variable used inside a ${VAR:?…} message #934

Description

@DRMacIver

A variable that appears only inside the message of a required-variable expansion is left out of ExtractVariables: ${U:?${B}} and ${U?$B} report U alone, while ${U:-${B}} and ${U:+${B}} report both U and B, and Substitute expands B into the message of the same template:

package main

import (
	"fmt"
	"sort"

	"github.com/compose-spec/compose-go/v2/template"
)

func main() {
	for _, tmpl := range []string{"${U:-${B}}", "${U:+${B}}", "${U:?${B}}", "${U?$B}"} {
		vars := template.ExtractVariables(map[string]interface{}{"k": tmpl}, nil)
		names := make([]string, 0, len(vars))
		for name := range vars {
			names = append(names, name)
		}
		sort.Strings(names)
		fmt.Printf("%-12s %v\n", tmpl, names)
	}

	mapping := func(name string) (string, bool) {
		if name == "B" {
			return "value of B", true
		}
		return "", false
	}
	_, err := template.SubstituteWithOptions("${U:?${B}}", mapping, template.WithoutLogging)
	fmt.Println(err)
}

Output:

${U:-${B}}   [B U]
${U:+${B}}   [B U]
${U:?${B}}   [U]
${U?$B}      [U]
required variable U is missing a value: value of B

The specification lists ${VARIABLE?$FOO} among the nested interpolations, and substitution does read B when building the message, so I expected ExtractVariables to report B for the :? and ? forms as it does for :- and :+.

Tested on compose-go v2.15.0 and on current main (f18e211).

BTW, this was found by an automated program that writes property-based tests for various open source projects using hegel (but it has been reviewed by hand before reporting). We've also potentially found (but not yet hand validated) 2 other bugs in compose-go. You can see the tests at https://github.com/hegeldev/hegel-zoo/tree/main/targets/go/compose-go. Let us know if you would like us to file the other bugs found and/or contribute the tests. NB the tests are currently LLM generated and probably not yet suitable for inclusion as is, but we're happy to help get them into a better state if you want them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions