mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-17 15:20:11 +02:00
fix(gbrain-lib): pin LC_ALL=C in varname validator (macOS locale guard)
In many macOS shells the default locale (e.g. en_US.UTF-8) makes bash glob brackets like `[A-Z]` match lowercase letters too, so the existing `case "$name" in [A-Z_][A-Z0-9_]*)` branch lets names like `lower-case` through validation. The function then trips `printf -v "$varname"` and `export "$varname"` with `not a valid identifier` errors that surface mid-prompt, which is exactly what the validator was supposed to prevent. Pinning `LC_ALL=C` inside the function gives ASCII-only bracket semantics on both macOS and Linux, matching the documented `[A-Z_][A-Z0-9_]*` contract. Declared `local` so it doesn't leak to the calling shell — `gstack-gbrain-lib.sh` is documented as a sourced helper, so a bare assignment would mutate the caller's locale for the rest of the process (silently affecting downstream `sort`, `tr`, locale-aware globs in the same shell, etc.). The existing regression test `test/gbrain-lib-verify.test.ts:'rejects invalid var names'` already covers the macOS repro shape (passes `lower-case` and expects the validator to reject + emit `invalid var name`). On Linux CI the test silently passed because `LC_ALL=C` is the typical default; on macOS dev boxes it fails. Verified: - `bun test test/gbrain-lib-verify.test.ts`: 22 pass, 0 fail (on macOS). - `_gstack_gbrain_validate_varname lower-case; echo $?` → 2. - `_gstack_gbrain_validate_varname FOO_BAR; echo $?` → 0. - Caller's LC_ALL preserved across calls (confirmed via sourced bash).
This commit is contained in:
@@ -27,8 +27,22 @@
|
||||
# restore), D16 (pooler URL paste hygiene with redacted preview).
|
||||
|
||||
# _gstack_gbrain_validate_varname <name> — returns 0 if usable, 2 otherwise.
|
||||
# `local LC_ALL=C` is load-bearing twice over:
|
||||
# 1. In many macOS shells the default locale (e.g. en_US.UTF-8) makes `case`
|
||||
# glob brackets like `[A-Z]` match lowercase letters too. Without the
|
||||
# LC_ALL=C pin, names like `lower-case` pass validation and then trip
|
||||
# `printf -v "$varname"` and `export "$varname"` with "not a valid
|
||||
# identifier" errors the caller can't easily distinguish from other
|
||||
# failures.
|
||||
# 2. `local` is required because this file is documented as a sourced helper
|
||||
# (see header), so a bare `LC_ALL=C` would mutate the caller's locale for
|
||||
# the rest of the process — silently affecting downstream `sort`, `tr`,
|
||||
# and any locale-aware glob in the same shell.
|
||||
# Together they give ASCII-only bracket semantics on both macOS and Linux
|
||||
# (matching the documented `[A-Z_][A-Z0-9_]*` contract) without leaking.
|
||||
_gstack_gbrain_validate_varname() {
|
||||
local name="$1"
|
||||
local LC_ALL=C
|
||||
case "$name" in
|
||||
[A-Z_][A-Z0-9_]*) return 0 ;;
|
||||
*) return 2 ;;
|
||||
|
||||
Reference in New Issue
Block a user