From: Markus Koschany <apo@debian.org>
Date: Tue, 6 Sep 2022 20:58:42 +0200
Subject: CVE-2022-25647

Bug-Debian: https://bugs.debian.org/1010670
Origin: https://github.com/google/gson/commit/e6fae590cf2a758c47cd5a17f9bf3780ce62c986
---
 .../google/gson/internal/LazilyParsedNumber.java    |  8 ++++++++
 .../com/google/gson/internal/LinkedHashTreeMap.java |  8 ++++++++
 .../com/google/gson/internal/LinkedTreeMap.java     |  8 ++++++++
 .../gson/internal/LazilyParsedNumberTest.java       | 18 ++++++++++++++++++
 .../google/gson/internal/LinkedHashTreeMapTest.java | 21 +++++++++++++++++++++
 .../com/google/gson/internal/LinkedTreeMapTest.java | 21 +++++++++++++++++++++
 6 files changed, 84 insertions(+)

diff --git a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java
index 3669af7..6138dff 100644
--- a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java
+++ b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java
@@ -15,6 +15,9 @@
  */
 package com.google.gson.internal;
 
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
 import java.math.BigDecimal;
 
@@ -77,6 +80,11 @@ public final class LazilyParsedNumber extends Number {
     return new BigDecimal(value);
   }
 
+  private void readObject(ObjectInputStream in) throws IOException {
+    // Don't permit directly deserializing this class; writeReplace() should have written a replacement
+    throw new InvalidObjectException("Deserialization is unsupported");
+  }
+
   @Override
   public int hashCode() {
     return value.hashCode();
diff --git a/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java b/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java
index b2707c5..0cade0d 100644
--- a/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java
+++ b/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java
@@ -17,6 +17,9 @@
 
 package com.google.gson.internal;
 
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.util.AbstractMap;
@@ -861,4 +864,9 @@ public final class LinkedHashTreeMap<K, V> extends AbstractMap<K, V> implements
   private Object writeReplace() throws ObjectStreamException {
     return new LinkedHashMap<K, V>(this);
   }
+
+  private void readObject(ObjectInputStream in) throws IOException {
+    // Don't permit directly deserializing this class; writeReplace() should have written a replacement
+    throw new InvalidObjectException("Deserialization is unsupported");
+  }
 }
diff --git a/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java b/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java
index 8046274..aaa8ce0 100644
--- a/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java
+++ b/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java
@@ -17,6 +17,9 @@
 
 package com.google.gson.internal;
 
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.util.AbstractMap;
@@ -627,4 +630,9 @@ public final class LinkedTreeMap<K, V> extends AbstractMap<K, V> implements Seri
   private Object writeReplace() throws ObjectStreamException {
     return new LinkedHashMap<K, V>(this);
   }
+
+  private void readObject(ObjectInputStream in) throws IOException {
+    // Don't permit directly deserializing this class; writeReplace() should have written a replacement
+    throw new InvalidObjectException("Deserialization is unsupported");
+  }
 }
diff --git a/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java
index f108fa0..75e77bb 100644
--- a/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java
+++ b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java
@@ -15,6 +15,13 @@
  */
 package com.google.gson.internal;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.math.BigDecimal;
+
 import junit.framework.TestCase;
 
 public class LazilyParsedNumberTest extends TestCase {
@@ -29,4 +36,15 @@ public class LazilyParsedNumberTest extends TestCase {
     LazilyParsedNumber n1Another = new LazilyParsedNumber("1");
     assertTrue(n1.equals(n1Another));
   }
+
+  public void testJavaSerialization() throws IOException, ClassNotFoundException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream objOut = new ObjectOutputStream(out);
+    objOut.writeObject(new LazilyParsedNumber("123"));
+    objOut.close();
+
+    ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+    Number deserialized = (Number) objIn.readObject();
+    assertEquals(new BigDecimal("123"), deserialized);
+  }
 }
diff --git a/gson/src/test/java/com/google/gson/internal/LinkedHashTreeMapTest.java b/gson/src/test/java/com/google/gson/internal/LinkedHashTreeMapTest.java
index 2aeeeb7..77fe518 100644
--- a/gson/src/test/java/com/google/gson/internal/LinkedHashTreeMapTest.java
+++ b/gson/src/test/java/com/google/gson/internal/LinkedHashTreeMapTest.java
@@ -20,8 +20,15 @@ import com.google.gson.common.MoreAsserts;
 import com.google.gson.internal.LinkedHashTreeMap.AvlBuilder;
 import com.google.gson.internal.LinkedHashTreeMap.AvlIterator;
 import com.google.gson.internal.LinkedHashTreeMap.Node;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Random;
@@ -224,6 +231,20 @@ public final class LinkedHashTreeMapTest extends TestCase {
     }
   }
 
+  public void testJavaSerialization() throws IOException, ClassNotFoundException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream objOut = new ObjectOutputStream(out);
+    Map<String, Integer> map = new LinkedHashTreeMap<String, Integer>();
+    map.put("a", 1);
+    objOut.writeObject(map);
+    objOut.close();
+
+    ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+    @SuppressWarnings("unchecked")
+    Map<String, Integer> deserialized = (Map<String, Integer>) objIn.readObject();
+    assertEquals(Collections.singletonMap("a", 1), deserialized);
+  }
+
   private static final Node<String, String> head = new Node<String, String>();
 
   private Node<String, String> node(String value) {
diff --git a/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java b/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java
index 580d25a..7f2bf9d 100644
--- a/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java
+++ b/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java
@@ -16,8 +16,14 @@
 
 package com.google.gson.internal;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Random;
@@ -147,4 +153,19 @@ public final class LinkedTreeMapTest extends TestCase {
     }
     assertEquals(Arrays.asList(expected), actualList);
   }
+
+  public void testJavaSerialization() throws IOException, ClassNotFoundException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream objOut = new ObjectOutputStream(out);
+    Map<String, Integer> map = new LinkedTreeMap<String, Integer>();
+    map.put("a", 1);
+    objOut.writeObject(map);
+    objOut.close();
+
+    ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+    @SuppressWarnings("unchecked")
+    Map<String, Integer> deserialized = (Map<String, Integer>) objIn.readObject();
+    assertEquals(Collections.singletonMap("a", 1), deserialized);
+  }
+
 }
