Reject --profile / -P within .mlrrc files (#358)

Per maintainer feedback on the PR: profiles are selected on the mlr
command line, not from within a .mlrrc file, so --profile / -P inside a
.mlrrc file is now a parse error -- the same way --prepipe is rejected
there -- rather than being silently ignored.

Adds a unit test, a should-fail regression case, and a docs bullet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
John Kerl 2026-07-14 16:39:29 -04:00
parent 3a0abd3378
commit 0fbba5ce66
10 changed files with 39 additions and 0 deletions

View file

@ -128,6 +128,9 @@ Semantics:
* Since `--profile` selects a section of your `.mlrrc`, it can't be combined with `--norc`, or
with `MLRRC=__none__` in the environment -- that's a fatal error.
* Profiles are selected on the `mlr` command line, not from within a `.mlrrc` file: putting
`--profile` (or `-P`) inside a `.mlrrc` file is a parse error, just as `--prepipe` is.
## Where to put your .mlrrc
If the environment variable `MLRRC` is set:

View file

@ -96,6 +96,9 @@ Semantics:
* Since `--profile` selects a section of your `.mlrrc`, it can't be combined with `--norc`, or
with `MLRRC=__none__` in the environment -- that's a fatal error.
* Profiles are selected on the `mlr` command line, not from within a `.mlrrc` file: putting
`--profile` (or `-P`) inside a `.mlrrc` file is a parse error, just as `--prepipe` is.
## Where to put your .mlrrc
If the environment variable `MLRRC` is set:

View file

@ -231,6 +231,10 @@ func handleMlrrcLine(
} else if args[0] == "--load" || args[0] == "--mload" {
// Don't allow code execution via .mlrrc
return false
} else if args[0] == "--profile" || args[0] == "-P" {
// Profiles are selected on the mlr command line, not from within a
// .mlrrc file
return false
} else if cli.FLAG_TABLE.Parse(args, argc, &argi, options) {
// handled
} else {

View file

@ -196,3 +196,24 @@ func TestMlrrcPrepipeStillDisallowed(t *testing.T) {
t.Fatal("expected error for --prepipe within a profile, got nil")
}
}
func TestMlrrcProfileFlagDisallowedWithinMlrrc(t *testing.T) {
// Profiles are selected on the mlr command line, not from within a
// .mlrrc file: --profile / -P there is a parse error, like --prepipe.
for _, line := range []string{"profile j", "--profile j", "-P j"} {
writeTempMlrrc(t, line+"\n")
options := cli.DefaultOptions()
err := loadMlrrc(options, "")
if err == nil {
t.Errorf("expected parse error for %q within .mlrrc, got nil", line)
} else if !strings.Contains(err.Error(), "parse error") {
t.Errorf("expected parse error for %q within .mlrrc, got: %v", line, err)
}
}
// Inside a selected profile section, too.
writeTempMlrrc(t, "[j]\nprofile p\n")
options := cli.DefaultOptions()
if err := loadMlrrc(options, "j"); err == nil {
t.Fatal("expected parse error for --profile within a profile section, got nil")
}
}

View file

@ -0,0 +1 @@
mlr cat test/input/a.csv

View file

@ -0,0 +1 @@
MLRRC=test/input/mlrrc-with-profile-flag

View file

@ -0,0 +1 @@
mlr: parse error at file "test/input/mlrrc-with-profile-flag" line 2: profile j

View file

@ -0,0 +1,5 @@
icsv
profile j
[j]
ojson