Hello
In an overlay, I want to alter a modification operation so that modification to an attribute is not done.
I crafted the code below, which seems to work, but is it right? There are XXX places where I expected another behavior, did I miss something?
And after "Modifying the modification", I also have "Modifying an add", just below, with the same questions.
/* Modifying the modification */ static void supann_rm_mods(Modifications *mods, Modifications **mods_prevp) { Modifications *mods_next = mods->sml_next; int freeit = 0;
/* XXX Setting freeit to 1 crashes */ slap_mod_free(&mods->sml_mod, freeit); mods->sml_numvals = 0;
free(mods); *mods_prevp = mods_next;
return; }
And this how it is used (of course removeit is a more complex logic, it is removed here for the sake of clarity)
Modifications *mods; Modifications **mods_prev; Modifications *mods_next;
mods_prev = &op->orm_modlist; for (mods = op->orm_modlist; mods; mods = mods_next) { short sm_op = mods->sml_op; Attribute a;
mods_next = mods->sml_next;
if (remove_it) supann_rm_mods(mods, mods_prev); else mods_prev = &mods->sml_next; }
Same question, for add oprations:
/* Modifying the add */ static void supann_rm_attr(Attribute *a, Attribute **a_prevp) { Attribute *a_next = a->a_next;
attr_clean(a);
#if 0 /* XXX This crashes */ free(a); #endif *a_prevp = a_next;
return; }
And its usage: Attribute **a_prev; Attribute *a_next;
a_prev = &op->ora_e->e_attrs; for (a = op->ora_e->e_attrs; a; a = a_next) { a_next = a->a_next;
if (removeit) supann_rm_attr(a, a_prev); else a_prev = &a->a_next; }
Emmanuel Dreyfus wrote:
Hello
In an overlay, I want to alter a modification operation so that modification to an attribute is not done.
I crafted the code below, which seems to work, but is it right? There are XXX places where I expected another behavior, did I miss something?
And after "Modifying the modification", I also have "Modifying an add", just below, with the same questions.
Modify is fine. For add, you should use attr_free(), not attr_clean() + free().
/* Modifying the modification */ static void supann_rm_mods(Modifications *mods, Modifications **mods_prevp) { Modifications *mods_next = mods->sml_next; int freeit = 0;
/* XXX Setting freeit to 1 crashes */ slap_mod_free(&mods->sml_mod, freeit); mods->sml_numvals = 0; free(mods); *mods_prevp = mods_next; return;}
And this how it is used (of course removeit is a more complex logic, it is removed here for the sake of clarity)
Modifications *mods; Modifications **mods_prev; Modifications *mods_next; mods_prev = &op->orm_modlist; for (mods = op->orm_modlist; mods; mods = mods_next) { short sm_op = mods->sml_op; Attribute a; mods_next = mods->sml_next; if (remove_it) supann_rm_mods(mods, mods_prev); else mods_prev = &mods->sml_next;}
Same question, for add oprations:
/* Modifying the add */ static void supann_rm_attr(Attribute *a, Attribute **a_prevp) { Attribute *a_next = a->a_next;
attr_clean(a);#if 0 /* XXX This crashes */ free(a); #endif *a_prevp = a_next;
return;}
And its usage: Attribute **a_prev; Attribute *a_next;
a_prev = &op->ora_e->e_attrs; for (a = op->ora_e->e_attrs; a; a = a_next) { a_next = a->a_next; if (removeit) supann_rm_attr(a, a_prev); else a_prev = &a->a_next;}
On Thu, Feb 12, 2026 at 03:25:33PM +0000, Howard Chu wrote:
Modify is fine. For add, you should use attr_free(), not attr_clean() + free().
Thank you for the review.
I also have the need toremove a single attribute value for modify or add. I wonder if I need to take care of SLAP_ATTR_DONT_FREE_DATA and SLAP_ATTR_DONT_FREE_VALS in the add caze.
static void supann_attr_rmval(Attribute *a, int index) { struct berval *nbv; int j;
nbv = &a->a_vals[index]; ber_memfree_x(nbv->bv_val, NULL); nbv->bv_val = NULL;
if (a->a_nvals && a->a_nvals != a->a_vals) { nbv = &a->a_nvals[index]; ber_memfree_x(nbv->bv_val, NULL); nbv->bv_val = NULL; }
a->a_numvals--;
/* * a->a_vals[j + 1] does not overflow since * we just decreased a->a_numvals */ for (j = index; j < a->a_numvals; j++) a->a_vals[j] = a->a_vals[j + 1];
a->a_vals[a->a_numvals].bv_val = NULL; a->a_vals[a->a_numvals].bv_len = 0;
if (a->a_nvals && a->a_nvals != a->a_vals) { for (j = index; j < a->a_numvals; j++) a->a_nvals[j] = a->a_nvals[j + 1];
a->a_nvals[a->a_numvals].bv_val = NULL; a->a_nvals[a->a_numvals].bv_len = 0; }
return; }
Emmanuel Dreyfus wrote:
On Thu, Feb 12, 2026 at 03:25:33PM +0000, Howard Chu wrote:
Modify is fine. For add, you should use attr_free(), not attr_clean() + free().
Thank you for the review.
I also have the need toremove a single attribute value for modify or add. I wonder if I need to take care of SLAP_ATTR_DONT_FREE_DATA and SLAP_ATTR_DONT_FREE_VALS in the add caze.
This all looks fine. But you should think about what happens if the attribute has no values remaining after you do your removal.
static void supann_attr_rmval(Attribute *a, int index) { struct berval *nbv; int j;
nbv = &a->a_vals[index]; ber_memfree_x(nbv->bv_val, NULL); nbv->bv_val = NULL; if (a->a_nvals && a->a_nvals != a->a_vals) { nbv = &a->a_nvals[index]; ber_memfree_x(nbv->bv_val, NULL); nbv->bv_val = NULL; } a->a_numvals--; /* * a->a_vals[j + 1] does not overflow since * we just decreased a->a_numvals */ for (j = index; j < a->a_numvals; j++) a->a_vals[j] = a->a_vals[j + 1]; a->a_vals[a->a_numvals].bv_val = NULL; a->a_vals[a->a_numvals].bv_len = 0; if (a->a_nvals && a->a_nvals != a->a_vals) { for (j = index; j < a->a_numvals; j++) a->a_nvals[j] = a->a_nvals[j + 1]; a->a_nvals[a->a_numvals].bv_val = NULL; a->a_nvals[a->a_numvals].bv_len = 0; } return;}
On Fri, Feb 13, 2026 at 01:03:22PM +0000, Howard Chu wrote:
This all looks fine. But you should think about what happens if the attribute has no values remaining after you do your removal.
This was my first question about reomoving a Modifications from the list :-)