Skip to content

IO.get_env with a "=" in the name reads part of another variable on the C lane and Node #1794

Closed

Description

@orezraey

What you did

bend envq.bend -o envq -o envq.js, then A='B=C' ./envq, A='B=C' node envq.js, A='B=C' bun envq.js

What happened

$ A='B=C' ./envq          # C lane (glibc)
A=Done:B=C
A=B=Done:C
$ A='B=C' node envq.js    # Node
A=Done:B=C
A=B=Done:C
$ A='B=C' bun envq.js     # Bun
A=Done:B=C
A=B=Fail:2

IO.get_env("A=B") names a variable that does not exist, so it should fail with ENOENT, as it does on Bun. On the C lane and on Node it answers Done("C"), the tail of A's value: glibc's getenv compares the name up to its length and then wants a =, so "A=B" matches the entry A=B=C. Node's process.env goes through the same getenv. Bun looks the exact key up in its own object and fails. So the lanes disagree, and a name built from input ("PATH=x", say) can read a variable the program never named. macOS's getenv stops the name at the first = instead, so there get_env("A=B") likely answers all of A's value (not verified here).

This is the = twin of #1449 (a NUL in the name). get_env.c already rejects a NUL with io_nul before calling getenv; a = can never be part of a variable name either (POSIX setenv refuses one with EINVAL).

The file

import Base

law report:
  for tag : String
  for r   : Result<&1, &1, (U32 & String), String>
  IO(Unit)

def report(tag, r):
  match r:
    case Done{value}:
      IO.print(String.append(tag, String.append("=Done:", value)))
    case Fail{error}:
      (code, message) = error
      IO.print(String.append(tag, String.append("=Fail:", U32.show(code))))

law main:
  IO(U32)

def main():
  do IO<U32>:
    a : Result<&1, &1, (U32 & String), String> <- IO.get_env("A")
    x : Unit <- report("A", a)
    b : Result<&1, &1, (U32 & String), String> <- IO.get_env("A=B")
    y : Unit <- report("A=B", b)
    return 0

bend version

Bend 2.0.37 (main at 10256a7)

uname -sm

Linux x86_64

clang --version (the first line)

clang version 23.1.1 (Node v26.10.0, Bun 1.4.3)

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