Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SUREFIRE-2076] BufferOverflowException when encoding message with null runMode #529

Merged
merged 2 commits into from Apr 27, 2022

Conversation

zoltanmeze
Copy link
Contributor

Per @Tibor17's comment #518 (comment) and #518 (comment)
and after some dicsussion (see comment after #518 (comment)) pulled this into a separate issue.

Jira ticket: https://issues.apache.org/jira/browse/SUREFIRE-2076

AbstractStreamEncoder#encodeHeader stores runMode part in at least 3 bytes:

  • 1 byte for length
  • 1 byte delimiter
  • runMode content in length-bytes
  • 1 byte delimiter

In case of null runMode the encoded part becomes 0:: (exactly 3 bytes length)

The issue is that AbstractStreamEncoder#estimateBufferLength is not expecting/couting any bytes for runMode part in case of null runMode. This results in in BufferOverflowException becase the byte size of the entire message is underestimated.

Exception thrown:

java.nio.BufferOverflowException
	at java.nio.Buffer.nextPutIndex(Buffer.java:547)
	at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:172)
	at org.apache.maven.surefire.api.stream.AbstractStreamEncoder.encodeString(AbstractStreamEncoder.java:127)
	at org.apache.maven.surefire.api.stream.AbstractStreamEncoder.encodeStringData(AbstractStreamEncoder.java:171)
	at org.apache.maven.surefire.api.stream.AbstractStreamEncoder.encode(AbstractStreamEncoder.java:157)
	at org.apache.maven.surefire.booter.spi.EventChannelEncoder.encodeMessage(EventChannelEncoder.java:398)
	at org.apache.maven.surefire.booter.spi.EventChannelEncoder.setOutErr(EventChannelEncoder.java:188)
	at org.apache.maven.surefire.booter.spi.EventChannelEncoder.testOutput(EventChannelEncoder.java:183)
	at org.apache.maven.surefire.api.booter.ForkingRunListener.writeTestOutput(ForkingRunListener.java:113)
	at org.apache.maven.surefire.api.booter.ForkingRunListener.writeTestOutput(ForkingRunListener.java:44)
	at org.apache.maven.surefire.common.junit4.JUnit4RunListener.writeTestOutput(JUnit4RunListener.java:235)
	at org.apache.maven.surefire.api.report.ConsoleOutputCapture$ForwardingPrintStream.println(ConsoleOutputCapture.java:144)

Following this checklist to help us incorporate your
contribution quickly and easily:

  • Make sure there is a JIRA issue filed
    for the change (usually before you start working on it). Trivial changes like typos do not
    require a JIRA issue. Your pull request should address just this issue, without
    pulling in other changes.
  • Each commit in the pull request should have a meaningful subject line and body.
  • Format the pull request title like [SUREFIRE-XXX] - Fixes bug in ApproximateQuantiles,
    where you replace SUREFIRE-XXX with the appropriate JIRA issue. Best practice
    is to use the JIRA issue title in the pull request title and in the first line of the
    commit message.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Run mvn clean install to make sure basic checks pass. A more thorough check will
    be performed on your pull request automatically.
  • You have run the integration tests successfully (mvn -Prun-its clean install).

If your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.

To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.

@Tibor17
Copy link
Contributor

Tibor17 commented Apr 25, 2022

After the #518 is merged, you have to rebase this PR. Then we will run the CI again.

@Tibor17
Copy link
Contributor

Tibor17 commented Apr 26, 2022

#518 was merged, let's concentrate on this one.

@zoltanmeze
Copy link
Contributor Author

After the #518 is merged, you have to rebase this PR. Then we will run the CI again.

Rebased onto latest master.

#518 was merged, let's concentrate on this one.

The issue should be easily reproducible with AbstractStreamEncoderTest#testStdErrStreamEmptyMessageNullRunMode. Test implemented similar way as testStdErrStreamEmptyMessageNullTestId from SUREFIRE-2056.

Expected length also changed in AbstractStreamEncoderTest#shouldComputeStreamPreemptiveLength
in cases where runMode is set to null, in those cases length is now greater by 3. Also included how the output should look like (without testId) in the comments.

Copy link
Contributor

@Tibor17 Tibor17 left a comment

Choose a reason for hiding this comment

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

LGTM

@Tibor17
Copy link
Contributor

Tibor17 commented Apr 26, 2022

@zoltanmeze This change looks fine. Pls check the method estimateBufferLength() completely if you see something we need to improve. thx

@zoltanmeze
Copy link
Contributor Author

zoltanmeze commented Apr 26, 2022

@zoltanmeze This change looks fine. Pls check the method estimateBufferLength() completely if you see something we need to improve. thx

Looks fine to me. Checked the usages a bit, was mostly looking if long and integer counts are properly set.

One thing I noticed, there is a null smartStackTrace included in encode on EventChannelEncoder#L221 but that same null string in not included in estimateBufferLength on EventChannelEncoder.java#L217. On master without these changes it's possible to get BufferOverflowException in EventChannelEncoderTest#testConsoleError by reducing message to only two characters or on this branch with empty string. Not really related to runMode, just noticed.

@Tibor17
Copy link
Contributor

Tibor17 commented Apr 27, 2022

@zoltanmeze
Exactly! The line should be int bufferMaxLength = estimateBufferLength( BOOTERCODE_CONSOLE_ERROR.getOpcode().length(), null, encoder, 0, 0, message, null, stackTrace ); which includes null string. This should be fixed as well. Would you continue on this?

…timation in consoleErrorLog

Can potentially lead to BufferOverflowException with underestimated buffer length
@zoltanmeze
Copy link
Contributor Author

Included missing null in 6e5a49c.

I don't think it's worth adding a unit test for this. This was obviously just missing. There are a couple of tests covering consoleErrorLog, but usually buffer length is overestimated because strings are allocating more space than what they actually need with encoder.maxBytesPerChar() * s.length(), so this was not causing any issues.

@Tibor17
Copy link
Contributor

Tibor17 commented Apr 27, 2022

If there are no objections, I would proceed with this PR.

@zoltanmeze
Copy link
Contributor Author

If there are no objections, I would proceed with this PR.

No objections from me

@Tibor17 Tibor17 merged commit 71f8717 into apache:master Apr 27, 2022
@Tibor17
Copy link
Contributor

Tibor17 commented Apr 27, 2022

Thx for contributing.

@olamy olamy added the bug label May 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants