Skip to content

Fix int mask sign extension in BitField long methods#1711

Open
alhudz wants to merge 1 commit into
apache:masterfrom
alhudz:bitfield-int-mask-sign-extension
Open

Fix int mask sign extension in BitField long methods#1711
alhudz wants to merge 1 commit into
apache:masterfrom
alhudz:bitfield-int-mask-sign-extension

Conversation

@alhudz

@alhudz alhudz commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Repro: new BitField(0x80000000), then getRawValue(-1L) / clear(-1L).
Expected: getRawValue(-1L) == 0x80000000 and clear(-1L) == 0xFFFFFFFF7FFFFFFF, since only bit 31 belongs to the field.
Actual: getRawValue(-1L) == 0xFFFFFFFF80000000 and clear(-1L) == 0x7FFFFFFF, so bits 32-63 leak into the field.
Cause: the long mask field and the long-typed methods arrived in 3.21.0, but BitField(int) still assigns the int mask straight into the long field, so any mask with bit 31 set is sign-extended across bits 32-63. The int-typed methods cast back to int and hide it, the long ones do not.
Fix: build the field with Integer.toUnsignedLong(mask) so the int mask only occupies the low 32 bits.

@garydgregory garydgregory changed the title fix int mask sign extension in BitField long methods Fix int mask sign extension in BitField long methods Jun 17, 2026
public BitField(final int mask) {
this.mask = mask;
this.mask = Integer.toUnsignedLong(mask);
this.shiftCount = mask == 0 ? 0 : Integer.numberOfTrailingZeros(mask);

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.

Hello @alhudz
Thank you for the PR.
Should the argument to numberOfTrailingZeros be mask or this.mask?

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.

2 participants