Skip to content

Fix: Integer Truncation in PatternLayout causing heap corruption with large logs#584

Closed
OxBat wants to merge 2 commits intoapache:masterfrom
OxBat:fix/patternlayout-integer-truncation
Closed

Fix: Integer Truncation in PatternLayout causing heap corruption with large logs#584
OxBat wants to merge 2 commits intoapache:masterfrom
OxBat:fix/patternlayout-integer-truncation

Conversation

@OxBat
Copy link
Copy Markdown
Contributor

@OxBat OxBat commented Jan 27, 2026

Summary

I identified a critical integer truncation vulnerability in PatternLayout::format. The code explicitly casts the 64-bit buffer length (size_t) to a signed 32-bit integer (int).

On 64-bit systems, if a log message exceeds 2GB (e.g., large JSON dumps or accumulated stack traces), the length wraps around to a negative number. This negative index is then passed to downstream formatters, leading to out-of-bounds memory access (heap corruption) or segmentation faults.

Technical Analysis

In src/main/cpp/patternlayout.cpp (around line 130):

// Vulnerable Code:
int startField = (int)output.length();

When output.length() > INT_MAX, startField becomes negative. This startField is subsequently used for pointer arithmetic or string indexing in FormattingInfo, causing the crash.

Remediation
This patch removes the unsafe cast and updates the variable type to size_t to correctly handle the return type of std::string::length().

Steps to Reproduce (Logic)

  1. Configure a PatternLayout with %m.
  2. Log a message string larger than 2GB on a 64-bit build.
  3. The cast to int truncates the size, resulting in a negative offset.

The explicit cast to (int) caused negative indexing when processing
log messages larger than 2GB on 64-bit systems, leading to potential
heap corruption. Changed startField type to size_t.
Comment thread src/main/cpp/patternlayout.cpp Outdated
{
int startField = (int)output.length();
// Fix integer truncation vulnerability (size_t to int cast)
size_t startField = output.length();
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.

it looks like you have some odd indentation here.

the comment is also not helpful, can we remove it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've removed the comment and fixed the indentation

@swebb2066
Copy link
Copy Markdown
Contributor

The proposed change does not correct the problem as the truncation still occurs when passing startField to FormattingInfo::format as its signature is:
void FormattingInfo::format(const int fieldStart, LogString& buffer) const

I suggest the correct solution is not calling FormattingInfo::format if the length exceeds INT_MAX

@swebb2066
Copy link
Copy Markdown
Contributor

Resolved by #593

@swebb2066 swebb2066 closed this Feb 13, 2026
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.

3 participants