Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func (v *Checker) identifierNode(node *ast.IdentifierNode) Nature {
return v.varScopes[i].nature
}
}
if node.Value == "$env" {
if node.Value == "$env" && !v.config.Disabled["$env"] {
return Nature{}
}

Expand Down Expand Up @@ -514,7 +514,7 @@ func (v *Checker) chainNode(node *ast.ChainNode) Nature {

func (v *Checker) memberNode(node *ast.MemberNode) Nature {
// $env variable
if an, ok := node.Node.(*ast.IdentifierNode); ok && an.Value == "$env" {
if an, ok := node.Node.(*ast.IdentifierNode); ok && an.Value == "$env" && !v.config.Disabled["$env"] {
if name, ok := node.Property.(*ast.StringNode); ok {
strict := v.config.Strict
if node.Optional {
Expand Down Expand Up @@ -652,7 +652,7 @@ func (v *Checker) callNode(node *ast.CallNode) Nature {
}

// $env is not callable.
if id, ok := node.Callee.(*ast.IdentifierNode); ok && id.Value == "$env" {
if id, ok := node.Callee.(*ast.IdentifierNode); ok && id.Value == "$env" && !v.config.Disabled["$env"] {
return v.error(node, "%s is not callable", v.config.Env.String())
}

Expand Down Expand Up @@ -965,7 +965,7 @@ func (v *Checker) checkBuiltinGet(node *ast.BuiltinNode) Nature {
prop := v.visit(node.Arguments[1])
prop = prop.Deref(&v.config.NtCache)

if id, ok := node.Arguments[0].(*ast.IdentifierNode); ok && id.Value == "$env" {
if id, ok := node.Arguments[0].(*ast.IdentifierNode); ok && id.Value == "$env" && !v.config.Disabled["$env"] {
if s, ok := node.Arguments[1].(*ast.StringNode); ok {
if nt, ok := v.config.Env.Get(&v.config.NtCache, s.Value); ok {
return nt
Expand Down
2 changes: 1 addition & 1 deletion compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func (c *compiler) IdentifierNode(node *ast.IdentifierNode) {
c.emit(OpLoadVar, index)
return
}
if node.Value == "$env" {
if node.Value == "$env" && (c.config == nil || !c.config.Disabled["$env"]) {
c.emit(OpLoadEnv)
return
}
Expand Down
69 changes: 69 additions & 0 deletions test/issues/710/issue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package issue_test

import (
"testing"

"github.com/expr-lang/expr"
"github.com/expr-lang/expr/internal/testify/assert"
"github.com/expr-lang/expr/internal/testify/require"
)

func TestIssue710_disable_env_builtin(t *testing.T) {
env := map[string]any{
"foo": 42,
}

t.Run("$env disabled in strict mode", func(t *testing.T) {
_, err := expr.Compile(`$env`, expr.Env(env), expr.DisableBuiltin("$env"))
require.Error(t, err)
assert.Contains(t, err.Error(), "unknown name $env")
})

t.Run("$env.field disabled in strict mode", func(t *testing.T) {
_, err := expr.Compile(`$env.foo`, expr.Env(env), expr.DisableBuiltin("$env"))
require.Error(t, err)
assert.Contains(t, err.Error(), "unknown name $env")
})

t.Run("get($env, field) disabled in strict mode", func(t *testing.T) {
_, err := expr.Compile(`get($env, "foo")`, expr.Env(env), expr.DisableBuiltin("$env"))
require.Error(t, err)
assert.Contains(t, err.Error(), "unknown name $env")
})

t.Run("$env() disabled in strict mode", func(t *testing.T) {
_, err := expr.Compile(`$env()`, expr.Env(env), expr.DisableBuiltin("$env"))
require.Error(t, err)
assert.Contains(t, err.Error(), "unknown name $env")
})

t.Run("$env disabled without strict mode", func(t *testing.T) {
// Without expr.Env(), the checker runs in non-strict mode.
// Disabled $env falls through to normal identifier resolution,
// which returns nil for unknown names in non-strict mode.
program, err := expr.Compile(`$env`, expr.DisableBuiltin("$env"))
require.NoError(t, err)

out, err := expr.Run(program, map[string]any{})
require.NoError(t, err)
assert.Nil(t, out)
})

t.Run("$env enabled by default", func(t *testing.T) {
program, err := expr.Compile(`$env.foo`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, 42, out)
})

t.Run("$env standalone enabled by default", func(t *testing.T) {
program, err := expr.Compile(`$env`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, env, out)
})
}
Loading