ldb: unpack function for new pack format
authorAaron Haslett <aaronhaslett@catalyst.net.nz>
Wed, 1 May 2019 01:36:36 +0000 (13:36 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 22 May 2019 04:42:28 +0000 (04:42 +0000)
Unpack function for new pack format with values separated from other
data so that while unpacking, the value section (which is probably large)
doesn't have to be loaded into cache/memory.
Additionally, width of length field can now vary per-element to save space.
The old unpack routine is still present and is called if the old pack
format version number is found.
LDB torture suite is modified to run relevant tests on both old and new
pack format.

NOTE: Configure with --abi-check-disable to build this commit. This
patch is part of a set of LDB ABI changes, and the version update is
done on the last commit.

Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
lib/ldb/common/ldb_pack.c
lib/ldb/include/ldb_module.h
source4/torture/ldb/ldb.c

index 4e5955ac5ede988ed08be7cd5251334f5eb1758f..21c0708ffdc1920e1066dcba5def5de2809239cb 100644 (file)
@@ -82,6 +82,8 @@
         PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16)))
 
 #define U32_LEN 4
+#define U16_LEN 2
+#define U8_LEN 1
 #define NULL_PAD_BYTE_LEN 1
 
 static int attribute_storable_values(const struct ldb_message_element *el)
@@ -213,20 +215,17 @@ int ldb_pack_data(struct ldb_context *ldb,
 
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
- *
- * Providing a list of attributes to this function allows selective unpacking.
- * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
  */
-int ldb_unpack_data_flags(struct ldb_context *ldb,
-                         const struct ldb_val *data,
-                         struct ldb_message *message,
-                         unsigned int flags)
+static int ldb_unpack_data_flags_v1(struct ldb_context *ldb,
+                                   const struct ldb_val *data,
+                                   struct ldb_message *message,
+                                   unsigned int flags,
+                                   unsigned format)
 {
        uint8_t *p;
        size_t remaining;
        size_t dn_len;
        unsigned int i, j;
-       uint32_t format;
        unsigned int nelem = 0;
        size_t len;
        struct ldb_val *ldb_val_single_array = NULL;
@@ -241,10 +240,7 @@ int ldb_unpack_data_flags(struct ldb_context *ldb,
                goto failed;
        }
 
-       if (ldb_unpack_get_format(data, &format) != LDB_SUCCESS) {
-               errno = EIO;
-               goto failed;
-       }
+       /* Skip first 4 bytes, format already read */
        p += U32_LEN;
        message->num_elements = PULL_LE_U32(p, 0);
        p += U32_LEN;
@@ -296,7 +292,6 @@ int ldb_unpack_data_flags(struct ldb_context *ldb,
                goto failed;
        }
 
-       
        if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
                return 0;
        }
@@ -448,6 +443,287 @@ failed:
        return -1;
 }
 
