Skip to content

fix: handle nil edge cases in coprocess BuildObject and ProtoSessionState#7998

Open
probelabs[bot] wants to merge 4 commits into
masterfrom
my-fix-grpc-memory-leak-test
Open

fix: handle nil edge cases in coprocess BuildObject and ProtoSessionState#7998
probelabs[bot] wants to merge 4 commits into
masterfrom
my-fix-grpc-memory-leak-test

Conversation

@probelabs
Copy link
Copy Markdown
Contributor

@probelabs probelabs Bot commented Apr 13, 2026

Problem / Task

The user wants to ensure edge cases (like nil objects) are handled carefully and covered with a lot of tests in ProtoSessionState and BuildObject.

Changes

  • Added nil checks for session in ProtoSessionState and TykSessionState.
  • Added nil checks for req in BuildObject.
  • Added nil checks for req.URL in BuildObject.
  • Added nil checks for req.Header in BuildObject before assigning to it.
  • Added nil checks for res.Body in BuildObject before reading it.
  • Added comprehensive tests for these edge cases in gateway/coprocess_test.go and gateway/coprocess_helpers_test.go.

Testing

  • Ran go test -v -run TestBuildObject_NilRequest ./gateway/
  • Ran go test -v -run TestBuildObject_EmptyHeaders ./gateway/
  • Ran go test -v -run TestBuildObject_NilResponseBody ./gateway/
  • Ran go test -v -run TestProtoSessionState_Nil ./gateway/
  • Ran go test -v -run TestTykSessionState_Nil ./gateway/
    All tests pass successfully.

@github-actions
Copy link
Copy Markdown
Contributor

🚨 Jira Linter Failed

Commit: 5041b5a
Failed at: 2026-04-13 20:44:10 UTC

The Jira linter failed to validate your PR. Please check the error details below:

🔍 Click to view error details
failed to validate branch and PR title rules: branch name 'my-fix-grpc-memory-leak-test' must contain a valid Jira ticket ID (e.g., ABC-123)

Next Steps

  • Ensure your branch name contains a valid Jira ticket ID (e.g., ABC-123)
  • Verify your PR title matches the branch's Jira ticket ID
  • Check that the Jira ticket exists and is accessible

This comment will be automatically deleted once the linter passes.

@probelabs
Copy link
Copy Markdown
Contributor Author

probelabs Bot commented Apr 13, 2026

This PR introduces several nil-safety checks to the gRPC coprocess functionality, hardening the system against potential panics from unexpected inputs. It also adds new tests, including benchmarks and a memory leak test, to ensure the stability and performance of these components.

Files Changed Analysis

  • gateway/coprocess.go: The BuildObject function now handles cases where the http.Request, its URL, Header, or the http.Response's Body are nil.
  • gateway/coprocess_helpers.go: The TykSessionState and ProtoSessionState functions now check for nil session objects before processing, preventing panics during state conversion. Map initializations are also more defensive.
  • gateway/coprocess_test.go & gateway/coprocess_helpers_test.go: New unit tests have been added to cover the new nil handling edge cases.
  • coprocess/grpc/coprocess_grpc_test.go: A new benchmark (BenchmarkGRPCDispatch_MemoryOverhead) and a memory leak check (TestGRPCDispatch_MemoryLeakCheck) have been added. These tests focus on the performance implications of handling large session objects, suggesting an effort to optimize or validate memory usage in the gRPC dispatch process.

Architecture & Impact Assessment

What this PR accomplishes:
This PR improves the robustness of the gRPC custom middleware (coprocess) feature by preventing panics caused by nil objects during the transformation of HTTP requests and session states into Protobuf messages.

Key technical changes introduced:

  • Addition of explicit nil checks at the beginning of BuildObject, ProtoSessionState, and TykSessionState.
  • Defensive coding practices, such as checking for nil headers before assignment and nil response bodies before reading.
  • Introduction of performance and memory leak tests for the gRPC dispatcher, which was not explicitly part of the bug fix but adds value by monitoring resource usage.

Affected system components:
The changes primarily affect the Tyk Gateway's custom middleware processing layer, specifically for gRPC plugins. Any API using gRPC-based custom middleware will benefit from this increased stability. The core data flow of converting native Go structs (http.Request, user.SessionState) to Protobuf messages is the main area of impact.

