bdd565
From 7f5ac2097be424a55248e391c6b40635d01b1fa6 Mon Sep 17 00:00:00 2001
bdd565
From: Pierre Rogier <progier@redhat.com>
bdd565
Date: Wed, 17 Apr 2024 18:18:04 +0200
bdd565
Subject: [PATCH] CVE-2024-3657-7.9
bdd565
bdd565
---
bdd565
 ldap/servers/slapd/back-ldbm/index.c | 111 ++++++++++++++-------------
bdd565
 1 file changed, 59 insertions(+), 52 deletions(-)
bdd565
bdd565
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
bdd565
index f0b969ff4..53a041ad1 100644
bdd565
--- a/ldap/servers/slapd/back-ldbm/index.c
bdd565
+++ b/ldap/servers/slapd/back-ldbm/index.c
bdd565
@@ -71,6 +71,32 @@ typedef struct _index_buffer_handle index_buffer_handle;
bdd565
 #define INDEX_BUFFER_FLAG_SERIALIZE 1
bdd565
 #define INDEX_BUFFER_FLAG_STATS 2
bdd565
 
bdd565
+/*
bdd565
+ * space needed to encode a byte:
bdd565
+ *  0x00-0x31 and 0x7f-0xff requires 3 bytes: \xx
bdd565
+ *  0x22 and 0x5C requires 2 bytes: \" and \\
bdd565
+ *  other requires 1 byte: c
bdd565
+ */
bdd565
+static char encode_size[] = {
bdd565
+    /* 0x00 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0x10 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0x20 */   1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
bdd565
+    /* 0x30 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
bdd565
+    /* 0x40 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
bdd565
+    /* 0x50 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
bdd565
+    /* 0x60 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
bdd565
+    /* 0x70 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
bdd565
+    /* 0x80 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0x90 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xA0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xB0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xC0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xD0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xE0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+    /* 0xF0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
bdd565
+};
bdd565
+
bdd565
+
bdd565
 /* Index buffering functions */
bdd565
 
bdd565
 static int
bdd565
@@ -800,65 +826,46 @@ index_add_mods(
bdd565
 
bdd565
 /*
bdd565
  * Convert a 'struct berval' into a displayable ASCII string
bdd565
+ * returns the printable string
bdd565
  */
bdd565
-
bdd565
-#define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"')
bdd565
-
bdd565
 const char *
bdd565
 encode(const struct berval *data, char buf[BUFSIZ])
bdd565
 {
bdd565
-    char *s;
bdd565
-    char *last;
bdd565
-    if (data == NULL || data->bv_len == 0)
bdd565
-        return "";
bdd565
-    last = data->bv_val + data->bv_len - 1;
bdd565
-    for (s = data->bv_val; s < last; ++s) {
bdd565
-        if (SPECIAL(*s)) {
bdd565
-            char *first = data->bv_val;
bdd565
-            char *bufNext = buf;
bdd565
-            size_t bufSpace = BUFSIZ - 4;
bdd565
-            while (1) {
bdd565
-                /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */
bdd565
-                if (bufSpace < (size_t)(s - first))
bdd565
-                    s = first + bufSpace - 1;
bdd565
-                if (s != first) {
bdd565
-                    memcpy(bufNext, first, s - first);
bdd565
-                    bufNext += (s - first);
bdd565
-                    bufSpace -= (s - first);
bdd565
-                }
bdd565
-                do {
bdd565
-                    if (bufSpace) {
bdd565
-                        *bufNext++ = '\\';
bdd565
-                        --bufSpace;
bdd565
-                    }
bdd565
-                    if (bufSpace < 2) {
bdd565
-                        memcpy(bufNext, "..", 2);
bdd565
-                        bufNext += 2;
bdd565
-                        goto bail;
bdd565
-                    }
bdd565
-                    if (*s == '\\' || *s == '"') {
bdd565
-                        *bufNext++ = *s;
bdd565
-                        --bufSpace;
bdd565
-                    } else {
bdd565
-                        sprintf(bufNext, "%02x", (unsigned)*(unsigned char *)s);
bdd565
-                        bufNext += 2;
bdd565
-                        bufSpace -= 2;
bdd565
-                    }
bdd565
-                } while (++s <= last && SPECIAL(*s));
bdd565
-                if (s > last)
bdd565
-                    break;
bdd565
-                first = s;
bdd565
-                while (!SPECIAL(*s) && s <= last)
bdd565
-                    ++s;
bdd565
-            }
bdd565
-        bail:
bdd565
-            *bufNext = '\0';
bdd565
-            /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */
bdd565
+    if (!data || !data->bv_val) {
bdd565
+        strcpy(buf, "<NULL>");
bdd565
+        return buf;
bdd565
+    }
bdd565
+    char *endbuff = &buf[BUFSIZ-4];  /* Reserve space to append "...\0" */
bdd565
+    char *ptout = buf;
bdd565
+    unsigned char *ptin = (unsigned char*) data->bv_val;
bdd565
+    unsigned char *endptin = ptin+data->bv_len;
bdd565
+
bdd565
+    while (ptin < endptin) {
bdd565
+        if (ptout >= endbuff) {
bdd565
+            /*
bdd565
+             * BUFSIZ(8K) > SLAPI_LOG_BUFSIZ(2K) so the error log message will be
bdd565
+             * truncated anyway. So there is no real interrest to test if the original
bdd565
+             * data contains no special characters and return it as is.
bdd565
+             */
bdd565
+            strcpy(endbuff, "...");
bdd565
             return buf;
bdd565
         }
bdd565
+        switch (encode_size[*ptin]) {
bdd565
+            case 1:
bdd565
+                *ptout++ = *ptin++;
bdd565
+                break;
bdd565
+            case 2:
bdd565
+                *ptout++ = '\\';
bdd565
+                *ptout++ = *ptin++;
bdd565
+                break;
bdd565
+            case 3:
bdd565
+                sprintf(ptout, "\\%02x", *ptin++);
bdd565
+                ptout += 3;
bdd565
+                break;
bdd565
+        }
bdd565
     }
bdd565
-    /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */
bdd565
-    return data->bv_val;
bdd565
+    *ptout = 0;
bdd565
+    return buf;
bdd565
 }
bdd565
 
bdd565
 static const char *
bdd565
-- 
bdd565
2.41.0
bdd565