Skip to content

🐛 bug: apply limits to msgp serialization#4065

Merged
ReneWerner87 merged 2 commits intomainfrom
add-msgp-limits-to-generated-sources
Feb 9, 2026
Merged

🐛 bug: apply limits to msgp serialization#4065
ReneWerner87 merged 2 commits intomainfrom
add-msgp-limits-to-generated-sources

Conversation

@gaby
Copy link
Member

@gaby gaby commented Feb 8, 2026

Motivation

  • Prevent msgp limit tags from unnecessarily constraining cache and idempotency payloads whose sizes are governed by storage policy rather than serializer limits.
  • Keep per-field caps for headers and other small fields to protect against unbounded memory usage during deserialization.
  • Regenerate msgp outputs so runtime decoding enforces the intended limits and fails fast on malicious inputs.

Description

  • Removed msgp body size caps for cache item.body and idempotency response.Body, deferring body-size enforcement to storage policy while retaining field-level limits for other fields.
  • Increased header/map array caps (for example Headers and header counts) to 1024 where appropriate and tightened per-field byte limits (for ctype, cencoding, cacheControl, expires, etag, and header key/value sizes).
  • Regenerated the msgp-generated files (*_msgp.go) so they include size-constant checks and use ReadBytesLimit/ReadBytesHeader/ReadBytes variants and explicit msgp.ErrLimitExceeded checks.
  • Added //nolint:revive annotations where msgp tags on unexported fields require linter exceptions.

@gaby gaby requested a review from a team as a code owner February 8, 2026 07:40
Copilot AI review requested due to automatic review settings February 8, 2026 07:40
@gaby gaby requested review from ReneWerner87, efectn and sixcolors and removed request for Copilot February 8, 2026 07:40
@ReneWerner87 ReneWerner87 added the v3 label Feb 8, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Walkthrough

This PR adds MessagePack serialization size limit enforcement across middleware components (cache, idempotency, session, redirect) by introducing per-field msgp limits, explicit bound checks during encode/decode, and metadata fields to track cache properties.

Changes

Cohort / File(s) Summary
Cache Manager Limits & Metadata
middleware/cache/manager.go, middleware/cache/manager_msgp.go
Adds msgp per-field limits (key 512, value 16384, headers 1024) and metadata fields (exp, ttl, forceRevalidate, revalidate, shareable, private) to item type. Replaces direct ReadBytes with ReadBytesLimit across multiple fields and enforces nested structure boundary checks in DecodeMsg/UnmarshalMsg paths.
Idempotency Response Limits
middleware/idempotency/response.go, middleware/idempotency/response_msgp.go
Updates Headers field with msgp limit tag (1024 entries) and adds documentation comments. Enforces limit checks in DecodeMsg/UnmarshalMsg for both top-level and nested header array sizes.
Session Data Documentation
middleware/session/data.go
Adds module-level and inline comments documenting that session state should remain bounded for storage compatibility.
Redirect Type Limits
redirect.go, redirect_msgp.go
Introduces MSGP directive with array (256) and map (32) limits for redirectionMsg type. Adds size limit constants and enforces maximum entries during encode/decode, replacing explicit error returns with named return patterns.
Redirect Benchmark Refactoring
redirect_msgp_test.go
Converts all Benchmark loops from b.Loop() to conventional for-i-less-b.N loops with b.ResetTimer() for timing accuracy.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • sixcolors
  • efectn
  • ReneWerner87

Poem

🐰 Bounded payloads hop through the wire,
Limits set high, but never too dire,
MessagePack guards keep the sizes so tight,
Headers and caches, all snug and just right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete and does not follow the provided template structure. Required sections like 'Changes introduced' (with sub-items), 'Type of change' checklist, and verification checklist are absent. Complete the PR description by adding the missing template sections, including 'Changes introduced' checklist items, 'Type of change' selection, and the verification checklist to ensure full compliance with repository standards.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title directly relates to the main change: applying limits to msgp serialization across multiple middleware modules.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-msgp-limits-to-generated-sources

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ReneWerner87 ReneWerner87 added this to v3 Feb 8, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Feb 8, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gaby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the msgp serialization limits across various middleware components, including cache, idempotency, session, and redirect functionalities. The primary goal is to optimize memory usage and enhance security by ensuring that large payloads are governed by their respective storage policies, while smaller, predictable fields have appropriate, tighter limits. The changes involve updating msgp directives in Go source files and regenerating the corresponding serialization code to incorporate these new constraints and robust error handling for limit exceedances.