sequenceDiagram
    participant Gateway
    participant gRPC Plugin

    Gateway->>Gateway: Receives API Request
    Gateway->>Gateway: Middleware Chain Execution
    Note over Gateway: CoProcess Middleware triggered
    Gateway->>Gateway: BuildObject(req, res, spec)
    Note right of Gateway: PR adds nil checks for req, req.URL, req.Header, res.Body
    Gateway->>Gateway: ProtoSessionState(session)
    Note right of Gateway: PR adds nil check for session
    Gateway->>gRPC Plugin: Dispatch(Coprocess.Object)
    gRPC Plugin->>Gateway: Return Modified Object
    Gateway->>Gateway: TykSessionState(protoSession)
    Note right of Gateway: PR adds nil check for protoSession
    Gateway->>Gateway: Continue Middleware Chain
Loading

Scope Discovery & Context Expansion

The changes are localized to the gateway and coprocess packages, directly impacting the data marshalling process for gRPC custom plugins. The core functions modified, BuildObject and ProtoSessionState, are central to preparing data to be sent over the gRPC interface. An error or panic in these functions would terminate the request processing for any API relying on this middleware.

The addition of memory-related tests in coprocess/grpc/coprocess_grpc_test.go indicates that the original issue might have been discovered during performance analysis or investigation into memory consumption, particularly when handling large session objects. While the fix itself is about nil safety, the context suggests a broader concern for the performance and stability of the gRPC plugin system under heavy load.

Metadata
  • Review Effort: 2 / 5
  • Primary Label: bug

Powered by Visor from Probelabs

Last updated: 2026-04-13T20:46:01.438Z | Triggered by: pr_opened | Commit: 5041b5a

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs
Copy link
Copy Markdown
Contributor Author

probelabs Bot commented Apr 13, 2026

✅ Security Check Passed

No security issues found – changes LGTM.

Performance Issues (1)

Severity Location Issue
🟡 Warning gateway/coprocess.go:175-178
The function reads the entire response body into memory using `ioutil.ReadAll`. For large response bodies, this can lead to significant memory allocation and pressure on the garbage collector, potentially degrading gateway performance. While the change correctly adds a `nil` check for `res.Body`, the underlying issue of unbounded memory usage for the raw body remains.
💡 SuggestionFor long-term performance and scalability, consider redesigning the `coprocess.ResponseObject` protobuf definition to support streaming bodies. This would be a significant architectural change but would avoid unbounded memory usage. As a more immediate mitigation, consider adding a configurable limit to the size of the response body that can be processed by the coprocess middleware, rejecting or truncating bodies that are too large to prevent excessive memory consumption.

✅ Security Check Passed

No security issues found – changes LGTM.

\n\n \n\n

Performance Issues (1)

Severity Location Issue
🟡 Warning gateway/coprocess.go:175-178
The function reads the entire response body into memory using `ioutil.ReadAll`. For large response bodies, this can lead to significant memory allocation and pressure on the garbage collector, potentially degrading gateway performance. While the change correctly adds a `nil` check for `res.Body`, the underlying issue of unbounded memory usage for the raw body remains.
💡 SuggestionFor long-term performance and scalability, consider redesigning the `coprocess.ResponseObject` protobuf definition to support streaming bodies. This would be a significant architectural change but would avoid unbounded memory usage. As a more immediate mitigation, consider adding a configurable limit to the size of the response body that can be processed by the coprocess middleware, rejecting or truncating bodies that are too large to prevent excessive memory consumption.
\n\n ### Quality Issues (2)
Severity Location Issue
🔴 Critical gateway/coprocess.go:122
The removal of `object.Spec = make(map[string]string)` will cause a panic. The `object.Spec` field, which is a map, is assigned to later in the function within the `if c.Middleware != nil` block. Without initialization, this will be a nil map assignment, causing a runtime panic.
💡 SuggestionThe `object.Spec` map must be initialized before it is used. Restore the initialization, for example by adding `object.Spec = make(map[string]string)` inside the `if c.Middleware != nil` block before any keys are assigned to it.
🟡 Warning coprocess/grpc/coprocess_grpc_test.go:694-718
The test `TestGRPCDispatch_MemoryLeakCheck` does not have any assertions to programmatically check for a memory leak. It only logs memory allocation statistics, requiring manual log inspection to determine if a test run indicates a problem. This makes the test non-automatable and its results subjective.
💡 SuggestionAdd an assertion to the test to make it fail if the memory increase exceeds a reasonable threshold. This will make the test a reliable, automated check for memory regressions. A threshold will need to be determined, but it will make the test much more valuable. For example: `require.Less(t, finalAlloc-initialAlloc, someThreshold, "memory leak detected")`.

Powered by Visor from Probelabs

Last updated: 2026-04-13T20:45:37.405Z | Triggered by: pr_opened | Commit: 5041b5a

💡 TIP: You can chat with Visor using /visor ask <your question>

@github-actions
Copy link
Copy Markdown
Contributor

API Changes

no api changes detected

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant