Skip to content

Add padding option to Base64Url - #135783

Open
mtmk wants to merge 2 commits into
dotnet:mainfrom
mtmk:base64url-padding
Open

mtmk wants to merge 2 commits into
dotnet:mainfrom
mtmk:base64url-padding

Conversation

@mtmk

@mtmk mtmk commented Oct 14, 2026

Copy link
Copy Markdown

Adds Base64UrlFormattingOptions and overloads of the Base64Url encode methods that take it, so callers can emit the = padding that some base64url consumers require (Go's base64.URLEncoding, Python's urlsafe_b64encode) instead of appending it by hand or post-processing Convert.ToBase64String. Padding goes through the existing tail path via a second encoder struct, so the vectorized loops are unchanged, and on the OperationStatus overloads it applies to the final block only. The new API is not exposed through Microsoft.Bcl.Memory: that package's net10.0 asset type-forwards Base64Url to a framework without these members, so a netstandard library compiled against the package would fail at run time on .NET 10.

Fixes #129847

Some base64url consumers (Go's encoding/base64.URLEncoding, Python's
urlsafe_b64encode, several JWT and OAuth libraries) require the '='
padding that RFC 4648 section 5 makes optional. Base64Url only ever
produced unpadded output, so callers had to append padding by hand or
post-process Convert.ToBase64String.

Add Base64UrlFormattingOptions with IncludePadding and overloads of the
encode methods that take it. Padding goes through the existing tail
path via a second encoder struct, so the vectorized loops are
unchanged. On the OperationStatus overloads the option applies to the
final block only; non-final calls use the unpadded encoder so their
destination sizing is unaffected. Value 1 of the enum is left unused so
a line break flag could later match Base64FormattingOptions.

The overloads live in a file that only CoreLib compiles. The
Microsoft.Bcl.Memory net10.0 asset type-forwards Base64Url to a
framework without them, so a library compiled against the package's
netstandard asset would fail at run time on .NET 10 if the package
exposed them.

Fix dotnet#129847
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 14, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-memory
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Guarded-buffer coverage remains missing, and the unsafe encoding paths were not built or exercised during this review.

1 open finding
What changed in this PR

Adds opt-in Base64Url padding for interoperability while preserving existing unpadded behavior.

Changes:

  • Adds formatting options and encoding overloads.
  • Reuses existing encoding helpers, applying padding only to final blocks.
  • Adds validation, boundary, streaming, and reference-output tests.
File Description
src/​libraries/​System.Runtime/​ref/​System.Runtime.cs Declares the new public APIs.
src/​libraries/​System.Private.CoreLib/​src/​System/​Buffers/​Text/​Base64Url/​Base64UrlFormattingOptions.cs Defines padding options.
src/​libraries/​System.Private.CoreLib/​src/​System/​Buffers/​Text/​Base64Url/​Base64UrlEncoder.Padding.cs Implements padded encoding overloads and helpers.
src/​libraries/​System.Private.CoreLib/​src/​System.Private.CoreLib.Shared.projitems Includes the new implementation files.
src/​libraries/​System.Memory/​tests/​Base64Url/​Base64UrlEncoderUnitTests.cs Tests padding behavior and error handling.

🧠 Review effort: Balanced

Comment on lines +290 to +292
public int GetMaxSrcLength(int srcLength, int destLength) =>
srcLength <= MaximumEncodeLength && destLength >= GetPaddedEncodedLength(srcLength) ?
srcLength : (destLength >> 2) * 3;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fixed in ca48546 Add guarded-buffer tests for Base64Url padding

The padding tests used managed arrays, which cannot catch a read or
write past the end of a span. Encode from a BoundedMemory source into
BoundedMemory byte and char destinations with a poison page after each,
at the scalar and vector block boundaries with 0, 1 and 2 byte tails,
using exact-size and one-short destinations and the in-place path.

Extend the Base64Url fuzzer with the IncludePadding overloads so
continuous fuzzing covers them as well.

This branch has not been deployed

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

Labels

area-System.Memory community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Base64Url option to emit padding

2 participants