diff --git a/CHANGES b/CHANGES
index e36100401d6f3ae3f01427cf0945bfaa9d8f09bb..06a1386a9349d99a199467138fa9f61ea1b94669 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@ OpenLDAP 2.4 Change Log
 
 OpenLDAP 2.4.25 Engineering
 	Fixed slapd add objectclasses in order (ITS#6837)
+	Fixed slapd sortval handling (ITS#6845)
 	Fixed slapd-ldap chain cn=config support (ITS#6837)
 	Fixed slapd-meta deadlock (ITS#6846)
 	Build Environment
diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 76bd732123bdf1160c26e2ace30b78e251ef61e5..c69ccefd6c1dadd1c5faff0f596fa1bbce40eaed 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -500,9 +500,6 @@ slap_mods2entry(
 		} else {
 			attr->a_nvals = attr->a_vals;
 		}
-		/* slap_mods_check() gives us sorted results */
-		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
-			attr->a_flags |= SLAP_ATTR_SORTED_VALS;
 
 		*tail = attr;
 		tail = &attr->a_next;
diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c
index fe2eded94ab796382ce23a1d3fced42ceae4d608..51f50758fcef64af13444d83e73127ebdaacf357 100644
--- a/servers/slapd/attr.c
+++ b/servers/slapd/attr.c
@@ -88,6 +88,8 @@ attr_alloc( AttributeDescription *ad )
 	ldap_pvt_thread_mutex_unlock( &attr_mutex );
 	
 	a->a_desc = ad;
+	if ( ad && ( ad->ad_type->sat_flags & SLAP_AT_SORTED_VAL ))
+		a->a_flags |= SLAP_ATTR_SORTED_VALS;
 
 	return a;
 }
diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c
index b419db0af11e3cb4203ee97e65822f65b2a1dfdd..fb38f2df9fd782f303c0bf1d5a9260bf1b488d55 100644
--- a/servers/slapd/back-bdb/modify.c
+++ b/servers/slapd/back-bdb/modify.c
@@ -289,31 +289,23 @@ int bdb_modify_internal(
 			if ( a2 ) {
 				/* need to detect which values were deleted */
 				int i, j;
-				struct berval tmp;
-				j = ap->a_numvals;
-				for ( i=0; i<j; ) {
+				vals = op->o_tmpalloc( (ap->a_numvals + 1) *
+					sizeof(struct berval), op->o_tmpmemctx );
+				j = 0;
+				for ( i=0; i < ap->a_numvals; i++ ) {
 					rc = attr_valfind( a2, SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 						&ap->a_nvals[i], NULL, op->o_tmpmemctx );
-					/* Move deleted values to end of array */
-					if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
-						j--;
-						if ( i != j ) {
-							tmp = ap->a_nvals[j];
-							ap->a_nvals[j] = ap->a_nvals[i];
-							ap->a_nvals[i] = tmp;
-							tmp = ap->a_vals[j];
-							ap->a_vals[j] = ap->a_vals[i];
-							ap->a_vals[i] = tmp;
-						}
-						continue;
-					}
+					/* Save deleted values */
+					if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
+						vals[j++] = ap->a_nvals[i];
 					i++;
 				}
-				vals = &ap->a_nvals[j];
+				BER_BVZERO(vals+j);
 			} else {
 				/* attribute was completely deleted */
 				vals = ap->a_nvals;
 			}
+			rc = 0;
 			if ( !BER_BVISNULL( vals )) {
 				rc = bdb_index_values( op, tid, ap->a_desc,
 					vals, e->e_id, SLAP_INDEX_DELETE_OP );
@@ -323,9 +315,11 @@ int bdb_modify_internal(
 						op->o_log_prefix, ap->a_desc->ad_cname.bv_val, 0 );
 					attrs_free( e->e_attrs );
 					e->e_attrs = save_attrs;
-					return rc;
 				}
 			}
+			if ( vals != ap->a_nvals )
+				op->o_tmpfree( vals, op->o_tmpmemctx );
+			if ( rc ) return rc;
 		}
 	}