Highlights

  • Relaxed Body Limits: The msgp serialization limits for cache item bodies and idempotency response bodies have been relaxed. Their size enforcement is now deferred to storage policies, rather than being constrained by serializer limits.
  • Adjusted Field Caps: Per-field caps for headers and other smaller fields have been adjusted. Header counts and map array caps were increased to 1024 or 2048 where appropriate, while byte limits for specific header fields like ctype, cencoding, cacheControl, expires, and etag were tightened to prevent unbounded memory usage during deserialization.
  • Regenerated msgp Outputs: All msgp-generated files (*_msgp.go) have been regenerated. This ensures that runtime decoding enforces the newly defined limits and fails fast on malicious inputs by utilizing ReadBytesLimit/ReadBytesHeader/ReadBytes variants and explicit msgp.ErrLimitExceeded checks.
  • Linter Exceptions: //nolint:revive annotations were added to unexported fields that require msgp tags for limit enforcement, addressing linter exceptions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • middleware/cache/manager.go
    • Added msgp:limit directives for arrays and maps to the item struct.
    • Introduced //nolint:revive for unexported fields with msgp tags.
    • Applied specific msg:,limit tags to fields within item and cachedHeader structs, adjusting byte limits for various header-related fields and removing the limit for the body field.
  • middleware/cache/manager_msgp.go
    • Added zc13959a0limitArrays and zc13959a0limitMaps constants for deserialization limits.
    • Modified DecodeMsg and UnmarshalMsg methods for cachedHeader and item to include checks against new map and array limits.
    • Updated DecodeMsg and UnmarshalMsg for byte slice fields to use ReadBytesLimit or ReadBytesHeader with specific byte limits and added msgp.ErrLimitExceeded checks.
    • Ensured nil byte slices are initialized after ReadBytesLimit calls.
    • Added ErrLimitExceeded checks for MarshalMsg when headers array length exceeds limits.
  • middleware/idempotency/response.go
    • Added msgp:limit directives for arrays and maps to the response struct.
    • Applied a msg:,limit=1024 tag to the Headers map field.
    • Removed the limit for the Body field.
  • middleware/idempotency/response_msgp.go
    • Added zd44e2ac8limitArrays and zd44e2ac8limitMaps constants for deserialization limits.
    • Modified DecodeMsg and UnmarshalMsg methods for response to include checks against new map and array limits.
    • Added ErrLimitExceeded checks for Headers map and its string array values in DecodeMsg, EncodeMsg, MarshalMsg, and UnmarshalMsg.
    • Updated DecodeMsg and UnmarshalMsg for the Body field to use ReadBytesLimit with the new array limit, and added nil byte slice initialization.
  • middleware/session/data.go
    • Added msgp:limit directives for arrays and maps to the data struct.
    • Applied a msg:,limit=2048 tag to the Data map field.
  • middleware/session/data_msgp.go
    • Added z1bff3a47limitArrays and z1bff3a47limitMaps constants for deserialization limits.
  • redirect.go
    • Added msgp:limit directives for arrays and maps to the redirectionMsg struct.
  • redirect_msgp.go
    • Added zc920acdalimitArrays and zc920acdalimitMaps constants for deserialization limits.
    • Modified DecodeMsg, EncodeMsg, MarshalMsg, and UnmarshalMsg methods for redirectionMsg and redirectionMsgs to include checks against new map and array limits, returning msgp.ErrLimitExceeded on overflow.
    • Corrected return statements in generated msgp methods to simply return on error.
  • redirect_msgp_test.go
    • Added b.ResetTimer() to all benchmark functions for accurate performance measurement.
Activity
  • The author gaby initiated this pull request to adjust msgp serialization limits.
  • The author executed make audit, make generate, make betteralign, make modernize, make format, and make lint to validate the changes and regenerate necessary code.
  • During make audit, govulncheck reported existing Go standard-library advisories, which were noted as unrelated to the changes in this PR.
  • All 2639 tests passed successfully, with 1 skipped, indicating no regressions from the changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.05%. Comparing base (8b5d061) to head (d3ccc67).
