CVE-2023-26470: Out-of-bounds Write (CWE-787)
value: XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. It's possible to make the farm unusable by adding an object to a page with a huge number (e.g. 67108863). Most of the time this will fill the memory allocated to XWiki and make it unusable every time this document is manipulated. This issue has been patched in XWiki 14.0-rc-1.

CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.5
Published: 2023-03-02T19:15Z
Repository: https://github.com/xwiki/xwiki-platform
Language: Java
Files changed: xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/doc/BaseObjects.java, xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/internal/doc/BaseObjectsTest.java
Commit date: 2022-01-11 11:23:55 +0100
Commit message: XWIKI-19223: Improve xobject memory storage in XWikidocument
* fix List#remove implementation
* override List#clear implementation for performances

Diff: diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/doc/BaseObjects.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/doc/BaseObjects.java
index 13faab26132b..1c06623e2447 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/doc/BaseObjects.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/doc/BaseObjects.java
@@ -100,11 +100,11 @@ private BaseObject put(int index, BaseObject element)
     public void add(int index, BaseObject element)
     {
         // Check if the index is valid
         rangeCheckForAdd(index);
 
-        // Move right values
+        // Shifts right values to the right
         if (index < this.size) {
             for (int i = this.size - 1; i >= index; --i) {
                 put(i + 1, get(i));
             }
         }
@@ -126,11 +126,30 @@ public BaseObject set(int index, BaseObject element)
     @Override
     public BaseObject remove(int index)
     {
         rangeCheck(index);
 
-        return this.map.remove(index);
+        BaseObject previous = this.map.remove(index);
+
+        // Shifts right values to the left
+        if (index < this.size - 1) {
+            for (int i = index; i < this.size - 1; ++i) {
+                put(i, get(i + 1));
+            }
+        }
+
+        // The list is one element shorter
+        --this.size;
+
+        return previous;
+    }
+
+    @Override
+    public void clear()
+    {
+        this.map.clear();
+        this.size = 0;
     }
 
     private void rangeCheck(int index)
     {
         if (index < 0 || index >= this.size) {
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/internal/doc/BaseObjectsTest.java b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/internal/doc/BaseObjectsTest.java
index 601c5affd004..da18b260e12f 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/internal/doc/BaseObjectsTest.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/internal/doc/BaseObjectsTest.java
@@ -118,14 +118,28 @@ void remove()
         BaseObjects objects = new BaseObjects(Arrays.asList(XOBJ1, XOBJ2, XOBJ3));
 
         assertEquals(3, objects.size());
 
         objects.remove(0);
-        objects.remove(2);
 
-        assertNull(objects.get(0));
-        assertSame(XOBJ2, objects.get(1));
-        assertNull(objects.get(2));
+        assertEquals(2, objects.size());
+        assertSame(XOBJ2, objects.get(0));
+        assertSame(XOBJ3, objects.get(1));
+
+        objects.remove(1);
+
+        assertEquals(1, objects.size());
+        assertSame(XOBJ2, objects.get(0));
+    }
+
+    @Test
+    void clear()
+    {
+        BaseObjects objects = new BaseObjects(Arrays.asList(XOBJ1, XOBJ2, XOBJ3));
 
         assertEquals(3, objects.size());
+
+        objects.clear();
+
+        assertEquals(0, objects.size());
     }
 }

Vulnerable code:         // Move right values
        return this.map.remove(index);
        objects.remove(2);
        assertNull(objects.get(0));
        assertSame(XOBJ2, objects.get(1));
        assertNull(objects.get(2));
Fixed code:         // Shifts right values to the right
        BaseObject previous = this.map.remove(index);

        // Shifts right values to the left
        if (index < this.size - 1) {
            for (int i = index; i < this.size - 1; ++i) {
                put(i, get(i + 1));
            }
        }

        // The list is one element shorter
        --this.size;

        return previous;
    }

    @Override
    public void clear()
    {
        this.map.clear();
        this.size = 0;
        assertEquals(2, objects.size());
        assertSame(XOBJ2, objects.get(0));
        assertSame(XOBJ3, objects.get(1));

        objects.remove(1);

        assertEquals(1, objects.size());
        assertSame(XOBJ2, objects.get(0));
    }

    @Test
    void clear()
    {
        BaseObjects objects = new BaseObjects(Arrays.asList(XOBJ1, XOBJ2, XOBJ3));

        objects.clear();

        assertEquals(0, objects.size());