+/*
+ * Unpack a ldb message from a linear buffer in ldb_val
+ */
+static int ldb_unpack_data_flags_v2(struct ldb_context *ldb,
+                                   const struct ldb_val *data,
+                                   struct ldb_message *message,
+                                   unsigned int flags)
+{
+       uint8_t *p, *q, *end_p, *value_section_p;
+       unsigned int i, j;
+       unsigned int nelem = 0;
+       size_t len;
+       struct ldb_val *ldb_val_single_array = NULL;
+       uint8_t val_len_width;
+
+       message->elements = NULL;
+
+       p = data->data;
+       end_p = p + data->length;
+
+       /* Skip first 4 bytes, format already read */
+       p += U32_LEN;
+
+       /* First fields are fixed: num_elements, DN length */
+       if (p + U32_LEN * 2 > end_p) {
+               errno = EIO;
+               goto failed;
+       }
+
+       message->num_elements = PULL_LE_U32(p, 0);
+       p += U32_LEN;
+
+       len = PULL_LE_U32(p, 0);
+       p += U32_LEN;
+
+       if (p + len + NULL_PAD_BYTE_LEN > end_p) {
+               errno = EIO;
+               goto failed;
+       }
+
+       if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
+               message->dn = NULL;
+       } else {
+               struct ldb_val blob;
+               blob.data = discard_const_p(uint8_t, p);
+               blob.length = len;
+               message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
+               if (message->dn == NULL) {
+                       errno = ENOMEM;
+                       goto failed;
+               }
+       }
+
+       p += len + NULL_PAD_BYTE_LEN;
+
+       if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
+               errno = EINVAL;
+               goto failed;
+       }
+
+       /* Now skip the canonicalized DN and its length */
+       len = PULL_LE_U32(p, 0) + NULL_PAD_BYTE_LEN;
+       p += U32_LEN;
+
+       if (p + len > end_p) {
+               errno = EIO;
+               goto failed;
+       }
+
+       p += len;
+
+       if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
+               errno = EINVAL;
+               goto failed;
+       }
+
+       if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
+               return 0;
+       }
+
+       if (message->num_elements == 0) {
+               return 0;
+       }
+
+       /*
+        * Sanity check (17 bytes is the minimum element size)
+        */
+       if (message->num_elements > (end_p - p) / 17) {
+               errno = EIO;
+               goto failed;
+       }
+
+       message->elements = talloc_zero_array(message,
+                                             struct ldb_message_element,
+                                             message->num_elements);
+       if (!message->elements) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       /*
+        * In typical use, most values are single-valued.  This makes
+        * it quite expensive to allocate an array of ldb_val for each
+        * of these, just to then hold the pointer to the data buffer.
+        * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
+        * ahead of time and use it for the single values where possible.
+        * (This is used the the normal search case, but not in the
+        * index case because of caller requirements).
+        */
+       if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
+               ldb_val_single_array = talloc_array(message->elements,
+                                                   struct ldb_val,
+                                                   message->num_elements);
+               if (ldb_val_single_array == NULL) {
+                       errno = ENOMEM;
+                       goto failed;
+               }
+       }
+
+       q = p + PULL_LE_U32(p, 0);
+       value_section_p = q;
+       p += U32_LEN;
+
+       for (i=0;i<message->num_elements;i++) {
+               const char *attr = NULL;
+               size_t attr_len;
+               struct ldb_message_element *element = NULL;
+
+               /* Sanity check: minimum element size */
+               if (p + (U32_LEN * 2) + /* attr name len, num values */
+                       (U8_LEN * 2) + /* value length width, one val length */
+                       (NULL_PAD_BYTE_LEN * 2) /* null for attr name + val */
+                       > value_section_p) {
+                       errno = EIO;
+                       goto failed;
+               }
+
+               attr_len = PULL_LE_U32(p, 0);
+               p += U32_LEN;
+
+               if (attr_len == 0) {
+                       errno = EIO;
+                       goto failed;
+               }
+               attr = (char *)p;
+
+               p += attr_len + NULL_PAD_BYTE_LEN;
+               /*
+                * num_values, val_len_width
+                *
+                * val_len_width is the width specifier
+                * for the variable length encoding
+                */
+               if (p + U32_LEN + U8_LEN > value_section_p) {
+                       errno = EIO;
+                       goto failed;
+               }
+
+               if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
+                       errno = EINVAL;
+                       goto failed;
+               }
+
+               element = &message->elements[nelem];
+               element->name = attr;
+               element->flags = 0;
+
+               element->num_values = PULL_LE_U32(p, 0);
+               element->values = NULL;
+               if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) &&
+                   element->num_values == 1) {
+                       element->values = &ldb_val_single_array[nelem];
+               } else if (element->num_values != 0) {
+                       element->values = talloc_array(message->elements,
+                                                      struct ldb_val,
+                                                      element->num_values);
+                       if (!element->values) {
+                               errno = ENOMEM;
+                               goto failed;
+                       }
+               }
+
+               p += U32_LEN;
+
+               /*
+                * Here we read how wide the remaining lengths are
+                * which avoids storing and parsing a lot of leading
+                * 0s
+                */
+               val_len_width = *p;
+               p += U8_LEN;
+
+               if (p + val_len_width * element->num_values >
+                   value_section_p) {
+                       errno = EIO;
+                       goto failed;
+               }
+
+               /*
+                * This is structured weird for compiler optimization
+                * purposes, but we need to pull the array of widths
+                * with different macros depending on how wide the
+                * biggest one is (specified by val_len_width)
+                */
+               if (val_len_width == U8_LEN) {
+                       for (j = 0; j < element->num_values; j++) {
+                               element->values[j].length = PULL_LE_U8(p, 0);
+                               p += U8_LEN;
+                       }
+               } else if (val_len_width == U16_LEN) {
+                       for (j = 0; j < element->num_values; j++) {
+                               element->values[j].length = PULL_LE_U16(p, 0);
+                               p += U16_LEN;
+                       }
+               } else if (val_len_width == U32_LEN) {
+                       for (j = 0; j < element->num_values; j++) {
+                               element->values[j].length = PULL_LE_U32(p, 0);
+                               p += U32_LEN;
+                       }
+               } else {
+                       errno = ERANGE;
+                       goto failed;
+               }
+
+               for (j = 0; j < element->num_values; j++) {
+                       len = element->values[j].length;
+                       if (len + NULL_PAD_BYTE_LEN < len) {
+                               errno = EIO;
+                               goto failed;
+                       }
+                       if (q + len + NULL_PAD_BYTE_LEN > end_p) {
+                               errno = EIO;
+                               goto failed;
+                       }
+
+                       element->values[j].data = q;
+                       q += len + NULL_PAD_BYTE_LEN;
+               }
+               nelem++;
+       }
+
+       /*
+        * If p isn't now pointing at the beginning of the value section,
+        * something went very wrong.
+        */
+       if (p != value_section_p) {
+               ldb_debug(ldb, LDB_DEBUG_ERROR,
+                         "Error: Data corruption in ldb_unpack_data_flags");
+               errno = EIO;
+               goto failed;
+       }
+
+       /*
+        * Adapt the number of elements to the real number of unpacked
+        * elements it means that we overallocated elements array.
+        */
+       message->num_elements = nelem;
+
+       /*
+        * Shrink the allocated size.  On current talloc behaviour
+        * this will help if we skipped 32 or more attributes.
+        */
+       message->elements = talloc_realloc(message, message->elements,
+                                          struct ldb_message_element,
+                                          message->num_elements);
+
+       if (q != end_p) {
+               ldb_debug(ldb, LDB_DEBUG_ERROR,
+                         "Error: %zu bytes unread in ldb_unpack_data_flags",
+                         end_p - q);
+               errno = EIO;
+               goto failed;
+       }
+
+       return 0;
+
+failed:
+       talloc_free(message->elements);
+       return -1;
+}
+
 int ldb_unpack_get_format(const struct ldb_val *data,
                          uint32_t *pack_format_version)
 {
@@ -458,6 +734,36 @@ int ldb_unpack_get_format(const struct ldb_val *data,
        return LDB_SUCCESS;
 }
 
+/*
+ * Unpack a ldb message from a linear buffer in ldb_val
+ */
+int ldb_unpack_data_flags(struct ldb_context *ldb,
+                         const struct ldb_val *data,
+                         struct ldb_message *message,
+                         unsigned int flags)
+{
+       unsigned format;
+
+       if (data->length < U32_LEN) {
+               errno = EIO;
+               return -1;
+       }
+
+       format = PULL_LE_U32(data->data, 0);
+       if (format == LDB_PACKING_FORMAT_V2) {
+               return ldb_unpack_data_flags_v2(ldb, data, message, flags);
+       }
+
+       /*
+        * The v1 function we're about to call takes either LDB_PACKING_FORMAT
+        * or LDB_PACKING_FORMAT_NODN packing format versions, and will error
+        * if given some other version, so we don't need to do any further
+        * checks on 'format'.
+        */
+       return ldb_unpack_data_flags_v1(ldb, data, message, flags, format);
+}
+
+
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
  *
index d9114e99e3435a976fff44549ce934fcd7d605e7..db80b28fcfa3ddfc0fb0f1d9de53a66d4e645e3e 100644 (file)
@@ -555,6 +555,7 @@ int ldb_unpack_get_format(const struct ldb_val *data,
 
 /* In-use packing formats */
 #define LDB_PACKING_FORMAT 0x26011967
+#define LDB_PACKING_FORMAT_V2 0x26011968
 
 /* Old packing formats */
 #define LDB_PACKING_FORMAT_NODN 0x26011966
index bc3d0ac4b1a5c5346e6e10ca019fba2cdae6bc26..ba59b025e9fdee8c2c17c255b0195649c2509ce4 100644 (file)
@@ -49,7 +49,7 @@ static const char *prefix_map_semi = "2:1.2.840.113556.1.2;5:2.16.840.1.101.2.2.
  *   -- adrianc
  */
 
-static const uint8_t dda1d01d_bin[] = {
+static const uint8_t dda1d01d_bin_v1[] = {
        0x67, 0x19, 0x01, 0x26, 0x0d, 0x00, 0x00, 0x00, 0x43, 0x4e, 0x3d, 0x64, 0x64, 0x61, 0x31, 0x64,
        0x30, 0x31, 0x64, 0x2d, 0x34, 0x62, 0x64, 0x37, 0x2d, 0x34, 0x63, 0x34, 0x39, 0x2d, 0x61, 0x31,
        0x38, 0x34, 0x2d, 0x34, 0x36, 0x66, 0x39, 0x32, 0x34, 0x31, 0x62, 0x35, 0x36, 0x30, 0x65, 0x2c,
@@ -202,6 +202,167 @@ static const uint8_t dda1d01d_bin[] = {
        0x00
 };
 
+static const uint8_t dda1d01d_bin_v2[] = {
+       0x68, 0x19, 0x01, 0x26, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x43, 0x4e, 0x3d, 0x64,
+       0x64, 0x61, 0x31, 0x64, 0x30, 0x31, 0x64, 0x2d, 0x34, 0x62, 0x64, 0x37, 0x2d, 0x34, 0x63, 0x34,
+       0x39, 0x2d, 0x61, 0x31, 0x38, 0x34, 0x2d, 0x34, 0x36, 0x66, 0x39, 0x32, 0x34, 0x31, 0x62, 0x35,
+       0x36, 0x30, 0x65, 0x2c, 0x43, 0x4e, 0x3d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+       0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74,
+       0x65, 0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x44, 0x43, 0x3d,
+       0x61, 0x64, 0x64, 0x63, 0x2c, 0x44, 0x43, 0x3d, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x2c, 0x44, 0x43,
+       0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x44, 0x43, 0x3d, 0x63, 0x6f, 0x6d, 0x00,
+       0x5b, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x63, 0x2e, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x2e, 0x65,
+       0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x79, 0x73, 0x74, 0x65,
+       0x6d, 0x2f, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x2f,
+       0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x64, 0x64, 0x61, 0x31, 0x64,
+       0x30, 0x31, 0x64, 0x2d, 0x34, 0x62, 0x64, 0x37, 0x2d, 0x34, 0x63, 0x34, 0x39, 0x2d, 0x61, 0x31,
+       0x38, 0x34, 0x2d, 0x34, 0x36, 0x66, 0x39, 0x32, 0x34, 0x31, 0x62, 0x35, 0x36, 0x30, 0x65, 0x00,
+       0x33, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c,
+       0x61, 0x73, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x03, 0x09, 0x02, 0x00, 0x00, 0x00, 0x63,
+       0x6e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x24, 0x0c, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x73, 0x74,
+       0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0b,
+       0x00, 0x00, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x00, 0x01,
+       0x00, 0x00, 0x00, 0x01, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x43, 0x68, 0x61,
+       0x6e, 0x67, 0x65, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x75,
+       0x53, 0x4e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04,
+       0x0a, 0x00, 0x00, 0x00, 0x75, 0x53, 0x4e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x00, 0x01,
+       0x00, 0x00, 0x00, 0x01, 0x04, 0x16, 0x00, 0x00, 0x00, 0x73, 0x68, 0x6f, 0x77, 0x49, 0x6e, 0x41,
+       0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x56, 0x69, 0x65, 0x77, 0x4f, 0x6e, 0x6c, 0x79, 0x00,
+       0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0x00, 0x00, 0x6e, 0x54, 0x53, 0x65, 0x63, 0x75,
+       0x72, 0x69, 0x74, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x00, 0x01,
+       0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x04, 0x00, 0x00, 0x00, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x01,
+       0x00, 0x00, 0x00, 0x01, 0x24, 0x0a, 0x00, 0x00, 0x00, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x47,
+       0x55, 0x49, 0x44, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x14, 0x00, 0x00, 0x00, 0x72, 0x65,
+       0x70, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61,
+       0x74, 0x61, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x90, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x6f, 0x62,
+       0x6a, 0x65, 0x63, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x01, 0x76, 0x74, 0x6f, 0x70, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
+       0x00, 0x64, 0x64, 0x61, 0x31, 0x64, 0x30, 0x31, 0x64, 0x2d, 0x34, 0x62, 0x64, 0x37, 0x2d, 0x34,
+       0x63, 0x34, 0x39, 0x2d, 0x61, 0x31, 0x38, 0x34, 0x2d, 0x34, 0x36, 0x66, 0x39, 0x32, 0x34, 0x31,
+       0x62, 0x35, 0x36, 0x30, 0x65, 0x00, 0x34, 0x00, 0x32, 0x30, 0x31, 0x35, 0x30, 0x37, 0x30, 0x38,
+       0x32, 0x32, 0x34, 0x33, 0x31, 0x30, 0x2e, 0x30, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x35, 0x30, 0x37,
+       0x30, 0x38, 0x32, 0x32, 0x34, 0x33, 0x31, 0x30, 0x2e, 0x30, 0x5a, 0x00, 0x33, 0x34, 0x36, 0x37,
+       0x00, 0x33, 0x34, 0x36, 0x37, 0x00, 0x54, 0x52, 0x55, 0x45, 0x00, 0x01, 0x00, 0x14, 0x8c, 0x14,
+       0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x01,
+       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x9a, 0xbd, 0x91, 0x7d, 0xd5,
+       0xe0, 0x11, 0x3c, 0x6e, 0x5e, 0x1a, 0x4b, 0x00, 0x02, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x9a, 0xbd, 0x91, 0x7d, 0xd5, 0xe0, 0x11, 0x3c, 0x6e,
+       0x5e, 0x1a, 0x4b, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x78, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07,
+       0x5a, 0x38, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xbe, 0x3b, 0x0e, 0xf3, 0xf0,
+       0x9f, 0xd1, 0x11, 0xb6, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1, 0xa5, 0x7a, 0x96, 0xbf, 0xe6,
+       0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x01, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x5a, 0x38, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03,
+       0x00, 0x00, 0x00, 0xbf, 0x3b, 0x0e, 0xf3, 0xf0, 0x9f, 0xd1, 0x11, 0xb6, 0x03, 0x00, 0x00, 0xf8,
+       0x03, 0x67, 0xc1, 0xa5, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00,
+       0x30, 0x49, 0xe2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,
+       0x00, 0x54, 0x04, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01,
+       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x9a, 0xbd, 0x91, 0x7d, 0xd5,
+       0xe0, 0x11, 0x3c, 0x6e, 0x5e, 0x1a, 0x4b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xff,
+       0x01, 0x0f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x14, 0x00, 0x94, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0b,
+       0x00, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+       0x42, 0x16, 0x4c, 0xc0, 0x20, 0xd0, 0x11, 0xa7, 0x68, 0x00, 0xaa, 0x00, 0x6e, 0x05, 0x29, 0x14,
+       0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b, 0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01,
+       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05,
+       0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x16, 0x4c, 0xc0,
+       0x20, 0xd0, 0x11, 0xa7, 0x68, 0x00, 0xaa, 0x00, 0x6e, 0x05, 0x29, 0xba, 0x7a, 0x96, 0xbf, 0xe6,
+       0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10,
+       0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x5f, 0xa5, 0x79, 0xd0, 0x11, 0x90,
+       0x20, 0x00, 0xc0, 0x4f, 0xc2, 0xd4, 0xcf, 0x14, 0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b,
+       0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20,
+       0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03,
+       0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x5f, 0xa5, 0x79, 0xd0, 0x11, 0x90, 0x20, 0x00, 0xc0, 0x4f,
+       0xc2, 0xd4, 0xcf, 0xba, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00,
+       0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a,
+       0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40,
+       0xc2, 0x0a, 0xbc, 0xa9, 0x79, 0xd0, 0x11, 0x90, 0x20, 0x00, 0xc0, 0x4f, 0xc2, 0xd4, 0xcf, 0x14,
+       0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b, 0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01,
+       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05,
+       0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0xc2, 0x0a, 0xbc, 0xa9,
+       0x79, 0xd0, 0x11, 0x90, 0x20, 0x00, 0xc0, 0x4f, 0xc2, 0xd4, 0xcf, 0xba, 0x7a, 0x96, 0xbf, 0xe6,
+       0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10,
+       0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x42, 0x2f, 0xba, 0x59, 0xa2, 0x79, 0xd0, 0x11, 0x90,
+       0x20, 0x00, 0xc0, 0x4f, 0xc2, 0xd3, 0xcf, 0x14, 0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b,
+       0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20,
+       0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03,
+       0x00, 0x00, 0x00, 0x42, 0x2f, 0xba, 0x59, 0xa2, 0x79, 0xd0, 0x11, 0x90, 0x20, 0x00, 0xc0, 0x4f,
+       0xc2, 0xd3, 0xcf, 0xba, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00,
+       0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a,
+       0x02, 0x00, 0x00, 0x05, 0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8,
+       0x88, 0x70, 0x03, 0xe1, 0x0a, 0xd2, 0x11, 0xb4, 0x22, 0x00, 0xa0, 0xc9, 0x68, 0xf9, 0x39, 0x14,
+       0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b, 0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01,
+       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05,
+       0x1a, 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x88, 0x70, 0x03, 0xe1,
+       0x0a, 0xd2, 0x11, 0xb4, 0x22, 0x00, 0xa0, 0xc9, 0x68, 0xf9, 0x39, 0xba, 0x7a, 0x96, 0xbf, 0xe6,
+       0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x38, 0x00, 0x10,
+       0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6d, 0x9e, 0xc6, 0xb7, 0xc7, 0x2c, 0xd2, 0x11, 0x85,
+       0x4e, 0x00, 0xa0, 0xc9, 0x83, 0xf6, 0x08, 0x86, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2,
+       0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09,
+       0x00, 0x00, 0x00, 0x05, 0x1a, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6d,
+       0x9e, 0xc6, 0xb7, 0xc7, 0x2c, 0xd2, 0x11, 0x85, 0x4e, 0x00, 0xa0, 0xc9, 0x83, 0xf6, 0x08, 0x9c,
+       0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x05, 0x1a, 0x38, 0x00, 0x10,
+       0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6d, 0x9e, 0xc6, 0xb7, 0xc7, 0x2c, 0xd2, 0x11, 0x85,
+       0x4e, 0x00, 0xa0, 0xc9, 0x83, 0xf6, 0x08, 0xba, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2,
+       0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09,
+       0x00, 0x00, 0x00, 0x05, 0x1a, 0x2c, 0x00, 0x94, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14,
+       0xcc, 0x28, 0x48, 0x37, 0x14, 0xbc, 0x45, 0x9b, 0x07, 0xad, 0x6f, 0x01, 0x5e, 0x5f, 0x28, 0x01,
+       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05,
+       0x1a, 0x2c, 0x00, 0x94, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9c, 0x7a, 0x96, 0xbf, 0xe6,
+       0x0d, 0xd0, 0x11, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x1a, 0x2c, 0x00, 0x94,
+       0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0xba, 0x7a, 0x96, 0xbf, 0xe6, 0x0d, 0xd0, 0x11, 0xa2,
+       0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20,
+       0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x05, 0x12, 0x28, 0x00, 0x30, 0x01, 0x00, 0x00, 0x01,
+       0x00, 0x00, 0x00, 0xde, 0x47, 0xe6, 0x91, 0x6f, 0xd9, 0x70, 0x4b, 0x95, 0x57, 0xd6, 0x3f, 0xf4,
+       0xf3, 0xcc, 0xd8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x00, 0x00, 0x00, 0x00,
+       0x12, 0x24, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15,
+       0x00, 0x00, 0x00, 0x9a, 0xbd, 0x91, 0x7d, 0xd5, 0xe0, 0x11, 0x3c, 0x6e, 0x5e, 0x1a, 0x4b, 0x07,
+       0x02, 0x00, 0x00, 0x00, 0x12, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x00, 0x12, 0x18, 0x00, 0xbd,
+       0x01, 0x0f, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20,
+       0x02, 0x00, 0x00, 0x00, 0x64, 0x64, 0x61, 0x31, 0x64, 0x30, 0x31, 0x64, 0x2d, 0x34, 0x62, 0x64,
+       0x37, 0x2d, 0x34, 0x63, 0x34, 0x39, 0x2d, 0x61, 0x31, 0x38, 0x34, 0x2d, 0x34, 0x36, 0x66, 0x39,
+       0x32, 0x34, 0x31, 0x62, 0x35, 0x36, 0x30, 0x65, 0x00, 0x57, 0x93, 0x1e, 0x29, 0x25, 0x49, 0xe5,
+       0x40, 0x9d, 0x98, 0x36, 0x07, 0x11, 0x9e, 0xbd, 0xe5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x02, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x01, 0x02, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x03, 0x09, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
+       0x00, 0x00, 0x7e, 0x38, 0xae, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x9d, 0xcd, 0xcd, 0x57, 0xee, 0x58,
+       0x6e, 0x4e, 0x96, 0x99, 0xcc, 0x7d, 0xe1, 0x96, 0xf1, 0x05, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x47, 0x55, 0x49, 0x44,
+       0x3d, 0x35, 0x32, 0x34, 0x32, 0x39, 0x30, 0x33, 0x38, 0x2d, 0x65, 0x34, 0x33, 0x35, 0x2d, 0x34,
+       0x66, 0x65, 0x33, 0x2d, 0x39, 0x36, 0x34, 0x65, 0x2d, 0x38, 0x30, 0x64, 0x61, 0x31, 0x35, 0x34,
+       0x39, 0x39, 0x63, 0x39, 0x63, 0x3e, 0x3b, 0x43, 0x4e, 0x3d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+       0x6e, 0x65, 0x72, 0x2c, 0x43, 0x4e, 0x3d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2c, 0x43, 0x4e,
+       0x3d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x44,
+       0x43, 0x3d, 0x61, 0x64, 0x64, 0x63, 0x2c, 0x44, 0x43, 0x3d, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x2c,
+       0x44, 0x43, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x44, 0x43, 0x3d, 0x63, 0x6f,
+       0x6d, 0x00
+};
+
 static const char dda1d01d_ldif[] = ""
 "dn: CN=dda1d01d-4bd7-4c49-a184-46f9241b560e,CN=Operations,CN=DomainUpdates,CN=System,DC=addc,DC=samba,DC=example,DC=com\n"
 "objectClass: top\n"
@@ -1076,11 +1237,12 @@ static bool helper_ldb_message_compare(struct torture_context *torture,
        return true;
 }
 
-static bool torture_ldb_unpack(struct torture_context *torture)
+static bool torture_ldb_unpack(struct torture_context *torture,
+                              const void *data_p)
 {
        TALLOC_CTX *mem_ctx = talloc_new(torture);
        struct ldb_context *ldb;
-       struct ldb_val data = data_blob_const(dda1d01d_bin, sizeof(dda1d01d_bin));
+       struct ldb_val data = *discard_const_p(struct ldb_val, data_p);
        struct ldb_message *msg = ldb_msg_new(mem_ctx);
        const char *ldif_text = dda1d01d_ldif;
        struct ldb_ldif ldif;
@@ -1103,11 +1265,12 @@ static bool torture_ldb_unpack(struct torture_context *torture)
        return true;
 }
 
-static bool torture_ldb_unpack_flags(struct torture_context *torture)
+static bool torture_ldb_unpack_flags(struct torture_context *torture,
+                                    const void *data_p)
 {
        TALLOC_CTX *mem_ctx = talloc_new(torture);
        struct ldb_context *ldb;
-       struct ldb_val data = data_blob_const(dda1d01d_bin, sizeof(dda1d01d_bin));
+       struct ldb_val data = *discard_const_p(struct ldb_val, data_p);
        struct ldb_message *msg = ldb_msg_new(mem_ctx);
        const char *ldif_text = dda1d01d_ldif;
        struct ldb_ldif ldif;
@@ -1144,14 +1307,79 @@ static bool torture_ldb_unpack_flags(struct torture_context *torture)
        return true;
 }
 
-static bool torture_ldb_parse_ldif(struct torture_context *torture)
+static bool torture_ldb_unpack_data_corrupt(struct torture_context *torture)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(torture);
+       struct ldb_context *ldb;
+
+       uint8_t bin[] = {0x68, 0x19, 0x01, 0x26, /* version */
+               1, 0, 0, 0, /* num elements */
+               4, 0, 0, 0, /* dn length */
+               'D', 'N', '=', 'A', 0, /* dn with null term */
+               2, 0, 0, 0, /* canonicalized dn length */
+               '/', 'A', 0, /* canonicalized dn with null term */
+               18, 0, 0, 0, /* size of name and sizes section + 4 (this field) */
+               3, 0, 0, 0, /* el name length */
+               'a', 'b', 'c', 0, /* name with null term */
+               1, 0, 0, 0, 1, /* num values and length width */
+               1, /* value lengths */
+               '1', 0}; /* values for abc */
+
+       struct ldb_val binary = data_blob_const(bin, sizeof(bin));
+       struct ldb_val bin_copy;
+       struct ldb_message *msg;
+
+       int i, j, current, expect_rcode, ret;
+       const char *comment;
+       const char *comment_fmt = "Expected unpack rcode for index %d "
+                                 "(corrupt bytes index %d) "
+                                 "to be %d but got %d";
+
+       /*
+        * List of corruptible byte ranges. First 12 bytes are corruptible,
+        * next 4 bytes are not, next 5 bytes are corruptible, etc.
+        */
+       uint8_t corrupt_bytes[] = {12, 4, 5, 2, 9, 3, 7, 2};
+
+       ldb = samba_ldb_init(mem_ctx, torture->ev, NULL,NULL,NULL);
+       torture_assert(torture, ldb != NULL, "Failed to init ldb");
+
+       current = 0;
+       for (i=0; i<sizeof(corrupt_bytes); i++) {
+               expect_rcode = i % 2 == 0 ? -1 : 0;
+
+               for (j=0; j<corrupt_bytes[i]; j++, current++) {
+                       bin_copy.data = talloc_size(NULL, binary.length);
+                       memcpy(bin_copy.data, binary.data, binary.length);
+                       bin_copy.length = binary.length;
+                       msg = ldb_msg_new(bin_copy.data);
+
+                       bin_copy.data[current]++;
+
+                       ret = ldb_unpack_data(ldb, &bin_copy, msg);
+
+                       comment = talloc_asprintf(bin_copy.data, comment_fmt,
+                                                 current, i,
+                                                 expect_rcode, ret);
+                       torture_assert_int_equal(torture, ret, expect_rcode,
+                                                comment);
+
+                       talloc_free(bin_copy.data);
+               }
+       }
+
+       return true;
+}
+
+static bool torture_ldb_parse_ldif(struct torture_context *torture,
+                                  const void *data_p)
 {
        TALLOC_CTX *mem_ctx = talloc_new(torture);
        const char *ldif_text = dda1d01d_ldif;
        struct ldb_context *ldb;
        struct ldb_ldif *ldif;
        struct ldb_val binary;
-       struct ldb_val data = data_blob_const(dda1d01d_bin, sizeof(dda1d01d_bin));
+       struct ldb_val data = *discard_const_p(struct ldb_val, data_p);
        struct ldb_message *msg = ldb_msg_new(mem_ctx);
 
        ldb = samba_ldb_init(mem_ctx, torture->ev, NULL,NULL,NULL);
@@ -1255,11 +1483,12 @@ static bool torture_ldb_pack_format_perf(struct torture_context *torture)
        return true;
 }
 
-static bool torture_ldb_unpack_and_filter(struct torture_context *torture)
+static bool torture_ldb_unpack_and_filter(struct torture_context *torture,
+                                         const void *data_p)
 {
        TALLOC_CTX *mem_ctx = talloc_new(torture);
        struct ldb_context *ldb;
-       struct ldb_val data = data_blob_const(dda1d01d_bin, sizeof(dda1d01d_bin));
+       struct ldb_val data = *discard_const_p(struct ldb_val, data_p);
        struct ldb_message *unpack_msg = ldb_msg_new(mem_ctx);
        struct ldb_message *msg = ldb_msg_new(mem_ctx);
        const char *lookup_names[] = {"instanceType", "nonexistant",
@@ -1375,12 +1604,17 @@ static bool torture_ldb_unpack_and_filter(struct torture_context *torture)
 
 struct torture_suite *torture_ldb(TALLOC_CTX *mem_ctx)
 {
+       int i;
+       struct ldb_val *bins = talloc_array(NULL, struct ldb_val, 2);
        struct torture_suite *suite = torture_suite_create(mem_ctx, "ldb");
 
        if (suite == NULL) {
                return NULL;
        }
 
+       bins[0] = data_blob_const(dda1d01d_bin_v1, sizeof(dda1d01d_bin_v1));
+       bins[1] = data_blob_const(dda1d01d_bin_v2, sizeof(dda1d01d_bin_v2));
+
        torture_suite_add_simple_test(suite, "attrs", torture_ldb_attrs);
        torture_suite_add_simple_test(suite, "dn-attrs", torture_ldb_dn_attrs);
        torture_suite_add_simple_test(suite, "dn-extended",
@@ -1388,16 +1622,26 @@ struct torture_suite *torture_ldb(TALLOC_CTX *mem_ctx)
        torture_suite_add_simple_test(suite, "dn-invalid-extended",
                                      torture_ldb_dn_invalid_extended);
        torture_suite_add_simple_test(suite, "dn", torture_ldb_dn);
-       torture_suite_add_simple_test(suite, "unpack-data",
-                                     torture_ldb_unpack);
-       torture_suite_add_simple_test(suite, "unpack-data-flags",
-                                     torture_ldb_unpack_flags);
-       torture_suite_add_simple_test(suite, "parse-ldif",
-                                     torture_ldb_parse_ldif);
-       torture_suite_add_simple_test(suite, "unpack-and-filter",
-                                     torture_ldb_unpack_and_filter);
        torture_suite_add_simple_test(suite, "pack-format-perf",
                                      torture_ldb_pack_format_perf);
+       torture_suite_add_simple_test(suite, "unpack-corrupt-v2",
+                                     torture_ldb_unpack_data_corrupt);
+
+       for (i=0; i<2; i++) {
+               torture_suite_add_simple_tcase_const(suite,
+                       talloc_asprintf(mem_ctx, "unpack-data-v%d", i+1),
+                       torture_ldb_unpack, &bins[i]);
+               torture_suite_add_simple_tcase_const(suite,
+                       talloc_asprintf(mem_ctx, "unpack-data-flags-v%d", i+1),
+                       torture_ldb_unpack_flags, &bins[i]);
+               torture_suite_add_simple_tcase_const(suite,
+                       talloc_asprintf(mem_ctx, "parse-ldif-v%d", i+1),
+                       torture_ldb_parse_ldif, &bins[i]);
+               torture_suite_add_simple_tcase_const(suite,
+                       talloc_asprintf(mem_ctx,
+                                       "unpack-data-and-filter-v%d", i+1),
+                       torture_ldb_unpack_and_filter, &bins[i]);
+       }
 
        suite->description = talloc_strdup(suite, "LDB (samba-specific behaviour) tests");