build(deps): bump github.com/open-policy-agent/opa from 1.10.1 to 1.11.0

Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.10.1 to 1.11.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.10.1...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-12-18 13:33:02 +01:00
committed by Ralf Haferkamp
parent 5ed944dfc3
commit 82c82f8ae2
94 changed files with 6802 additions and 1946 deletions
+232 -190
View File
@@ -32,7 +32,7 @@ const (
opaWasmABIMinorVersionVar = "opa_wasm_abi_minor_version"
)
// nolint: deadcode,varcheck
// nolint: varcheck
const (
opaTypeNull int32 = iota + 1
opaTypeBoolean
@@ -414,7 +414,7 @@ func (c *Compiler) initModule() error {
},
},
},
Init: bytes.Repeat([]byte{0}, int(heapBase-offset)),
Init: make([]byte, int(heapBase-offset)),
})
return nil
@@ -1058,9 +1058,11 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err
},
})
case *ir.AssignIntStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs, instruction.I64Const{Value: stmt.Value})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueNumberSetInt)})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Target)},
instruction.I64Const{Value: stmt.Value},
instruction.Call{Index: c.function(opaValueNumberSetInt)},
)
case *ir.ScanStmt:
if err := c.compileScan(stmt, &instrs); err != nil {
return nil, err
@@ -1073,12 +1075,14 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err
}
case *ir.DotStmt:
if loc, ok := stmt.Source.Value.(ir.Local); ok {
instrs = append(instrs, instruction.GetLocal{Index: c.local(loc)})
instrs = append(instrs, c.instrRead(stmt.Key))
instrs = append(instrs, instruction.Call{Index: c.function(opaValueGet)})
instrs = append(instrs, instruction.TeeLocal{Index: c.local(stmt.Target)})
instrs = append(instrs, instruction.I32Eqz{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(loc)},
c.instrRead(stmt.Key),
instruction.Call{Index: c.function(opaValueGet)},
instruction.TeeLocal{Index: c.local(stmt.Target)},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
)
} else {
// Booleans and string sources would lead to the BrIf (since opa_value_get
// on them returns 0), so let's skip trying that.
@@ -1086,97 +1090,131 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err
break
}
case *ir.LenStmt:
instrs = append(instrs, c.instrRead(stmt.Source))
instrs = append(instrs, instruction.Call{Index: c.function(opaValueLength)})
instrs = append(instrs, instruction.Call{Index: c.function(opaNumberSize)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
c.instrRead(stmt.Source),
instruction.Call{Index: c.function(opaValueLength)},
instruction.Call{Index: c.function(opaNumberSize)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.EqualStmt:
instrs = append(instrs, c.instrRead(stmt.A))
instrs = append(instrs, c.instrRead(stmt.B))
instrs = append(instrs, instruction.Call{Index: c.function(opaValueCompare)})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
c.instrRead(stmt.A),
c.instrRead(stmt.B),
instruction.Call{Index: c.function(opaValueCompare)},
instruction.BrIf{Index: 0},
)
case *ir.NotEqualStmt:
instrs = append(instrs, c.instrRead(stmt.A))
instrs = append(instrs, c.instrRead(stmt.B))
instrs = append(instrs, instruction.Call{Index: c.function(opaValueCompare)})
instrs = append(instrs, instruction.I32Eqz{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
c.instrRead(stmt.A),
c.instrRead(stmt.B),
instruction.Call{Index: c.function(opaValueCompare)},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
)
case *ir.MakeNullStmt:
instrs = append(instrs, instruction.Call{Index: c.function(opaNull)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.Call{Index: c.function(opaNull)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.MakeNumberIntStmt:
instrs = append(instrs, instruction.I64Const{Value: stmt.Value})
instrs = append(instrs, instruction.Call{Index: c.function(opaNumberInt)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.I64Const{Value: stmt.Value},
instruction.Call{Index: c.function(opaNumberInt)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.MakeNumberRefStmt:
instrs = append(instrs, instruction.I32Const{Value: c.stringAddr(stmt.Index)})
instrs = append(instrs, instruction.I32Const{Value: int32(len(c.policy.Static.Strings[stmt.Index].Value))})
instrs = append(instrs, instruction.Call{Index: c.function(opaNumberRef)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.I32Const{Value: c.stringAddr(stmt.Index)},
instruction.I32Const{Value: int32(len(c.policy.Static.Strings[stmt.Index].Value))},
instruction.Call{Index: c.function(opaNumberRef)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.MakeArrayStmt:
instrs = append(instrs, instruction.I32Const{Value: stmt.Capacity})
instrs = append(instrs, instruction.Call{Index: c.function(opaArrayWithCap)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.I32Const{Value: stmt.Capacity},
instruction.Call{Index: c.function(opaArrayWithCap)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.MakeObjectStmt:
instrs = append(instrs, instruction.Call{Index: c.function(opaObject)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.Call{Index: c.function(opaObject)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.MakeSetStmt:
instrs = append(instrs, instruction.Call{Index: c.function(opaSet)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.Call{Index: c.function(opaSet)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.IsArrayStmt:
if loc, ok := stmt.Source.Value.(ir.Local); ok {
instrs = append(instrs, instruction.GetLocal{Index: c.local(loc)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueType)})
instrs = append(instrs, instruction.I32Const{Value: opaTypeArray})
instrs = append(instrs, instruction.I32Ne{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(loc)},
instruction.Call{Index: c.function(opaValueType)},
instruction.I32Const{Value: opaTypeArray},
instruction.I32Ne{},
instruction.BrIf{Index: 0},
)
} else {
instrs = append(instrs, instruction.Br{Index: 0})
break
}
case *ir.IsObjectStmt:
if loc, ok := stmt.Source.Value.(ir.Local); ok {
instrs = append(instrs, instruction.GetLocal{Index: c.local(loc)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueType)})
instrs = append(instrs, instruction.I32Const{Value: opaTypeObject})
instrs = append(instrs, instruction.I32Ne{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(loc)},
instruction.Call{Index: c.function(opaValueType)},
instruction.I32Const{Value: opaTypeObject},
instruction.I32Ne{},
instruction.BrIf{Index: 0},
)
} else {
instrs = append(instrs, instruction.Br{Index: 0})
break
}
case *ir.IsSetStmt:
if loc, ok := stmt.Source.Value.(ir.Local); ok {
instrs = append(instrs, instruction.GetLocal{Index: c.local(loc)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueType)})
instrs = append(instrs, instruction.I32Const{Value: opaTypeSet})
instrs = append(instrs, instruction.I32Ne{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(loc)},
instruction.Call{Index: c.function(opaValueType)},
instruction.I32Const{Value: opaTypeSet},
instruction.I32Ne{},
instruction.BrIf{Index: 0},
)
} else {
instrs = append(instrs, instruction.Br{Index: 0})
break
}
case *ir.IsUndefinedStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Source)})
instrs = append(instrs, instruction.I32Const{Value: 0})
instrs = append(instrs, instruction.I32Ne{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Source)},
instruction.I32Const{Value: 0},
instruction.I32Ne{},
instruction.BrIf{Index: 0},
)
case *ir.ResetLocalStmt:
instrs = append(instrs, instruction.I32Const{Value: 0})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.I32Const{Value: 0},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.IsDefinedStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Source)})
instrs = append(instrs, instruction.I32Eqz{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Source)},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
)
case *ir.ArrayAppendStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Array)})
instrs = append(instrs, c.instrRead(stmt.Value))
instrs = append(instrs, instruction.Call{Index: c.function(opaArrayAppend)})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Array)},
c.instrRead(stmt.Value),
instruction.Call{Index: c.function(opaArrayAppend)},
)
case *ir.ObjectInsertStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Object)})
instrs = append(instrs, c.instrRead(stmt.Key))
instrs = append(instrs, c.instrRead(stmt.Value))
instrs = append(instrs, instruction.Call{Index: c.function(opaObjectInsert)})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Object)},
c.instrRead(stmt.Key),
c.instrRead(stmt.Value),
instruction.Call{Index: c.function(opaObjectInsert)},
)
case *ir.ObjectInsertOnceStmt:
tmp := c.genLocal()
instrs = append(instrs, instruction.Block{
@@ -1203,14 +1241,18 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err
},
})
case *ir.ObjectMergeStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.A)})
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.B)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueMerge)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(stmt.Target)})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.A)},
instruction.GetLocal{Index: c.local(stmt.B)},
instruction.Call{Index: c.function(opaValueMerge)},
instruction.SetLocal{Index: c.local(stmt.Target)},
)
case *ir.SetAddStmt:
instrs = append(instrs, instruction.GetLocal{Index: c.local(stmt.Set)})
instrs = append(instrs, c.instrRead(stmt.Value))
instrs = append(instrs, instruction.Call{Index: c.function(opaSetAdd)})
instrs = append(instrs,
instruction.GetLocal{Index: c.local(stmt.Set)},
c.instrRead(stmt.Value),
instruction.Call{Index: c.function(opaSetAdd)},
)
default:
var buf bytes.Buffer
err := ir.Pretty(&buf, stmt)
@@ -1226,8 +1268,7 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err
func (c *Compiler) compileScan(scan *ir.ScanStmt, result *[]instruction.Instruction) error {
var instrs = *result
instrs = append(instrs, instruction.I32Const{Value: 0})
instrs = append(instrs, instruction.SetLocal{Index: c.local(scan.Key)})
instrs = append(instrs, instruction.I32Const{Value: 0}, instruction.SetLocal{Index: c.local(scan.Key)})
body, err := c.compileScanBlock(scan)
if err != nil {
return err
@@ -1242,23 +1283,21 @@ func (c *Compiler) compileScan(scan *ir.ScanStmt, result *[]instruction.Instruct
}
func (c *Compiler) compileScanBlock(scan *ir.ScanStmt) ([]instruction.Instruction, error) {
var instrs []instruction.Instruction
// Execute iterator.
instrs = append(instrs, instruction.GetLocal{Index: c.local(scan.Source)})
instrs = append(instrs, instruction.GetLocal{Index: c.local(scan.Key)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueIter)})
// Check for emptiness.
instrs = append(instrs, instruction.TeeLocal{Index: c.local(scan.Key)})
instrs = append(instrs, instruction.I32Eqz{})
instrs = append(instrs, instruction.BrIf{Index: 1})
// Load value.
instrs = append(instrs, instruction.GetLocal{Index: c.local(scan.Source)})
instrs = append(instrs, instruction.GetLocal{Index: c.local(scan.Key)})
instrs = append(instrs, instruction.Call{Index: c.function(opaValueGet)})
instrs = append(instrs, instruction.SetLocal{Index: c.local(scan.Value)})
instrs := []instruction.Instruction{
// Execute iterator.
instruction.GetLocal{Index: c.local(scan.Source)},
instruction.GetLocal{Index: c.local(scan.Key)},
instruction.Call{Index: c.function(opaValueIter)},
// Check for emptiness.
instruction.TeeLocal{Index: c.local(scan.Key)},
instruction.I32Eqz{},
instruction.BrIf{Index: 1},
// Load value.
instruction.GetLocal{Index: c.local(scan.Source)},
instruction.GetLocal{Index: c.local(scan.Key)},
instruction.Call{Index: c.function(opaValueGet)},
instruction.SetLocal{Index: c.local(scan.Value)},
}
// Loop body.
nested, err := c.compileBlock(scan.Block)
@@ -1278,8 +1317,7 @@ func (c *Compiler) compileNot(not *ir.NotStmt, result *[]instruction.Instruction
// generate and initialize condition variable
cond := c.genLocal()
instrs = append(instrs, instruction.I32Const{Value: 1})
instrs = append(instrs, instruction.SetLocal{Index: cond})
instrs = append(instrs, instruction.I32Const{Value: 1}, instruction.SetLocal{Index: cond})
nested, err := c.compileBlock(not.Block)
if err != nil {
@@ -1287,14 +1325,15 @@ func (c *Compiler) compileNot(not *ir.NotStmt, result *[]instruction.Instruction
}
// unset condition variable if end of block is reached
nested = append(nested, instruction.I32Const{Value: 0})
nested = append(nested, instruction.SetLocal{Index: cond})
instrs = append(instrs, instruction.Block{Instrs: nested})
// break out of block if condition variable was unset
instrs = append(instrs, instruction.GetLocal{Index: cond})
instrs = append(instrs, instruction.I32Eqz{})
instrs = append(instrs, instruction.BrIf{Index: 0})
instrs = append(instrs, instruction.Block{Instrs: append(nested,
instruction.I32Const{Value: 0},
instruction.SetLocal{Index: cond},
)},
// break out of block if condition variable was unset
instruction.GetLocal{Index: cond},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
)
*result = instrs
return nil
@@ -1304,34 +1343,36 @@ func (c *Compiler) compileWithStmt(with *ir.WithStmt, result *[]instruction.Inst
var instrs = *result
save := c.genLocal()
instrs = append(instrs, instruction.Call{Index: c.function(opaMemoizePush)})
instrs = append(instrs, instruction.GetLocal{Index: c.local(with.Local)})
instrs = append(instrs, instruction.SetLocal{Index: save})
instrs = append(instrs,
instruction.Call{Index: c.function(opaMemoizePush)},
instruction.GetLocal{Index: c.local(with.Local)},
instruction.SetLocal{Index: save},
)
if len(with.Path) == 0 {
instrs = append(instrs, c.instrRead(with.Value))
instrs = append(instrs, instruction.SetLocal{Index: c.local(with.Local)})
instrs = append(instrs, c.instrRead(with.Value), instruction.SetLocal{Index: c.local(with.Local)})
} else {
instrs = c.compileUpsert(with.Local, with.Path, with.Value, with.Location, instrs)
}
undefined := c.genLocal()
instrs = append(instrs, instruction.I32Const{Value: 1})
instrs = append(instrs, instruction.SetLocal{Index: undefined})
instrs = append(instrs, instruction.I32Const{Value: 1}, instruction.SetLocal{Index: undefined})
nested, err := c.compileBlock(with.Block)
if err != nil {
return err
}
nested = append(nested, instruction.I32Const{Value: 0})
nested = append(nested, instruction.SetLocal{Index: undefined})
instrs = append(instrs, instruction.Block{Instrs: nested})
instrs = append(instrs, instruction.GetLocal{Index: save})
instrs = append(instrs, instruction.SetLocal{Index: c.local(with.Local)})
instrs = append(instrs, instruction.Call{Index: c.function(opaMemoizePop)})
instrs = append(instrs, instruction.GetLocal{Index: undefined})
instrs = append(instrs, instruction.BrIf{Index: 0})
nested = append(nested, instruction.I32Const{Value: 0}, instruction.SetLocal{Index: undefined})
instrs = append(instrs,
instruction.Block{Instrs: nested},
instruction.GetLocal{Index: save},
instruction.SetLocal{Index: c.local(with.Local)},
instruction.Call{Index: c.function(opaMemoizePop)},
instruction.GetLocal{Index: undefined},
instruction.BrIf{Index: 0},
)
*result = instrs
@@ -1339,37 +1380,38 @@ func (c *Compiler) compileWithStmt(with *ir.WithStmt, result *[]instruction.Inst
}
func (c *Compiler) compileUpsert(local ir.Local, path []int, value ir.Operand, _ ir.Location, instrs []instruction.Instruction) []instruction.Instruction {
lcopy := c.genLocal() // holds copy of local
instrs = append(instrs, instruction.GetLocal{Index: c.local(local)})
instrs = append(instrs, instruction.SetLocal{Index: lcopy})
// Shallow copy the local if defined otherwise initialize to an empty object.
instrs = append(instrs, instruction.Block{
Instrs: []instruction.Instruction{
instruction.Block{Instrs: []instruction.Instruction{
instruction.GetLocal{Index: lcopy},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
instruction.GetLocal{Index: lcopy},
instruction.Call{Index: c.function(opaValueShallowCopy)},
instrs = append(instrs,
instruction.GetLocal{Index: c.local(local)},
instruction.SetLocal{Index: lcopy},
// Shallow copy the local if defined otherwise initialize to an empty object.
instruction.Block{
Instrs: []instruction.Instruction{
instruction.Block{Instrs: []instruction.Instruction{
instruction.GetLocal{Index: lcopy},
instruction.I32Eqz{},
instruction.BrIf{Index: 0},
instruction.GetLocal{Index: lcopy},
instruction.Call{Index: c.function(opaValueShallowCopy)},
instruction.TeeLocal{Index: lcopy},
instruction.SetLocal{Index: c.local(local)},
instruction.Br{Index: 1},
}},
instruction.Call{Index: c.function(opaObject)},
instruction.TeeLocal{Index: lcopy},
instruction.SetLocal{Index: c.local(local)},
instruction.Br{Index: 1},
}},
instruction.Call{Index: c.function(opaObject)},
instruction.TeeLocal{Index: lcopy},
instruction.SetLocal{Index: c.local(local)},
},
})
},
})
// Initialize the locals that specify the path of the upsert operation.
lpath := make(map[int]uint32, len(path))
for i := range path {
lpath[i] = c.genLocal()
instrs = append(instrs, instruction.I32Const{Value: c.opaStringAddr(path[i])})
instrs = append(instrs, instruction.SetLocal{Index: lpath[i]})
instrs = append(instrs,
instruction.I32Const{Value: c.opaStringAddr(path[i])},
instruction.SetLocal{Index: lpath[i]},
)
}
// Generate a block that traverses the path of the upsert operation,
@@ -1379,36 +1421,34 @@ func (c *Compiler) compileUpsert(local ir.Local, path []int, value ir.Operand, _
ltemp := c.genLocal()
for i := range len(path) - 1 {
// Lookup the next part of the path.
inner = append(inner, instruction.GetLocal{Index: lcopy})
inner = append(inner, instruction.GetLocal{Index: lpath[i]})
inner = append(inner, instruction.Call{Index: c.function(opaValueGet)})
inner = append(inner, instruction.SetLocal{Index: ltemp})
// If the next node is missing, break.
inner = append(inner, instruction.GetLocal{Index: ltemp})
inner = append(inner, instruction.I32Eqz{})
inner = append(inner, instruction.BrIf{Index: uint32(i)})
// If the next node is not an object, break.
inner = append(inner, instruction.GetLocal{Index: ltemp})
inner = append(inner, instruction.Call{Index: c.function(opaValueType)})
inner = append(inner, instruction.I32Const{Value: opaTypeObject})
inner = append(inner, instruction.I32Ne{})
inner = append(inner, instruction.BrIf{Index: uint32(i)})
// Otherwise, shallow copy the next node node and insert into the copy
// before continuing.
inner = append(inner, instruction.GetLocal{Index: ltemp})
inner = append(inner, instruction.Call{Index: c.function(opaValueShallowCopy)})
inner = append(inner, instruction.SetLocal{Index: ltemp})
inner = append(inner, instruction.GetLocal{Index: lcopy})
inner = append(inner, instruction.GetLocal{Index: lpath[i]})
inner = append(inner, instruction.GetLocal{Index: ltemp})
inner = append(inner, instruction.Call{Index: c.function(opaObjectInsert)})
inner = append(inner, instruction.GetLocal{Index: ltemp})
inner = append(inner, instruction.SetLocal{Index: lcopy})
inner = append(inner,
// Lookup the next part of the path.
instruction.GetLocal{Index: lcopy},
instruction.GetLocal{Index: lpath[i]},
instruction.Call{Index: c.function(opaValueGet)},
instruction.SetLocal{Index: ltemp},
// If the next node is missing, break.
instruction.GetLocal{Index: ltemp},
instruction.I32Eqz{},
instruction.BrIf{Index: uint32(i)},
// If the next node is not an object, break.
instruction.GetLocal{Index: ltemp},
instruction.Call{Index: c.function(opaValueType)},
instruction.I32Const{Value: opaTypeObject},
instruction.I32Ne{},
instruction.BrIf{Index: uint32(i)},
// Otherwise, shallow copy the next node node and insert into the copy
// before continuing.
instruction.GetLocal{Index: ltemp},
instruction.Call{Index: c.function(opaValueShallowCopy)},
instruction.SetLocal{Index: ltemp},
instruction.GetLocal{Index: lcopy},
instruction.GetLocal{Index: lpath[i]},
instruction.GetLocal{Index: ltemp},
instruction.Call{Index: c.function(opaObjectInsert)},
instruction.GetLocal{Index: ltemp},
instruction.SetLocal{Index: lcopy},
)
}
inner = append(inner, instruction.Br{Index: uint32(len(path) - 1)})
@@ -1418,27 +1458,29 @@ func (c *Compiler) compileUpsert(local ir.Local, path []int, value ir.Operand, _
lval := c.genLocal()
for i := range len(path) - 1 {
block = append(block, instruction.Block{Instrs: inner})
block = append(block, instruction.Call{Index: c.function(opaObject)})
block = append(block, instruction.SetLocal{Index: lval})
block = append(block, instruction.GetLocal{Index: lcopy})
block = append(block, instruction.GetLocal{Index: lpath[i]})
block = append(block, instruction.GetLocal{Index: lval})
block = append(block, instruction.Call{Index: c.function(opaObjectInsert)})
block = append(block, instruction.GetLocal{Index: lval})
block = append(block, instruction.SetLocal{Index: lcopy})
block = append(block,
instruction.Block{Instrs: inner},
instruction.Call{Index: c.function(opaObject)},
instruction.SetLocal{Index: lval},
instruction.GetLocal{Index: lcopy},
instruction.GetLocal{Index: lpath[i]},
instruction.GetLocal{Index: lval},
instruction.Call{Index: c.function(opaObjectInsert)},
instruction.GetLocal{Index: lval},
instruction.SetLocal{Index: lcopy},
)
inner = block
block = nil
}
// Finish by inserting the statement's value into the shallow copied node.
instrs = append(instrs, instruction.Block{Instrs: inner})
instrs = append(instrs, instruction.GetLocal{Index: lcopy})
instrs = append(instrs, instruction.GetLocal{Index: lpath[len(path)-1]})
instrs = append(instrs, c.instrRead(value))
instrs = append(instrs, instruction.Call{Index: c.function(opaObjectInsert)})
return instrs
return append(instrs,
instruction.Block{Instrs: inner},
instruction.GetLocal{Index: lcopy},
instruction.GetLocal{Index: lpath[len(path)-1]},
c.instrRead(value),
instruction.Call{Index: c.function(opaObjectInsert)},
)
}
func (c *Compiler) compileCallDynamicStmt(stmt *ir.CallDynamicStmt, result *[]instruction.Instruction) error {
+53 -20
View File
@@ -4,39 +4,72 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/json"
"errors"
"io"
"strings"
)
// MustWriteTarGz write the list of file names and content
// into a tarball.
func MustWriteTarGz(files [][2]string) *bytes.Buffer {
var buf bytes.Buffer
gw := gzip.NewWriter(&buf)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
for _, file := range files {
if err := WriteFile(tw, file[0], []byte(file[1])); err != nil {
panic(err)
}
}
return &buf
type TarGzWriter struct {
*tar.Writer
gw *gzip.Writer
}
// WriteFile adds a file header with content to the given tar writer
func WriteFile(tw *tar.Writer, path string, bs []byte) error {
func NewTarGzWriter(w io.Writer) *TarGzWriter {
gw := gzip.NewWriter(w)
tw := tar.NewWriter(gw)
return &TarGzWriter{
Writer: tw,
gw: gw,
}
}
func (tgw *TarGzWriter) WriteFile(path string, bs []byte) (err error) {
hdr := &tar.Header{
Name: "/" + strings.TrimLeft(path, "/"),
Name: path,
Mode: 0600,
Typeflag: tar.TypeReg,
Size: int64(len(bs)),
}
if err := tw.WriteHeader(hdr); err != nil {
if err = tgw.WriteHeader(hdr); err == nil {
_, err = tgw.Write(bs)
}
return err
}
func (tgw *TarGzWriter) WriteJSONFile(path string, v any) error {
buf := &bytes.Buffer{}
if err := json.NewEncoder(buf).Encode(v); err != nil {
return err
}
_, err := tw.Write(bs)
return err
return tgw.WriteFile(path, buf.Bytes())
}
func (tgw *TarGzWriter) Close() error {
return errors.Join(tgw.Writer.Close(), tgw.gw.Close())
}
// MustWriteTarGz writes the list of file names and content into a tarball.
// Paths are prefixed with "/".
func MustWriteTarGz(files [][2]string) *bytes.Buffer {
buf := &bytes.Buffer{}
tgw := NewTarGzWriter(buf)
defer tgw.Close()
for _, file := range files {
if !strings.HasPrefix(file[0], "/") {
file[0] = "/" + file[0]
}
if err := tgw.WriteFile(file[0], []byte(file[1])); err != nil {
panic(err)
}
}
return buf
}
+1 -1
View File
@@ -23,7 +23,7 @@
//
// created 26-02-2013
// nolint: deadcode,unused,varcheck // Package in development (2021).
// nolint:unused,varcheck // Package in development (2021).
package gojsonschema
import (
@@ -158,6 +158,8 @@ func SignV4(headers map[string][]string, method string, theURL *url.URL, body []
// include the values for the signed headers
orderedKeys := util.KeysSorted(headersToSign)
for _, k := range orderedKeys {
// TODO: fix later
//nolint:perfsprint
canonicalReq += k + ":" + strings.Join(headersToSign[k], ",") + "\n"
}
canonicalReq += "\n" // linefeed to terminate headers
+2 -2
View File
@@ -7,16 +7,16 @@ package ref
import (
"errors"
"strings"
"github.com/open-policy-agent/opa/v1/ast"
"github.com/open-policy-agent/opa/v1/storage"
"github.com/open-policy-agent/opa/v1/util"
)
// ParseDataPath returns a ref from the slash separated path s rooted at data.
// All path segments are treated as identifier strings.
func ParseDataPath(s string) (ast.Ref, error) {
path, ok := storage.ParsePath("/" + strings.TrimPrefix(s, "/"))
path, ok := storage.ParsePath(util.WithPrefix(s, "/"))
if !ok {
return nil, errors.New("invalid path")
}
+6 -10
View File
@@ -81,8 +81,6 @@ type GHResponse struct {
// New returns an instance of the Reporter
func New(opts Options) (Reporter, error) {
r := GHVersionCollector{}
url := cmp.Or(os.Getenv("OPA_TELEMETRY_SERVICE_URL"), ExternalServiceURL)
restConfig := fmt.Appendf(nil, `{
@@ -93,7 +91,7 @@ func New(opts Options) (Reporter, error) {
if err != nil {
return nil, err
}
r.client = client
r := GHVersionCollector{client: client}
// heap_usage_bytes is always present, so register it unconditionally
r.RegisterGatherer("heap_usage_bytes", readRuntimeMemStats)
@@ -135,19 +133,17 @@ func createDataResponse(ghResp GHResponse) (*DataResponse, error) {
return nil, errors.New("server response does not contain tag_name")
}
v := strings.TrimPrefix(version.Version, "v")
sv, err := semver.NewVersion(v)
sv, err := semver.Parse(version.Version)
if err != nil {
return nil, fmt.Errorf("failed to parse current version %q: %w", v, err)
return nil, fmt.Errorf("failed to parse current version %q: %w", version.Version, err)
}
latestV := strings.TrimPrefix(ghResp.TagName, "v")
latestSV, err := semver.NewVersion(latestV)
latestSV, err := semver.Parse(ghResp.TagName)
if err != nil {
return nil, fmt.Errorf("failed to parse latest version %q: %w", latestV, err)
return nil, fmt.Errorf("failed to parse latest version %q: %w", ghResp.TagName, err)
}
isLatest := sv.Compare(*latestSV) >= 0
isLatest := sv.Compare(latestSV) >= 0
// Note: alternatively, we could look through the assets in the GH API response to find a matching asset,
// and use its URL. However, this is not guaranteed to be more robust, and wouldn't use the 'openpolicyagent.org' domain.
+2 -5
View File
@@ -18,6 +18,7 @@ import (
"github.com/open-policy-agent/opa/v1/loader"
"github.com/open-policy-agent/opa/v1/metrics"
"github.com/open-policy-agent/opa/v1/storage"
"github.com/open-policy-agent/opa/v1/util"
)
// InsertAndCompileOptions contains the input for the operation.
@@ -246,13 +247,9 @@ func WalkPaths(paths []string, filter loader.Filter, asBundle bool) (*WalkPathsR
cleanedPath = fp
}
if !strings.HasPrefix(cleanedPath, "/") {
cleanedPath = "/" + cleanedPath
}
result.FileDescriptors = append(result.FileDescriptors, &Descriptor{
Root: path,
Path: cleanedPath,
Path: util.WithPrefix(cleanedPath, "/"),
})
}
}
+194 -197
View File
@@ -14,237 +14,234 @@
// Semantic Versions http://semver.org
// Package semver has been vendored from:
// This file was originally vendored from:
// https://github.com/coreos/go-semver/tree/e214231b295a8ea9479f11b70b35d5acf3556d9b/semver
// A number of the original functions of the package have been removed since
// they are not required for our built-ins.
// There isn't a single line left from the original source today, but being generous about
// attribution won't hurt.
package semver
import (
"bytes"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/open-policy-agent/opa/v1/util"
)
// reMetaIdentifier matches pre-release and metadata identifiers against the spec requirements
var reMetaIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`)
// Version represents a parsed SemVer
type Version struct {
Major int64
Minor int64
Patch int64
PreRelease PreRelease
Metadata string
PreRelease string `json:"PreRelease,omitempty"`
Metadata string `json:"Metadata,omitempty"`
}
// PreRelease represents a pre-release suffix string
type PreRelease string
// Parse constructs new semver Version from version string.
func Parse(version string) (v Version, err error) {
version = strings.TrimPrefix(version, "v")
func splitOff(input *string, delim string) (val string) {
parts := strings.SplitN(*input, delim, 2)
if len(parts) == 2 {
*input = parts[0]
val = parts[1]
version, v.Metadata = cut(version, '+')
if v.Metadata != "" && !reMetaIdentifier.MatchString(v.Metadata) {
return v, fmt.Errorf("invalid metadata identifier: %s", v.Metadata)
}
return val
version, v.PreRelease = cut(version, '-')
if v.PreRelease != "" && !reMetaIdentifier.MatchString(v.PreRelease) {
return v, fmt.Errorf("invalid pre-release identifier: %s", v.PreRelease)
}
if strings.Count(version, ".") != 2 {
return v, fmt.Errorf("%s should contain major, minor, and patch versions", version)
}
major, after := cut(version, '.')
if v.Major, err = strconv.ParseInt(major, 10, 64); err != nil {
return v, err
}
minor, after := cut(after, '.')
if v.Minor, err = strconv.ParseInt(minor, 10, 64); err != nil {
return v, err
}
if v.Patch, err = strconv.ParseInt(after, 10, 64); err != nil {
return v, err
}
return v, nil
}
// NewVersion constructs new SemVers from strings
func NewVersion(version string) (*Version, error) {
v := Version{}
if err := v.Set(version); err != nil {
return nil, err
// MustParse is like Parse but panics if the version string is invalid instead of returning an error.
func MustParse(version string) Version {
v, err := Parse(version)
if err != nil {
panic(err)
}
return &v, nil
return v
}
// Set parses and updates v from the given version string. Implements flag.Value
func (v *Version) Set(version string) error {
metadata := splitOff(&version, "+")
preRelease := PreRelease(splitOff(&version, "-"))
dotParts := strings.SplitN(version, ".", 3)
if len(dotParts) != 3 {
return fmt.Errorf("%s is not in dotted-tri format", version)
}
if err := validateIdentifier(string(preRelease)); err != nil {
return fmt.Errorf("failed to validate pre-release: %v", err)
}
if err := validateIdentifier(metadata); err != nil {
return fmt.Errorf("failed to validate metadata: %v", err)
}
parsed := make([]int64, 3)
for i, v := range dotParts[:3] {
val, err := strconv.ParseInt(v, 10, 64)
parsed[i] = val
if err != nil {
return err
}
}
v.Metadata = metadata
v.PreRelease = preRelease
v.Major = parsed[0]
v.Minor = parsed[1]
v.Patch = parsed[2]
return nil
}
func (v Version) String() string {
var buffer bytes.Buffer
fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch)
if v.PreRelease != "" {
fmt.Fprintf(&buffer, "-%s", v.PreRelease)
}
if v.Metadata != "" {
fmt.Fprintf(&buffer, "+%s", v.Metadata)
}
return buffer.String()
}
// Compare tests if v is less than, equal to, or greater than versionB,
// returning -1, 0, or +1 respectively.
func (v Version) Compare(versionB Version) int {
if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 {
return cmp
}
return preReleaseCompare(v, versionB)
}
// Slice converts the comparable parts of the semver into a slice of integers.
func (v Version) Slice() []int64 {
return []int64{v.Major, v.Minor, v.Patch}
}
// Slice splits the pre-release suffix string
func (p PreRelease) Slice() []string {
preRelease := string(p)
return strings.Split(preRelease, ".")
}
func preReleaseCompare(versionA Version, versionB Version) int {
a := versionA.PreRelease
b := versionB.PreRelease
/* Handle the case where if two versions are otherwise equal it is the
* one without a PreRelease that is greater */
if len(a) == 0 && (len(b) > 0) {
return 1
} else if len(b) == 0 && (len(a) > 0) {
return -1
}
// If there is a prerelease, check and compare each part.
return recursivePreReleaseCompare(a.Slice(), b.Slice())
}
func recursiveCompare(versionA []int64, versionB []int64) int {
if len(versionA) == 0 {
return 0
}
a := versionA[0]
b := versionB[0]
if a > b {
return 1
} else if a < b {
return -1
}
return recursiveCompare(versionA[1:], versionB[1:])
}
func recursivePreReleaseCompare(versionA []string, versionB []string) int {
// A larger set of pre-release fields has a higher precedence than a smaller set,
// if all of the preceding identifiers are equal.
if len(versionA) == 0 {
if len(versionB) > 0 {
return -1
}
return 0
} else if len(versionB) == 0 {
// We're longer than versionB so return 1.
return 1
}
a := versionA[0]
b := versionB[0]
aInt := false
bInt := false
aI, err := strconv.Atoi(versionA[0])
if err == nil {
aInt = true
}
bI, err := strconv.Atoi(versionB[0])
if err == nil {
bInt = true
}
// Numeric identifiers always have lower precedence than non-numeric identifiers.
if aInt && !bInt {
return -1
} else if !aInt && bInt {
return 1
}
// Handle Integer Comparison
if aInt && bInt {
if aI > bI {
return 1
} else if aI < bI {
return -1
}
}
// Handle String Comparison
if a > b {
return 1
} else if a < b {
return -1
}
return recursivePreReleaseCompare(versionA[1:], versionB[1:])
}
// validateIdentifier makes sure the provided identifier satisfies semver spec
func validateIdentifier(id string) error {
if id != "" && !reIdentifier.MatchString(id) {
return fmt.Errorf("%s is not a valid semver identifier", id)
}
return nil
}
// reIdentifier is a regular expression used to check that pre-release and metadata
// identifiers satisfy the spec requirements
var reIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`)
// Compare compares two semver strings.
func Compare(a, b string) int {
aV, err := NewVersion(strings.TrimPrefix(a, "v"))
aV, err := Parse(a)
if err != nil {
return -1
}
bV, err := NewVersion(strings.TrimPrefix(b, "v"))
bV, err := Parse(b)
if err != nil {
return 1
}
return aV.Compare(*bV)
return aV.Compare(bV)
}
// AppendText appends the textual representation of the version to b and returns the extended buffer.
// This method conforms to the encoding.TextAppender interface, and is useful for serializing the Version
// without allocating, provided the caller has pre-allocated sufficient space in b.
func (v Version) AppendText(b []byte) ([]byte, error) {
if b == nil {
b = make([]byte, 0, length(v))
}
b = append(strconv.AppendInt(b, v.Major, 10), '.')
b = append(strconv.AppendInt(b, v.Minor, 10), '.')
b = strconv.AppendInt(b, v.Patch, 10)
if v.PreRelease != "" {
b = append(append(b, '-'), v.PreRelease...)
}
if v.Metadata != "" {
b = append(append(b, '+'), v.Metadata...)
}
return b, nil
}
// String returns the string representation of the version.
func (v Version) String() string {
bs := make([]byte, 0, length(v))
bs, _ = v.AppendText(bs)
return string(bs)
}
// Compare tests if v is less than, equal to, or greater than other, returning -1, 0, or +1 respectively.
// Comparison is based on the SemVer specification (https://semver.org/#spec-item-11).
func (v Version) Compare(other Version) int {
if v.Major > other.Major {
return 1
} else if v.Major < other.Major {
return -1
}
if v.Minor > other.Minor {
return 1
} else if v.Minor < other.Minor {
return -1
}
if v.Patch > other.Patch {
return 1
} else if v.Patch < other.Patch {
return -1
}
if v.PreRelease == other.PreRelease {
return 0
}
// if two versions are otherwise equal it is the one without a pre-release that is greater
if v.PreRelease == "" && other.PreRelease != "" {
return 1
}
if other.PreRelease == "" && v.PreRelease != "" {
return -1
}
a, afterA := cut(v.PreRelease, '.')
b, afterB := cut(other.PreRelease, '.')
for {
if a == "" && b != "" {
return -1
}
if a != "" && b == "" {
return 1
}
aIsInt := isAllDecimals(a)
bIsInt := isAllDecimals(b)
// numeric identifiers have lower precedence than non-numeric
if aIsInt && !bIsInt {
return -1
} else if !aIsInt && bIsInt {
return 1
}
if aIsInt && bIsInt {
aInt, _ := strconv.Atoi(a)
bInt, _ := strconv.Atoi(b)
if aInt > bInt {
return 1
} else if aInt < bInt {
return -1
}
} else {
// string comparison
if a > b {
return 1
} else if a < b {
return -1
}
}
// a larger set of pre-release fields has a higher precedence than a
// smaller set, if all of the preceding identifiers are equal.
if afterA != "" && afterB == "" {
return 1
} else if afterA == "" && afterB != "" {
return -1
}
a, afterA = cut(afterA, '.')
b, afterB = cut(afterB, '.')
}
}
func isAllDecimals(s string) bool {
for _, r := range s {
if r < '0' || r > '9' {
return false
}
}
return s != ""
}
// length allows calculating the length of the version for pre-allocation.
func length(v Version) int {
n := util.NumDigitsInt64(v.Major) + util.NumDigitsInt64(v.Minor) + util.NumDigitsInt64(v.Patch) + 2
if v.PreRelease != "" {
n += len(v.PreRelease) + 1
}
if v.Metadata != "" {
n += len(v.Metadata) + 1
}
return n
}
// cut is a *slightly* faster version of strings.Cut only accepting
// single byte separators, and skipping the boolean return value.
func cut(s string, sep byte) (before, after string) {
if i := strings.IndexByte(s, sep); i >= 0 {
return s[:i], s[i+1:]
}
return s, ""
}