--- res/res_config_ldap.c.orig 2009-08-10 15:30:55.000000000 -0400 +++ res/res_config_ldap.c 2009-09-15 06:25:44.000000000 -0400 @@ -1181,7 +1181,9 @@ /* Create the modification array with the parameter/value pairs we were given, * if there are several parameters with the same name, we collect them into - * one parameter/value pair and delimit them with a semicolon */ + * one parameter/value pair and delimit them with a semicolon. + * For Bug 15895 - handle both a single null value (delete the parameter) and + * a series of null values (create multiple semicolon-delimited null values) */ newparam = va_arg(ap, const char *); newparam = convert_attribute_name_to_ldap(table_config, newparam); newval = va_arg(ap, const char *); @@ -1199,19 +1201,32 @@ ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1); strcpy(ldap_mods[0]->mod_type, newparam); - ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2); - ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1); - strcpy(ldap_mods[0]->mod_values[0], newval); - + ldap_mods[0]->mod_values = ast_calloc(sizeof(char **), 1); + if (newval[0]==0) { + ldap_mods[0]->mod_values[0] = 0; /* Null pointer to delete from LDAP */ + } else { + ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1); + strcpy(ldap_mods[0]->mod_values[0], newval); + } while ((newparam = va_arg(ap, const char *))) { newparam = convert_attribute_name_to_ldap(table_config, newparam); newval = va_arg(ap, const char *); mod_exists = 0; for (i = 0; i < mods_size - 1; i++) { - if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) { - /* We have the parameter allready, adding the value as a semicolon delimited value */ - ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2)); + if (ldap_mods[i] && !strcmp(ldap_mods[i]->mod_type, newparam)) { + /* We have the parameter already; add the value as a semicolon delimited value. + If the new parameter is null, just add a semicolon. + If the old parameter was null, we need the storage we didn't get before. */ + if (ldap_mods[i]->mod_values[0]==0) { + /* Previously null, so do initial allocation not done before */ + ldap_mods[i]->mod_values[0] = ast_calloc(sizeof(char), 1); + } else { + /* A value was already there. Increase storage to the length of the + current value plus the length of the new value plus the semicolon + and the null string terminator */ + ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2)); + } strcat(ldap_mods[i]->mod_values[0], ";"); strcat(ldap_mods[i]->mod_values[0], newval); mod_exists = 1; @@ -1231,9 +1246,14 @@ ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1); strcpy(ldap_mods[mods_size - 2]->mod_type, newparam); - ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2); - ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1); - strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval); + ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char **), 1); + + if (newval[0]==0) { + ldap_mods[mods_size -2]->mod_values[0] = 0; + } else { + ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1); + strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval); + } } } /* freeing ldap_mods further down */