From 90a55f796203cd2e41c10f480c404280f378b001 Mon Sep 17 00:00:00 2001 From: max Date: Mon, 6 Jul 2026 03:55:03 +0200 Subject: [PATCH] fix(has): return false for negative array indices The sequence branch only checked the upper bound (len > index), so has(-1) returned true even on an empty array. Guard index >= 0. --- pkg/yqlib/operator_has.go | 2 +- pkg/yqlib/operator_has_test.go | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/yqlib/operator_has.go b/pkg/yqlib/operator_has.go index d9fc6320..dd60ecdc 100644 --- a/pkg/yqlib/operator_has.go +++ b/pkg/yqlib/operator_has.go @@ -44,7 +44,7 @@ func hasOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi if errParsingInt != nil { return Context{}, errParsingInt } - candidateHasKey = int64(len(contents)) > number + candidateHasKey = number >= 0 && int64(len(contents)) > number } results.PushBack(createBooleanCandidate(candidate, candidateHasKey)) default: diff --git a/pkg/yqlib/operator_has_test.go b/pkg/yqlib/operator_has_test.go index bed11fcb..47a708af 100644 --- a/pkg/yqlib/operator_has_test.go +++ b/pkg/yqlib/operator_has_test.go @@ -71,6 +71,16 @@ var hasOperatorScenarios = []expressionScenario{ "D0, P[4], (!!bool)::true\n", }, }, + { + skipDoc: true, + description: "Negative array index is never present", + document: "[[1, 2, 3], []]", + expression: `.[] | has(-1)`, + expected: []string{ + "D0, P[0], (!!bool)::false\n", + "D0, P[1], (!!bool)::false\n", + }, + }, } func TestHasOperatorScenarios(t *testing.T) {