⚠️ Report is 31 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4065      +/-   ##
==========================================
- Coverage   91.10%   91.05%   -0.06%     
==========================================
  Files         119      119              
  Lines       11203    11207       +4     
==========================================
- Hits        10207    10205       -2     
- Misses        630      635       +5     
- Partials      366      367       +1     
Flag Coverage Δ
unittests 91.05% <ø> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gaby gaby changed the title 🧹 chore: relax msgp body limits for cache and idempotency, adjust field caps 🐛 bug: Apply limits to msgp serialization Feb 8, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to improve security by adding and adjusting msgp serialization limits. The changes are generally positive, especially the move to relax limits on large body fields while tightening them on smaller metadata fields. However, the process of regenerating the msgp code appears to have introduced several significant inconsistencies, likely due to bugs in the generator tool. These include mismatched size limits between encoding and decoding paths for the same fields, and a case where a limit is applied to a field within a struct that is ignored by msgp, rendering the limit ineffective. I've left specific comments on these issues. Addressing them is crucial to ensure the serialization is as robust and secure as intended. The updates to the benchmark tests are a welcome improvement.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
middleware/cache/manager_msgp.go (1)

406-414: ⚠️ Potential issue | 🟠 Major

Limit check occurs after WriteArrayHeader — writer left in corrupt state on violation.

en.WriteArrayHeader at Line 406 has already flushed the array header to the stream before the limit is validated at Line 411. If the limit is exceeded, the writer contains a partial/malformed message (array header promising N elements with none following).

The check should happen before the write:

Proposed fix
+	if uint32(len(z.headers)) > zc13959a0limitArrays {
+		err = msgp.ErrLimitExceeded
+		return
+	}
 	err = en.WriteArrayHeader(uint32(len(z.headers)))
 	if err != nil {
 		err = msgp.WrapError(err, "headers")
 		return
 	}
-	if uint32(len(z.headers)) > zc13959a0limitArrays {
-		err = msgp.ErrLimitExceeded
-		return
-	}

Since this is generated code, the fix likely needs to be applied to the msgp generator directives or templates, then regenerated.

middleware/idempotency/response_msgp.go (1)

120-128: ⚠️ Potential issue | 🟠 Major

Same write-before-check pattern as in the cache file — EncodeMsg writes headers before validating limits.

At Line 120, WriteMapHeader flushes the Headers map header to the stream. The limit check at Line 125 fires after the write. Similarly, WriteArrayHeader at Line 135 precedes its limit check at Line 140. On limit violation, the writer is left with a partial/corrupt message.

Proposed fix — move checks before writes
+	if uint32(len(z.Headers)) > zd44e2ac8limitMaps {
+		err = msgp.ErrLimitExceeded
+		return
+	}
 	err = en.WriteMapHeader(uint32(len(z.Headers)))
 	if err != nil {
 		err = msgp.WrapError(err, "Headers")
 		return
 	}
-	if uint32(len(z.Headers)) > zd44e2ac8limitMaps {
-		err = msgp.ErrLimitExceeded
-		return
-	}

And similarly for the inner array header:

+		if uint32(len(za0002)) > zd44e2ac8limitArrays {
+			err = msgp.ErrLimitExceeded
+			return
+		}
 		err = en.WriteArrayHeader(uint32(len(za0002)))
 		if err != nil {
 			err = msgp.WrapError(err, "Headers", za0001)
 			return
 		}
-		if uint32(len(za0002)) > zd44e2ac8limitArrays {
-			err = msgp.ErrLimitExceeded
-			return
-		}

As with the cache file, this needs to be fixed in the generator since these are generated files.

Also applies to: 135-143

🤖 Fix all issues with AI agents
In `@middleware/cache/manager_msgp.go`:
- Around line 607-610: In MarshalMsg, the code calls msgp.AppendArrayHeader(o,
uint32(len(z.headers))) before checking the array-size limit
zc13959a0limitArrays, which writes into the buffer (wasting Require's
allocation) and is inconsistent with decode-path checks; move the limit check to
before the AppendArrayHeader call (i.e., validate uint32(len(z.headers)) <=
zc13959a0limitArrays and return msgp.ErrLimitExceeded if not) and only then call
msgp.AppendArrayHeader to append the header; apply the same change pattern
wherever AppendArrayHeader is used with similar generated limit constants.

