Skip to content

GH-49614: [C++] Report an error instead of silent truncation in base64_decode on invalid input - #49660

Merged
kou merged 3 commits into
apache:mainfrom
Reranko05:fix-base64-invalid-input
Apr 14, 2026
Merged

GH-49614: [C++] Report an error instead of silent truncation in base64_decode on invalid input#49660
kou merged 3 commits into
apache:mainfrom
Reranko05:fix-base64-invalid-input

Conversation

@Reranko05

@Reranko05Reranko05 commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Rationale for this change

arrow::util::base64_decode previously allowed invalid input to be processed, which could result in silently truncated or incorrect output without signaling an error. This can lead to unintended data corruption.

What changes are included in this PR?

  • Change base64_decode to return arrow::Result<std::string> instead of std::string
  • Add validation for:
    • invalid input length
    • invalid base64 characters
    • incorrect padding
  • Return an error (Status::Invalid) for invalid input instead of producing partial output
  • Update all call sites to handle Result<std::string>
  • Add unit tests covering valid and invalid inputs

Are these changes tested?

Yes. Unit tests have been added to verify:

  • valid decoding behavior
  • invalid input length
  • invalid characters
  • incorrect padding handling

Are there any user-facing changes?

  • The API now returns arrow::Result<std::string> instead of std::string
  • Invalid base64 input now results in an error (Status::Invalid) instead of returning partial or incorrect output

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #49614has been automatically assigned in GitHub to PR creator.

Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
@Reranko05
Reranko05force-pushed the fix-base64-invalid-input branch from 4670ec5 to 5c7db64CompareApril 4, 2026 20:38
@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Thanks for the feedback. I’ve updated the implementation and tests.

  • Added stricter validation (length, padding placement/count, allowed characters)
  • Removed early termination in the decode loop to avoid silent truncation
  • Expanded test coverage to include invalid inputs and edge cases

All tests pass locally. Please let me know if any further adjustments are needed.

@koukou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you use arrow::Result<std::string> return type instead of using ARROW_LOG()?

@kou

kou commented Apr 5, 2026

Copy link
Copy Markdown
Member

FYI: You can run CI on your fork by enabling GitHub Actions on your fork.

@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Could you use arrow::Result<std::string> return type instead of using ARROW_LOG()?

Thanks for the suggestion @kou !

Just to clarify, would you prefer changing the existing base64_decode API to return arrow::Resultstd::string, or introducing a separate checked variant while keeping the current API unchanged?

I want to make sure the approach aligns with existing usage and expectations.

@kou

kou commented Apr 5, 2026

Copy link
Copy Markdown
Member

"changing the existing base64_decode API to return arrow::Resultstd::string".
But I want to know how many changes are required for existing code that use base64_decode().

@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

@kou I checked the current usages of base64_decode(), and it appears to be used in a very limited number of places (primarily in tests and one internal call site in flight_test.cc).

Updating to arrow::Result<std::string> would require adjusting those call sites to use ARROW_ASSIGN_OR_RAISE, but the impact seems quite localized and manageable.

I can proceed with the API change and update the affected call sites accordingly.

@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Hi @kou, just following up on this.

I can proceed with updating base64_decode() to return arrow::Result<std::string> and adjust the affected call sites accordingly. Please let me know if this approach looks good, or if you'd prefer any alternative.

Happy to proceed based on your guidance.

@kou

kou commented Apr 8, 2026

Copy link
Copy Markdown
Member

Oh, sorry. I forgot to reply this...

Yes. Let's proceed with arrow::Result<std::string>.

@Reranko05
Reranko05force-pushed the fix-base64-invalid-input branch from 8f053b7 to 34a388cCompareApril 8, 2026 09:53
@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Hi @kou, thanks for confirming!

I’ve updated base64_decode() to return arrow::Result<std::string> and added validation for invalid inputs (length, padding, and non-base64 characters). I also updated the tests accordingly.

All tests are passing locally. Please let me know if you’d like any changes or adjustments.

Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/util/base64.h
Comment threadcpp/src/arrow/util/base64.h Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated

CopilotAI 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.

Pull request overview

This PR addresses a correctness issue in Arrow’s C++ base64 decoder by ensuring malformed base64 input is detected instead of producing silently truncated/partial output.

Changes:

  • Adds pre-validation for base64 input (length, padding placement, invalid characters) in base64_decode.
  • Changes base64_decode API to return arrow::Result<std::string> with Status::Invalid on malformed input.
  • Adds unit tests covering valid/invalid decoding cases (and adjusts a couple of ToChars assertions).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

FileDescription
cpp/src/arrow/vendored/base64.cppAdds base64 input validation and switches decode to return errors instead of partial output.
cpp/src/arrow/util/base64.hUpdates public API signature of base64_decode to return Result<std::string>.
cpp/src/arrow/util/string_test.ccAdds tests for base64 decode validity/error cases and tweaks ToChars expectations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadcpp/src/arrow/util/base64.h
Comment threadcpp/src/arrow/util/base64.h
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
@Reranko05
Reranko05force-pushed the fix-base64-invalid-input branch from 34a388c to ed84348CompareApril 8, 2026 17:09
@Reranko05

Reranko05 commented Apr 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Hi @kou, I have addressed all review comments:

  • Removed redundant helpers and reused existing base64_chars
  • Merged validation into decoding loop (single-pass)
  • Fixed padding validation to ensure '=' only appears at the end
  • Cleaned up includes and namespace usage
  • Updated tests to improve coverage and follow Arrow conventions

All tests pass locally.

@kou
kou requested a review from CopilotApril 8, 2026 21:14
@kou

kou commented Apr 8, 2026

Copy link
Copy Markdown
Member

Could you enable GitHub Actions on your fork to run CI on your fork too?

CopilotAI 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.

Pull request overview

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


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc Outdated
Comment threadcpp/src/arrow/util/string_test.cc
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/arrow/vendored/base64.cpp Outdated
Comment threadcpp/src/parquet/encryption/file_key_unwrapper.cc Outdated
Comment threadcpp/src/parquet/encryption/key_toolkit_internal.cc Outdated

CopilotAI 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.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadcpp/src/gandiva/gdv_function_stubs.cc
@Reranko05
Reranko05force-pushed the fix-base64-invalid-input branch from 22e6c2c to 98e24deCompareApril 13, 2026 01:34
@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Hi @kou, I have addressed the remaining feedback by using PARQUET_ASSIGN_OR_THROW and updating error handling to return deterministic, case-specific messages. All CI checks are passing.

CopilotAI 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.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadcpp/src/arrow/vendored/base64.cpp
Comment threadcpp/src/arrow/util/base64_test.cc
Comment threadcpp/src/arrow/util/CMakeLists.txt
kou
kou approved these changes Apr 13, 2026

@koukou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1

@dmitry-chirkov-dremio Do you want to review this before we merge this?

@dmitry-chirkov-dremio

dmitry-chirkov-dremio commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

@dmitry-chirkov-dremio Do you want to review this before we merge this?

Yes, give me 24h.

@dmitry-chirkov-dremiodmitry-chirkov-dremio 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.

Looks good to me however won't approve until conversations are resolved (including Copilot's comments). Leaving couple of comments of my own as well.

Good job, @Reranko05 - almost there.
cc @kou

Comment threadcpp/src/arrow/vendored/base64.cpp
Comment threadcpp/src/arrow/vendored/base64.cpp
@Reranko05

Copy link
Copy Markdown
CollaboratorAuthor

Good job, @Reranko05 - almost there. cc @kou

Thank you @dmitry-chirkov-dremio, I've addressed all review comments and resolved outstanding threads.

@dmitry-chirkov-dremiodmitry-chirkov-dremio 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.

LGTM

@kou

kou commented Apr 14, 2026

Copy link
Copy Markdown
Member

Thanks. I'll merge this.

@koukou changed the title GH-49614: [C++] Fix silent truncation in base64_decode on invalid inputGH-49614: [C++] Report an error instead of silent truncation in base64_decode on invalid inputApr 14, 2026
@kou
kou merged commit d9aeaa1 into apache:mainApr 14, 2026
57 of 58 checks passed
@koukou removed the awaiting committer review Awaiting committer review label Apr 14, 2026
@Reranko05
Reranko05 deleted the fix-base64-invalid-input branch April 14, 2026 08:00
@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 3 benchmarking runs that have been run so far on merge-commit d9aeaa1.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details. It also includes information about 5 possible false positives for unstable benchmarks that are known to sometimes produce them.

@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 3 benchmarking runs that have been run so far on merge-commit d9aeaa1.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details. It also includes information about 5 possible false positives for unstable benchmarks that are known to sometimes produce them.

Mottl pushed a commit to Mottl/arrow that referenced this pull request May 26, 2026
… base64_decode on invalid input (apache#49660)
### Rationale for this change
`arrow::util::base64_decode` previously allowed invalid input to be processed, which could result in silently truncated or incorrect output without signaling an error. This can lead to unintended data corruption.
### What changes are included in this PR?
- Change `base64_decode` to return `arrow::Result<std::string>` instead of `std::string`
- Add validation for:
- invalid input length
- invalid base64 characters
- incorrect padding
- Return an error (`Status::Invalid`) for invalid input instead of producing partial output
- Update all call sites to handle `Result<std::string>`
- Add unit tests covering valid and invalid inputs
### Are these changes tested?
Yes. Unit tests have been added to verify:
- valid decoding behavior
- invalid input length
- invalid characters
- incorrect padding handling
### Are there any user-facing changes?
- The API now returns `arrow::Result<std::string>` instead of `std::string`
- Invalid base64 input now results in an error (`Status::Invalid`) instead of returning partial or incorrect output
* GitHub Issue: apache#49614
Authored-by: Aaditya Srinivasan <aadityasri03@gmail.com>
Signed-off-by: Sutou Kouhei <kou@clear-code.com>
kou added a commit to groonga/groonga that referenced this pull request Jul 15, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Reranko05@kou@dmitry-chirkov-dremio