From 6c75e5c10050a013fcecc3909b3f76ecd18b809a Mon Sep 17 00:00:00 2001 From: Alhuda Khan Date: Mon, 13 Jul 2026 21:07:10 +0530 Subject: [PATCH] fix sign extension in BitField.getValue for top-bit fields --- .../org/apache/commons/lang3/BitField.java | 4 ++-- .../apache/commons/lang3/BitFieldTest.java | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/BitField.java b/src/main/java/org/apache/commons/lang3/BitField.java index 91ed6ca007f..177a84d3f38 100644 --- a/src/main/java/org/apache/commons/lang3/BitField.java +++ b/src/main/java/org/apache/commons/lang3/BitField.java @@ -196,7 +196,7 @@ public short getShortValue(final short holder) { * @see #setValue(int,int) */ public int getValue(final int holder) { - return getRawValue(holder) >> shiftCount; + return getRawValue(holder) >>> shiftCount; } /** @@ -212,7 +212,7 @@ public int getValue(final int holder) { * @since 3.21.0 */ public long getValue(final long holder) { - return getRawValue(holder) >> shiftCount; + return getRawValue(holder) >>> shiftCount; } /** diff --git a/src/test/java/org/apache/commons/lang3/BitFieldTest.java b/src/test/java/org/apache/commons/lang3/BitFieldTest.java index c91f925303c..7c5fffd1f24 100644 --- a/src/test/java/org/apache/commons/lang3/BitFieldTest.java +++ b/src/test/java/org/apache/commons/lang3/BitFieldTest.java @@ -141,6 +141,26 @@ void testGetValue() { assertEquals(BF_ZERO.getValue(0), 0); } + /** + * Tests that {@link BitField#getValue(int)} and {@link BitField#getValue(long)} shift the selected bits right without sign extension when the field occupies + * the top bit of the holder (bit 31 for int, bit 63 for long). + */ + @Test + void testGetValueTopBit() { + final BitField bit31 = new BitField(0x80000000); + assertEquals(bit31.getValue(-1), 1); + assertEquals(bit31.getValue(0), 0); + final BitField topByte = new BitField(0xFF000000); + assertEquals(topByte.getValue(0xFF000000), 255); + // The int and long overloads must agree for the same field and holder. + assertEquals(topByte.getValue(0xFF000000L), 255L); + final BitField bit63 = new BitField(0x8000000000000000L); + assertEquals(bit63.getValue(0x8000000000000000L), 1L); + assertEquals(bit63.getValue(0L), 0L); + final BitField topNibble = new BitField(0xF000000000000000L); + assertEquals(topNibble.getValue(topNibble.setValue(0L, 15L)), 15L); + } + /** * Tests that an int mask with the high bit set is treated as 32 unsigned bits on the long methods, instead of being sign-extended into bits 32-63. */