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

Fix Proto encoding of negative integers #889

Merged
merged 1 commit into from
Feb 7, 2024

Conversation

cklin
Copy link
Contributor

@cklin cklin commented Feb 7, 2024

Currently the Proto class determines whether to emit a continuing byte for the integer value n this way:

while (n > 0x7f) {

The intention of the comparison is to check whether n has any bit set below the lowest 7 bits. Unfortunately it does not work if n is negative, which causes the loop to be skipped entirely. When that happens, the jfr2pprof produces a protobuf profile that is rejected by pprof.

This PR fixes the bug so that Proto encodes negative integer values correctly.

@@ -71,7 +71,7 @@ public void writeInt(int n) {
int length = n == 0 ? 1 : (38 - Integer.numberOfLeadingZeros(n)) / 7;
ensureCapacity(length);

while (n > 0x7f) {
while (n & 0x7f != n) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why can a number be negative? In what cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The case I hit was nanosSinceLastSample in jfr2pprof.java being negative.

I don't know if that is supposed to happen; all I can tell you is that it happened, with async-profiler 3.0 and the default clock source.

@@ -82,7 +82,7 @@ public void writeLong(long n) {
int length = n == 0 ? 1 : (70 - Long.numberOfLeadingZeros(n)) / 7;
ensureCapacity(length);

while (n > 0x7f) {
while (n & 0x7f != n) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A canonical way to check if an integer has higher bits set is

(n & ~0x7f) != 0

or

(n >>> 7) != 0

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the check based on your suggestion.

@cklin cklin requested a review from apangin February 7, 2024 19:56
@apangin apangin merged commit ad05845 into async-profiler:master Feb 7, 2024
1 check passed
@apangin
Copy link
Collaborator

apangin commented Feb 7, 2024

Thank you for the fix. Merged.

@cklin cklin deleted the protobuf-encoding-fix branch February 7, 2024 20:49
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.

None yet

2 participants