From 05c806f65c526d820ae3c52d0b77c81fa3719a3f Mon Sep 17 00:00:00 2001 From: Vikram Gaur Date: Sat, 25 Jul 2026 17:16:03 +0000 Subject: [PATCH 1/2] Add support for newer SDKs. The library fails to compile on latest JDKs since the JDKs have now started to strictly encapsulate internal JDK packages. Since ErrorProne requires access to these internal packages, we need to grant access to these internal packages. This change also fixes a minor issue with memory allocation. --- pom.xml | 51 +++++++++++++++++------- src/com/google/cose/utils/CborUtils.java | 9 ++++- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index de6b1ce..140c50b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,19 +20,19 @@ com.google.guava guava - 32.1.1-android + 33.6.0-android com.google.crypto.tink tink-android - 1.10.0 + 1.23.0 org.bouncycastle - bcprov-jdk15on - 1.69 + bcprov-jdk18on + 1.84 jar @@ -42,10 +42,8 @@ %regex[.*.class] - 1.1.2 - 3.12.0 - 3.1.0 - 3.2.1 + 3.12.0 + 3.4.0 UTF-8 @@ -126,6 +124,29 @@ --> 8 8 + true + + -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED + -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED + -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED + @@ -133,7 +154,7 @@ maven-compiler-plugin - 3.8.1 + 3.15.0 1.8 1.8 @@ -145,14 +166,14 @@ com.google.errorprone error_prone_core - 2.14.0 + 2.49.0 maven-jar-plugin - 3.2.0 + 3.5.0 maven-source-plugin @@ -192,15 +213,15 @@ maven-dependency-plugin - 3.1.1 + 3.11.0 maven-antrun-plugin - 1.6 + 3.2.0 maven-surefire-plugin - 2.22.2 + 3.5.6 ${test.include} @@ -216,7 +237,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.6.3 diff --git a/src/com/google/cose/utils/CborUtils.java b/src/com/google/cose/utils/CborUtils.java index 67739cc..6f17461 100644 --- a/src/com/google/cose/utils/CborUtils.java +++ b/src/com/google/cose/utils/CborUtils.java @@ -47,7 +47,14 @@ public class CborUtils { */ public static DataItem decode(final byte[] data) throws CborException { final ByteArrayInputStream bais = new ByteArrayInputStream(data); - final List dataItems = new CborDecoder(bais).decode(); + final CborDecoder decoder = new CborDecoder(bais); + decoder.setMaxPreallocationSize(data.length); + final List dataItems; + try { + dataItems = new CborDecoder(bais).decode(); + } catch (OutOfMemoryError e) { + throw new CborException("CBOR declared size exceeds input length", e); + } if (dataItems.size() != 1) { throw new CborException("Byte stream cannot be decoded properly. Expected 1 item, found " + dataItems.size()); From d6f10f52d54359a57ee384f56d4a3af77d1459bf Mon Sep 17 00:00:00 2001 From: Vikram Gaur Date: Thu, 30 Jul 2026 20:03:01 +0000 Subject: [PATCH 2/2] Add null checks to CborUtils and test cases. This change adds a new test file CborUtilsTest for testing the utility functions. It also adds null checks in the helper functions to avoid NullPointerException. --- .gitignore | 2 + src/com/google/cose/utils/CborUtils.java | 27 ++++ test/com/google/cose/utils/CborUtilsTest.java | 153 ++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 .gitignore create mode 100644 test/com/google/cose/utils/CborUtilsTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e97c6ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +*.class diff --git a/src/com/google/cose/utils/CborUtils.java b/src/com/google/cose/utils/CborUtils.java index 6f17461..bdee45c 100644 --- a/src/com/google/cose/utils/CborUtils.java +++ b/src/com/google/cose/utils/CborUtils.java @@ -46,6 +46,9 @@ public class CborUtils { * @return DataItem cbor object */ public static DataItem decode(final byte[] data) throws CborException { + if (data == null) { + throw new CborException("data cannot be null"); + } final ByteArrayInputStream bais = new ByteArrayInputStream(data); final CborDecoder decoder = new CborDecoder(bais); decoder.setMaxPreallocationSize(data.length); @@ -68,6 +71,9 @@ public static DataItem decode(final byte[] data) throws CborException { * @return encoded bytes */ public static byte[] encode(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } final ByteArrayOutputStream baos = new ByteArrayOutputStream(); CborEncoder encoder = new CborEncoder(baos); encoder.encode(dataItem); @@ -80,6 +86,9 @@ public static byte[] encode(final DataItem dataItem) throws CborException { * @return Map object */ public static Map asMap(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } if (dataItem.getMajorType() != MajorType.MAP) { throw new CborException( String.format("Expected a map, got %s", dataItem.getMajorType().name())); @@ -93,6 +102,9 @@ public static Map asMap(final DataItem dataItem) throws CborException { * @return Array object */ public static Array asArray(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } if (dataItem.getMajorType() != MajorType.ARRAY) { throw new CborException( String.format("Expected an array, got %s", dataItem.getMajorType().name())); @@ -102,6 +114,9 @@ public static Array asArray(final DataItem dataItem) throws CborException { public static Array asArray(final DataItem dataItem, final int length, final String semanticName) throws CborException { + if (semanticName == null) { + throw new CborException("semanticName cannot be null"); + } Array item = asArray(dataItem); if (item.getDataItems().size() != length) { throw new CborException(String.format("Expected %s to be of size %d, recieved %d", @@ -125,6 +140,9 @@ public static List getDataItems(final DataItem dataItem) throws CborEx * @return ByteString object */ public static ByteString asByteString(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } if (dataItem.getMajorType() != MajorType.BYTE_STRING) { throw new CborException( String.format("Expected a byte string, got %s", dataItem.getMajorType().name())); @@ -147,6 +165,9 @@ public static byte[] getBytes(final DataItem dataItem) throws CborException { * @return UnicodeString object */ public static UnicodeString asUnicodeString(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } if (dataItem.getMajorType() != MajorType.UNICODE_STRING) { throw new CborException( String.format("Expected a unicode string, got %s", dataItem.getMajorType().name())); @@ -170,6 +191,9 @@ public static String getString(final DataItem dataItem) throws CborException { * @throws CborException if dataItem is neither UnsignedInteger not NegativeInteger */ public static int asInteger(final DataItem dataItem) throws CborException { + if (dataItem == null) { + throw new CborException("dataItem cannot be null"); + } if (dataItem.getMajorType() == MajorType.UNSIGNED_INTEGER) { return ((UnsignedInteger) dataItem).getValue().intValue(); } @@ -186,6 +210,9 @@ public static int asInteger(final DataItem dataItem) throws CborException { * @return true if the item represents NULL */ public static boolean isNull(final DataItem item) { + if (item == null) { + return false; + } return (item.getMajorType() == MajorType.SPECIAL) && ((Special) item).getSpecialType() == SpecialType.SIMPLE_VALUE && ((SimpleValue) item).getSimpleValueType() == SimpleValueType.NULL; diff --git a/test/com/google/cose/utils/CborUtilsTest.java b/test/com/google/cose/utils/CborUtilsTest.java new file mode 100644 index 0000000..496a345 --- /dev/null +++ b/test/com/google/cose/utils/CborUtilsTest.java @@ -0,0 +1,153 @@ +package com.google.cose.utils; + +import co.nstant.in.cbor.CborException; +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.ByteString; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.Map; +import co.nstant.in.cbor.model.NegativeInteger; +import co.nstant.in.cbor.model.SimpleValue; +import co.nstant.in.cbor.model.UnicodeString; +import co.nstant.in.cbor.model.UnsignedInteger; +import org.junit.Assert; +import org.junit.Test; + +public class CborUtilsTest { + @Test + public void testDecodeNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.decode(null)); + } + + @Test + public void testEncodeNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.encode(null)); + } + + @Test + public void testAsMapNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asMap(null)); + } + + @Test + public void testAsArrayNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asArray(null)); + } + + @Test + public void testAsArrayThreeArgsNullSemanticNameThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asArray(new Array(), 0, null)); + } + + @Test + public void testAsArrayThreeArgsNullDataItemThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asArray(null, 0, "name")); + } + + @Test + public void testAsByteStringNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asByteString(null)); + } + + @Test + public void testAsUnicodeStringNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asUnicodeString(null)); + } + + @Test + public void testAsIntegerNullThrows() { + Assert.assertThrows(CborException.class, () -> CborUtils.asInteger(null)); + } + + @Test + public void testIsNullReturnsFalseForNull() { + Assert.assertFalse(CborUtils.isNull(null)); + } + + @Test + public void testEncodeDecode() throws CborException { + UnicodeString item = new UnicodeString("test"); + byte[] encoded = CborUtils.encode(item); + DataItem decoded = CborUtils.decode(encoded); + Assert.assertEquals(item, decoded); + } + + @Test + public void testAsMapPositive() throws CborException { + Map map = new Map(); + Assert.assertEquals(map, CborUtils.asMap(map)); + } + + @Test + public void testAsMapNegativeWrongType() { + Assert.assertThrows(CborException.class, () -> CborUtils.asMap(new Array())); + } + + @Test + public void testAsArrayPositive() throws CborException { + Array array = new Array(); + Assert.assertEquals(array, CborUtils.asArray(array)); + } + + @Test + public void testAsArrayNegativeWrongType() { + Assert.assertThrows(CborException.class, () -> CborUtils.asArray(new Map())); + } + + @Test + public void testAsArrayThreeArgsPositive() throws CborException { + Array array = new Array(); + array.add(new UnicodeString("item")); + Assert.assertEquals(array, CborUtils.asArray(array, 1, "test-array")); + } + + @Test + public void testAsArrayThreeArgsWrongSizeThrows() { + Array array = new Array(); + Assert.assertThrows(CborException.class, () -> CborUtils.asArray(array, 1, "test-array")); + } + + @Test + public void testAsByteStringPositive() throws CborException { + ByteString bs = new ByteString(new byte[]{1, 2, 3}); + Assert.assertEquals(bs, CborUtils.asByteString(bs)); + Assert.assertArrayEquals(new byte[]{1, 2, 3}, CborUtils.getBytes(bs)); + } + + @Test + public void testAsByteStringNegativeWrongType() { + Assert.assertThrows(CborException.class, () -> CborUtils.asByteString(new UnicodeString("not bytes"))); + } + + @Test + public void testAsUnicodeStringPositive() throws CborException { + UnicodeString us = new UnicodeString("hello"); + Assert.assertEquals(us, CborUtils.asUnicodeString(us)); + Assert.assertEquals("hello", CborUtils.getString(us)); + } + + @Test + public void testAsUnicodeStringNegativeWrongType() { + Assert.assertThrows(CborException.class, () -> CborUtils.asUnicodeString(new ByteString(new byte[]{1}))); + } + + @Test + public void testAsIntegerPositive() throws CborException { + UnsignedInteger ui = new UnsignedInteger(123); + Assert.assertEquals(123, CborUtils.asInteger(ui)); + + NegativeInteger ni = new NegativeInteger(-123); + Assert.assertEquals(-123, CborUtils.asInteger(ni)); + } + + @Test + public void testAsIntegerNegativeWrongType() { + Assert.assertThrows(CborException.class, () -> CborUtils.asInteger(new UnicodeString("not a number"))); + } + + @Test + public void testIsNullPositive() { + Assert.assertTrue(CborUtils.isNull(SimpleValue.NULL)); + Assert.assertFalse(CborUtils.isNull(SimpleValue.TRUE)); + Assert.assertFalse(CborUtils.isNull(new UnicodeString("not null"))); + } +}