mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
compile/compile: Fix panic from CLI + metadata entrypoint overlaps.
This commit fixes a panic that could occur when `opa build` was provided an entrypoint from both a CLI flag, and via entrypoint metadata annotation. The fix is simple: deduplicate the slice of entrypoint refs that the compiler uses, before compiling WASM or Plan targets. Fixes: #6661 Co-authored-by: Daniel Herzig <danielherzig96@gmail.com> Signed-off-by: Philip Conrad <philipaconrad@gmail.com>
This commit is contained in:
committed by
Ashutosh Narkar
parent
e0060ce6a1
commit
88eaaa93ad
+27
-1
@@ -326,6 +326,12 @@ func (c *Compiler) Build(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Dedup entrypoint refs, if both CLI and entrypoint metadata annotations
|
||||
// were used.
|
||||
if err := c.dedupEntrypointRefs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.optimize(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -429,6 +435,27 @@ func (c *Compiler) checkNumEntrypoints() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note(philipc): When an entrypoint is provided on the CLI and from an
|
||||
// entrypoint annotation, it can lead to duplicates in the slice of
|
||||
// entrypoint refs. This can cause panics down the line due to c.entrypoints
|
||||
// being a different length than c.entrypointrefs. As a result, we have to
|
||||
// trim out the duplicates.
|
||||
func (c *Compiler) dedupEntrypointRefs() error {
|
||||
// Build list of entrypoint refs, without duplicates.
|
||||
newEntrypointRefs := make([]*ast.Term, 0, len(c.entrypointrefs))
|
||||
entrypointRefSet := make(map[string]struct{}, len(c.entrypointrefs))
|
||||
for i, r := range c.entrypointrefs {
|
||||
refString := r.String()
|
||||
// Store only the first index in the list that matches.
|
||||
if _, ok := entrypointRefSet[refString]; !ok {
|
||||
entrypointRefSet[refString] = struct{}{}
|
||||
newEntrypointRefs = append(newEntrypointRefs, c.entrypointrefs[i])
|
||||
}
|
||||
}
|
||||
c.entrypointrefs = newEntrypointRefs
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bundle returns the compiled bundle. This function can be called to retrieve the
|
||||
// output of the compiler (as an alternative to having the bundle written to a stream.)
|
||||
func (c *Compiler) Bundle() *bundle.Bundle {
|
||||
@@ -506,7 +533,6 @@ func (c *Compiler) initBundle() error {
|
||||
}
|
||||
|
||||
func (c *Compiler) optimize(ctx context.Context) error {
|
||||
|
||||
if c.optimizationLevel <= 0 {
|
||||
var err error
|
||||
c.compiler, err = compile(c.capabilities, c.bundle, c.debug, c.enablePrintStatements)
|
||||
|
||||
+22
-2
@@ -978,9 +978,7 @@ update {
|
||||
|
||||
func modulesToString(modules []bundle.ModuleFile) string {
|
||||
var buf bytes.Buffer
|
||||
//result := make([]string, len(modules))
|
||||
for i, m := range modules {
|
||||
//result[i] = m.Parsed.String()
|
||||
buf.WriteString(strconv.Itoa(i))
|
||||
buf.WriteString(":\n")
|
||||
buf.WriteString(string(m.Raw))
|
||||
@@ -1623,6 +1621,28 @@ q[3]
|
||||
"test/p": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
note: "overlapping manual entrypoints + annotation entrypoints",
|
||||
entrypoints: []string{"test/p"},
|
||||
modules: map[string]string{
|
||||
"test.rego": `
|
||||
package test
|
||||
|
||||
# METADATA
|
||||
# entrypoint: true
|
||||
p {
|
||||
q[input.x]
|
||||
}
|
||||
|
||||
q[1]
|
||||
q[2]
|
||||
q[3]
|
||||
`,
|
||||
},
|
||||
wantEntrypoints: map[string]struct{}{
|
||||
"test/p": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
note: "ref head rule annotation",
|
||||
entrypoints: []string{},
|
||||
|
||||
Reference in New Issue
Block a user