From 12589f297894fbfe80ff6e3bce1a26bf20088b16 Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Sun, 16 Mar 2025 11:57:03 +0100 Subject: [PATCH 1/5] ci: fixed broken codecov coverage upload Signed-off-by: Frederic BIDON --- .github/workflows/go-test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 27273bd..8b7863c 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -52,7 +52,6 @@ jobs: uses: codecov/codecov-action@v5 with: files: './coverage-${{ matrix.os }}.${{ matrix.go_version }}.out' - flags: '${{ matrix.go_version }}' - os: '${{ matrix.os }}' + flags: '${{ matrix.go_version }},${{ matrix.os }}' fail_ci_if_error: false verbose: true From db103690056d17e819e36e5876b6287d39e676c1 Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Mon, 17 Mar 2025 12:28:22 +0100 Subject: [PATCH 2/5] ci: fixed codecov upload Fixed broken test coverage upload to codecov with codecov-action@v5. * fixed tokenless upload (now supported with codecov v5) * fixed flags for codecov * fixed coverage for windows (now use bash instead of powershell) Signed-off-by: Frederic BIDON --- .github/workflows/go-test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 8b7863c..20b3d31 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -37,21 +37,21 @@ jobs: go_version: ['oldstable', 'stable' ] steps: - - name: Run unit tests - uses: actions/setup-go@v5 + - uses: actions/setup-go@v5 with: go-version: '${{ matrix.go_version }}' check-latest: true cache: true - uses: actions/checkout@v4 - - - run: go test -v -race -coverprofile="coverage-${{ matrix.os }}.${{ matrix.go_version }}.out" -covermode=atomic -coverpkg=$(go list)/... ./... + - name: Run unit tests + shell: bash + run: go test -v -race -coverprofile="coverage-${{ matrix.os }}.${{ matrix.go_version }}.out" -covermode=atomic -coverpkg=$(go list)/... ./... - name: Upload coverage to codecov uses: codecov/codecov-action@v5 with: files: './coverage-${{ matrix.os }}.${{ matrix.go_version }}.out' - flags: '${{ matrix.go_version }},${{ matrix.os }}' + flags: '${{ matrix.go_version }}-${{ matrix.os }}' fail_ci_if_error: false verbose: true From 76476c295abf2d3312f527c1ba9e7324e6ac8a26 Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Fri, 28 Mar 2025 15:49:47 +0100 Subject: [PATCH 3/5] ci: updated config for golangci-lint v2 Signed-off-by: Frederic BIDON --- .github/workflows/go-test.yml | 2 +- .golangci.yml | 102 ++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 20b3d31..58326bb 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -21,7 +21,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: version: latest only-new-issues: true diff --git a/.golangci.yml b/.golangci.yml index d2fafb8..5006306 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,56 +1,62 @@ -linters-settings: - gocyclo: - min-complexity: 45 - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 3 - +version: "2" linters: - enable-all: true + default: all disable: - - recvcheck - - unparam - - lll - - gochecknoinits - - gochecknoglobals + - cyclop + - depguard + - errchkjson + - errorlint + - exhaustruct + - forcetypeassert - funlen - - godox + - gochecknoglobals + - gochecknoinits - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage - - nlreturn - - errorlint - - nestif - godot - - gofumpt + - godox + - gosmopolitan + - inamedparam + - ireturn + - lll + - musttag + - nestif + - nlreturn + - nonamedreturns - paralleltest - - tparallel + - testpackage - thelper - - exhaustruct + - tparallel + - unparam - varnamelen - - gci - - depguard - - errchkjson - - inamedparam - - nonamedreturns - - musttag - - ireturn - - forcetypeassert - - cyclop - # deprecated linters - #- deadcode - #- interfacer - #- scopelint - #- varcheck - #- structcheck - #- golint - #- nosnakecase - #- maligned - #- goerr113 - #- ifshort - #- gomnd - #- exhaustivestruct + - whitespace + - wrapcheck + - wsl + settings: + dupl: + threshold: 200 + goconst: + min-len: 2 + min-occurrences: 3 + gocyclo: + min-complexity: 45 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ From f485c21286d4b74f6da8b875373ad99d6eb3828c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 02:08:10 +0000 Subject: [PATCH 4/5] Bump golangci/golangci-lint-action in the development-dependencies group Bumps the development-dependencies group with 1 update: [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action). Updates `golangci/golangci-lint-action` from 7 to 8 - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v7...v8) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major dependency-group: development-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/go-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 58326bb..7165e0f 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -21,7 +21,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v7 + uses: golangci/golangci-lint-action@v8 with: version: latest only-new-issues: true From 22474992b4b450fea1211b4cb5c1166758fb33e2 Mon Sep 17 00:00:00 2001 From: Matthew F Leader Date: Tue, 5 Aug 2025 16:35:37 -0400 Subject: [PATCH 5/5] fix: prevent panic on nil intermediate values during Set operations Add nil checks in setSingleImpl() and traversal loop to handle nil intermediate values gracefully. Per RFC 6901 Section 7, implementations must raise error conditions for unresolvable paths instead of panicking. - Add isNil() check before reflection operations in setSingleImpl() - Add nil validation in set() method traversal loop - Return descriptive errors: "cannot set field X on nil value" - Add comprehensive test cases for nil traversal scenarios Fixes panic: "reflect: call of reflect.Value.Type on zero Value" when traversing JSON paths containing nil intermediate values. Signed-off-by: Matthew F Leader --- pointer.go | 10 ++++++ pointer_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/pointer.go b/pointer.go index a08cd68..6136210 100644 --- a/pointer.go +++ b/pointer.go @@ -179,6 +179,11 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameProvider) error { rValue := reflect.Indirect(reflect.ValueOf(node)) + // Check for nil to prevent panic when calling rValue.Type() + if isNil(node) { + return fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) + } + if ns, ok := node.(JSONSetable); ok { // pointer impl return ns.JSONSet(decodedToken, data) } @@ -285,6 +290,11 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error { return setSingleImpl(node, data, decodedToken, nameProvider) } + // Check for nil during traversal + if isNil(node) { + return fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer) + } + rValue := reflect.Indirect(reflect.ValueOf(node)) kind := rValue.Kind() diff --git a/pointer_test.go b/pointer_test.go index 8cac301..b1b382b 100644 --- a/pointer_test.go +++ b/pointer_test.go @@ -644,6 +644,94 @@ func TestSetNode(t *testing.T) { assert.Equal(t, 999, setDoc.Coll.Items[0].C) }) }) + + t.Run("with nil traversal panic", func(t *testing.T) { + // This test exposes the panic that occurs when trying to set a value + // through a path that contains nil intermediate values + data := map[string]any{ + "level1": map[string]any{ + "level2": map[string]any{ + "level3": nil, // This nil causes the panic + }, + }, + } + + ptr, err := New("/level1/level2/level3/value") + require.NoError(t, err) + + // This should return an error, not panic + _, err = ptr.Set(data, "test-value") + + // The library should handle this gracefully and return an error + // instead of panicking + require.Error(t, err, "Setting value through nil intermediate path should return an error, not panic") + }) + + t.Run("with direct nil map value", func(t *testing.T) { + // Simpler test case that directly tests nil traversal + data := map[string]any{ + "container": nil, + } + + ptr, err := New("/container/nested/value") + require.NoError(t, err) + + // Attempting to traverse through nil should return an error, not panic + _, err = ptr.Set(data, "test") + require.Error(t, err, "Cannot traverse through nil intermediate values") + }) + + t.Run("with nil in nested structure", func(t *testing.T) { + // Test case with multiple nil values in nested structure + data := map[string]any{ + "config": map[string]any{ + "settings": nil, + }, + "data": map[string]any{ + "nested": map[string]any{ + "properties": map[string]any{ + "attributes": nil, // Nil intermediate value + }, + }, + }, + } + + ptr, err := New("/data/nested/properties/attributes/name") + require.NoError(t, err) + + // Should return error, not panic + _, err = ptr.Set(data, "test-name") + require.Error(t, err, "Setting through nil intermediate path should return error") + }) + + t.Run("with path creation through nil intermediate", func(t *testing.T) { + // Test case that simulates path creation functions encountering nil + // This happens when tools try to create missing paths but encounter nil intermediate values + data := map[string]any{ + "spec": map[string]any{ + "template": nil, // This blocks path creation attempts + }, + } + + // Attempting to create a path like /spec/template/metadata/labels should fail gracefully + ptr, err := New("/spec/template/metadata") + require.NoError(t, err) + + // Should return error when trying to set on nil intermediate during path creation + _, err = ptr.Set(data, map[string]any{"labels": map[string]any{}}) + require.Error(t, err, "Setting on nil intermediate during path creation should return error") + }) + + t.Run("with SetForToken on nil", func(t *testing.T) { + // Test the single-level SetForToken function with nil + data := map[string]any{ + "container": nil, + } + + // Should handle nil gracefully at single token level + _, err := SetForToken(data["container"], "nested", "value") + require.Error(t, err, "SetForToken on nil should return error, not panic") + }) } func TestOffset(t *testing.T) {