In `@middleware/idempotency/response_msgp.go`:
- Around line 181-190: In MarshalMsg, the code appends map/array headers before
checking limits; move the checks so that you validate len(z.Headers) against
zd44e2ac8limitMaps and len(za0002) against zd44e2ac8limitArrays before calling
msgp.AppendMapHeader and msgp.AppendArrayHeader respectively (i.e., check limits
first, return msgp.ErrLimitExceeded if exceeded, then append headers and
continue iterating over z.Headers in MarshalMsg).
- Around line 9-13: The generated msgp array limit (zd44e2ac8limitArrays =
16384) enforces a 16KB cap that contradicts the Body comment and the cache
middleware; either remove the msgp limit or align it with cache
(zd44e2ac8limitArrays = 65535) so storage-policy bounds are respected. Locate
the auto-generated msgp limit constant (zd44e2ac8limitArrays) and the
corresponding msgp directive in response_msgp.go and either delete the limit
directive/constant entirely (so msgp doesn't enforce a fixed ReadBytesLimit) or
change the constant value to 65535 to match the cache middleware, then
regenerate or adjust the generated code so the Body field remains bounded only
by storage policy.

In `@redirect_msgp.go`:
- Around line 229-247: The EncodeMsg function writes the array header before
checking the slice-length limit (zc920acdalimitArrays), which can leave the
writer in a partial/invalid state on error; move the limit check (uint32(len(z))
> zc920acdalimitArrays) to before the call to en.WriteArrayHeader so the
function returns msgp.ErrLimitExceeded without writing anything, keeping the
existing error wrapping behavior for individual element EncodeMsg calls and
matching the MarshalMsg pattern.

Copilot AI review requested due to automatic review settings February 8, 2026 08:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates msgp serialization/deserialization limits across Fiber’s cookie redirect messages, cache entries, and idempotency response payloads to better bound memory usage during decoding while removing/relaxing limits for large bodies that are governed by storage policy. It also regenerates msgp outputs accordingly and updates generated benchmarks.

Changes:

  • Add msgp limit directives/struct tags (e.g., redirect arrays/maps; cache header/body related fields; idempotency header counts) and regenerate *_msgp.go code to enforce them during decode/unmarshal.
  • Remove/avoid msgp body caps for cache and idempotency bodies, relying on storage policy limits instead.
  • Update generated benchmark loops and add targeted linter suppressions for msgp tags on unexported fields.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
redirect_msgp_test.go Updates generated benchmarks to use b.ResetTimer() and explicit for i := 0; i < b.N; i++ loops.
redirect_msgp.go Regenerated msgp code; introduces array/map size limits and adds marshal-side enforcement for redirect cookie payloads.
redirect.go Adds msgp limit directive for redirect cookie message arrays/maps and documents rationale.
middleware/session/data.go Adds documentation/comments about session size expectations.
middleware/idempotency/response_msgp.go Regenerated msgp code; enforces header map/array count limits during decode/unmarshal.
middleware/idempotency/response.go Adds limit=1024 to header field tag; clarifies body limit policy in comments.
middleware/cache/manager_msgp.go Regenerated msgp code; uses ReadBytesLimit/ReadBytesHeader and explicit limit checks for cached header/value and related fields.
middleware/cache/manager.go Adds msgp limit tags to unexported fields and //nolint:revive annotations to satisfy linting.

@gaby gaby changed the title 🐛 bug: Apply limits to msgp serialization 🐛 bug: apply limits to msgp serialization Feb 8, 2026
@ReneWerner87
Copy link
Member

@gaby can you check ai comments

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@gaby
Copy link
Member Author

gaby commented Feb 8, 2026

@copilot Should we add msgp limits anywhere else?

Copy link
Contributor

Copilot AI commented Feb 8, 2026

@gaby I've opened a new pull request, #4067, to work on those changes. Once the pull request is ready, I'll request review from you.

@ReneWerner87 ReneWerner87 merged commit 04a44f9 into main Feb 9, 2026
30 checks passed
@ReneWerner87 ReneWerner87 deleted the add-msgp-limits-to-generated-sources branch February 9, 2026 10:16
@github-project-automation github-project-automation bot moved this to Done in v3 Feb 9, 2026
@ReneWerner87 ReneWerner87 modified the milestones: v3, v3.1.0 Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants