From cacf0c0e19803ea19a4b8c7bf9c233d27dcbfa42 Mon Sep 17 00:00:00 2001 From: Sander Hestvik Date: Thu, 25 Apr 2024 07:55:31 +0200 Subject: [PATCH 1/2] Handle empty string input for parseBase64Binary --- api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java | 3 +++ .../test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java b/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java index 052ddb0..3e3c314 100644 --- a/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java +++ b/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java @@ -711,6 +711,9 @@ private static int guessLength(String text) { * because JIT can inline a lot of string access (with data of 1K chars, it was twice as fast) */ public static byte[] _parseBase64Binary(String text) { + if(text.isEmpty()) { + return new byte[0]; + } final int buflen = guessLength(text); if (buflen < 3) { throw new IllegalArgumentException("base64 text invalid."); diff --git a/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java b/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java index b38ca39..6c29218 100644 --- a/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java +++ b/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java @@ -84,6 +84,9 @@ public void testPrint() { @Test public void testBase64() { Assert.assertThrows(IllegalArgumentException.class, () -> DatatypeConverter.parseBase64Binary("Qxx==")); + + Assert.assertEquals("", new String(DatatypeConverter.parseBase64Binary(""))); + Assert.assertNotEquals("Hello, world!", new String(DatatypeConverter.parseBase64Binary("SGVsbG8sIJdvcmxkIQ=="))); Assert.assertEquals("Hello, world!", new String(DatatypeConverter.parseBase64Binary("SGVsbG8sIHdvcmxkIQ=="))); From 30b033ee9677509ab7c4ac151ca1aa040bdc00f3 Mon Sep 17 00:00:00 2001 From: Sander Hestvik Date: Wed, 15 May 2024 14:13:13 +0200 Subject: [PATCH 2/2] Fix input validation in _parseBase64Binary and add test cases from https://www.rfc-editor.org/rfc/rfc4648#section-10 Co-authored-by: Antonio Santos Izaguirre --- .../main/java/jakarta/xml/bind/DatatypeConverterImpl.java | 7 ++----- .../java/org/eclipse/jaxb/api/DatatypeConverterTest.java | 6 ++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java b/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java index 3e3c314..cd49706 100644 --- a/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java +++ b/api/src/main/java/jakarta/xml/bind/DatatypeConverterImpl.java @@ -711,13 +711,10 @@ private static int guessLength(String text) { * because JIT can inline a lot of string access (with data of 1K chars, it was twice as fast) */ public static byte[] _parseBase64Binary(String text) { - if(text.isEmpty()) { - return new byte[0]; - } - final int buflen = guessLength(text); - if (buflen < 3) { + if (null == text || text.length() % 4 != 0) { throw new IllegalArgumentException("base64 text invalid."); } + final int buflen = guessLength(text); final byte[] out = new byte[buflen]; int o = 0; diff --git a/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java b/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java index 6c29218..e5b99ff 100644 --- a/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java +++ b/api/src/test/java/org/eclipse/jaxb/api/DatatypeConverterTest.java @@ -86,6 +86,12 @@ public void testBase64() { Assert.assertThrows(IllegalArgumentException.class, () -> DatatypeConverter.parseBase64Binary("Qxx==")); Assert.assertEquals("", new String(DatatypeConverter.parseBase64Binary(""))); + Assert.assertEquals("f", new String(DatatypeConverter.parseBase64Binary("Zg=="))); + Assert.assertEquals("fo", new String(DatatypeConverter.parseBase64Binary("Zm8="))); + Assert.assertEquals("foo", new String(DatatypeConverter.parseBase64Binary("Zm9v"))); + Assert.assertEquals("foob", new String(DatatypeConverter.parseBase64Binary("Zm9vYg=="))); + Assert.assertEquals("fooba", new String(DatatypeConverter.parseBase64Binary("Zm9vYmE="))); + Assert.assertEquals("foobar", new String(DatatypeConverter.parseBase64Binary("Zm9vYmFy"))); Assert.assertNotEquals("Hello, world!", new String(DatatypeConverter.parseBase64Binary("SGVsbG8sIJdvcmxkIQ==")));