From 47ddf672e3ee161bfbc5c9c2d718f69160ed13cd Mon Sep 17 00:00:00 2001 From: James Yuzawa Date: Fri, 11 Sep 2026 09:13:14 -0400 Subject: [PATCH] fix bitfield off-by-one encoding --- .../encoder/FixedBitfieldEncoder.java | 2 +- .../com/iab/gpp/encoder/GppModelTest.java | 18 +++++++----------- .../encoder/FixedBitfieldEncoderTest.java | 19 ++++++++++++------- .../iab/gpp/encoder/section/TcfCaV1Test.java | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoder.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoder.java index cb1e14a..c6be967 100644 --- a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoder.java +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoder.java @@ -8,7 +8,7 @@ private FixedBitfieldEncoder() {} public static void encode(BitString builder, IntegerSet value, int bitStringLength) { for (int i = 0; i < bitStringLength; i++) { - builder.writeBoolean(value.containsInt(i)); + builder.writeBoolean(value.containsInt(i + 1)); } } } diff --git a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java index 147c340..2fd6098 100644 --- a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java +++ b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java @@ -397,7 +397,7 @@ public void testEncodeUspV1AndTcfEuV2AndTcfCaV1() { String gppString = gppModel.encode(); Assertions.assertEquals( - "DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.IAAA~BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao~1YNN", + "DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.IAAA~BPSG_8APSG_8AAyACAENGdCg_fA_AA_A_ABgABABAAABAB4AACACAAA.eOOOBxxxwcQ~1YNN", gppString); Assertions.assertEquals(4, gppString.split("~").length); @@ -824,12 +824,10 @@ public void testDecode9() { public void testConsistency() { GppModel fromObjectModel = new GppModel(); - fromObjectModel.setFieldValue( - TcfEuV2.NAME, TcfEuV2Field.PURPOSE_CONSENTS, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); - fromObjectModel.setFieldValue( - TcfEuV2.NAME, - TcfEuV2Field.VENDOR_CONSENTS, - Arrays.asList(32, 128, 81, 210, 755, 21, 173, 238)); + Set purposeConsents = Set.of(1, 2, 4, 5, 6, 8, 9); + fromObjectModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.PURPOSE_CONSENTS, purposeConsents); + Set vendorConsents = Set.of(32, 128, 81, 210, 755, 21, 173, 238); + fromObjectModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS, vendorConsents); Assertions.assertEquals( fromObjectModel.getSection(TcfEuV2.NAME).encode(), @@ -839,11 +837,9 @@ public void testConsistency() { GppModel decodedModel = new GppModel(fromObjectModel.encode()); Assertions.assertEquals( - Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), - decodedModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.PURPOSE_CONSENTS)); + purposeConsents, decodedModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.PURPOSE_CONSENTS)); Assertions.assertEquals( - Set.of(21, 32, 81, 128, 173, 210, 238, 755), - decodedModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS)); + vendorConsents, decodedModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS)); } @Test diff --git a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoderTest.java b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoderTest.java index e8ea82e..d191d6d 100644 --- a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoderTest.java +++ b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/datatype/encoder/FixedBitfieldEncoderTest.java @@ -13,8 +13,13 @@ public class FixedBitfieldEncoderTest { public void testEncode1() { BitString builder = new BitString(); IntegerSet set = new IntegerSet(); - FixedBitfieldEncoder.encode(builder, set, 2); - Assertions.assertEquals("00", builder.toString()); + set.add(2); + set.add(4); + set.add(6); + FixedBitfieldEncoder.encode(builder, set, 6); + String encoded = builder.toString(); + Assertions.assertEquals("010101", encoded); + Assertions.assertEquals(set, decode(encoded)); } @Test @@ -29,7 +34,7 @@ public void testEncode2() { public void testEncode3() { BitString builder = new BitString(); IntegerSet set = new IntegerSet(); - set.add(0); + set.add(1); FixedBitfieldEncoder.encode(builder, set, 1); Assertions.assertEquals("1", builder.toString()); } @@ -48,24 +53,24 @@ public void testEncode5() { IntegerSet set = new IntegerSet(); set.addInt(1); FixedBitfieldEncoder.encode(builder, set, 2); - Assertions.assertEquals("01", builder.toString()); + Assertions.assertEquals("10", builder.toString()); } @Test public void testEncode6() { BitString builder = new BitString(); IntegerSet set = new IntegerSet(); - set.addInt(0); + set.addInt(2); FixedBitfieldEncoder.encode(builder, set, 2); - Assertions.assertEquals("10", builder.toString()); + Assertions.assertEquals("01", builder.toString()); } @Test public void testEncode7() { BitString builder = new BitString(); IntegerSet set = new IntegerSet(); - set.addInt(0); set.addInt(1); + set.addInt(2); FixedBitfieldEncoder.encode(builder, set, 2); Assertions.assertEquals("11", builder.toString()); } diff --git a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/TcfCaV1Test.java b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/TcfCaV1Test.java index 9c184d5..fcf6749 100644 --- a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/TcfCaV1Test.java +++ b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/TcfCaV1Test.java @@ -66,7 +66,7 @@ public void testEncode2() { ZonedDateTime.of(2022, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")).toInstant()); Assertions.assertEquals( - "BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao", tcfCaV1.encode()); + "BPSG_8APSG_8AAyACAENGdCg_fA_AA_A_ABgABABAAABAB4AACACAAA.eOOOBxxxwcQ", tcfCaV1.encode()); } @Test