summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2009-04-30 15:10:49 -0400
committerNalin Dahyabhai <nalin@dahyabhai.net>2009-04-30 15:10:49 -0400
commite655bd0159fcbb553a168bbe37d6a4f8b6f9b1d6 (patch)
tree9e05085203cf27b090ebfb62ff90d08f7b31d3b9
parent8314613845f5c3a1844a3a08969eaea4f5e06ab2 (diff)
downloadslapi-nis-e655bd0159fcbb553a168bbe37d6a4f8b6f9b1d6.tar.gz
slapi-nis-e655bd0159fcbb553a168bbe37d6a4f8b6f9b1d6.tar.xz
slapi-nis-e655bd0159fcbb553a168bbe37d6a4f8b6f9b1d6.zip
- fix format_link() to not corrupt the heap with some bad math
-rw-r--r--src/format.c72
1 files changed, 43 insertions, 29 deletions
diff --git a/src/format.c b/src/format.c
index 050ca50..4992da9 100644
--- a/src/format.c
+++ b/src/format.c
@@ -2303,7 +2303,7 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
struct format_ref_attr_list ***ref_attr_list,
struct format_ref_attr_list ***inref_attr_list)
{
- int ret, argc, i, *j, l, n_lists, n_done;
+ int ret, argc, i, j, *n_items, l, result_n, n_lists, n_done;
unsigned int **lengths, length, max_length;
char **argv, ***values, *buffer, *p;
struct berval bv, **choices;
@@ -2330,14 +2330,14 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
/* Allocate space to store the information. */
values = malloc(sizeof(char **) * ((argc + 1) / 3));
lengths = malloc(sizeof(int *) * ((argc + 1) / 3));
- j = malloc(sizeof(int) * ((argc + 1) / 3));
- if ((values == NULL) || (lengths == NULL)) {
+ n_items = malloc(sizeof(int) * ((argc + 1) / 3));
+ if ((values == NULL) || (lengths == NULL) || (n_items == NULL)) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"link: out of memory\n");
format_free_parsed_args(argv);
free(values);
free(lengths);
- free(j);
+ free(n_items);
return -ENOMEM;
}
@@ -2358,37 +2358,53 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
}
- /* If we got _no_ answers for anything, that's a NULL result. */
+ /* If we got _no_ answers for everything, that's a NULL result. */
if (n_lists == 0) {
format_free_parsed_args(argv);
free(values);
free(lengths);
- free(j);
+ free(n_items);
return -ENOENT;
}
/* Walk the lists, building the output data items. */
n_lists = (argc + 1) / 3;
for (i = 0; i < n_lists; i++) {
- j[i] = 0;
+ for (j = 0;
+ (values[i] != NULL) && (values[i][j] != NULL);
+ j++) {
+ continue;
+ }
+ n_items[i] = j;
}
- n_done = 0;
- length = 0;
max_length = 0;
buffer = NULL;
- do {
- /* Calculate how much space we need. */
+ length = 0;
+ n_done = 0;
+ for (result_n = 0; n_done < n_lists; result_n++) {
+ /* Calculate how much space we need for this result. */
length = 0;
+ n_done = 0;
for (i = 0; i < n_lists; i++) {
- if ((values[i] != NULL) && (values[i][j[i]] != NULL)) {
- length += lengths[i][j[i]];
+ if (result_n < n_items[i]) {
+ /* List has an item for this result. */
+ length += lengths[i][result_n];
} else {
+ /* Use the padding. */
length += strlen(argv[i * 3 + 1]);
+ /* Note that this list has run out. */
+ n_done++;
}
if (i < (n_lists - 1)) {
+ /* And the separator. */
length += strlen(argv[i * 3 + 2]);
}
}
+ /* If we're out of data, we should stop before adding a result
+ * to the list. */
+ if (n_done == n_lists) {
+ break;
+ }
/* Make sure the buffer is large enough. */
if (length > max_length) {
free(buffer);
@@ -2396,13 +2412,13 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
if (buffer == NULL) {
format_free_bv_list(choices);
format_free_parsed_args(argv);
- for (i = 0; i < n_lists; i += 3) {
+ for (i = 0; i < n_lists; i++) {
format_free_data_set(values[i],
lengths[i]);
}
free(values);
free(lengths);
- free(j);
+ free(n_items);
return -ENOMEM;
}
max_length = length;
@@ -2410,17 +2426,19 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
/* Build the output value. */
p = buffer;
for (i = 0; i < n_lists; i++) {
- if ((values[i] != NULL) && (values[i][j[i]] != NULL)) {
- l = lengths[i][j[i]];
- memcpy(p, values[i][j[i]], l);
+ if (result_n < n_items[i]) {
+ /* The value from the list of values. */
+ l = lengths[i][result_n];
+ memcpy(p, values[i][result_n], l);
p += l;
- (j[i])++;
} else {
+ /* Padding. */
l = strlen(argv[i * 3 + 1]);
memcpy(p, argv[i * 3 + 1], l);
p += l;
}
if (i < (n_lists - 1)) {
+ /* Separator. */
l = strlen(argv[i * 3 + 2]);
memcpy(p, argv[i * 3 + 2], l);
p += l;
@@ -2441,13 +2459,7 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
bv.bv_len, bv.bv_val);
format_add_bv_list(&choices, &bv);
}
- /* Figure out if we're done yet. */
- for (i = 0, n_done = 0; i < n_lists; i++) {
- if ((values[i] == NULL) || (values[i][j[i]] == NULL)) {
- n_done++;
- }
- }
- } while (n_done != n_lists);
+ }
if (choices != NULL) {
format_add_choice(outbuf_choices, outbuf, choices);
@@ -2458,13 +2470,13 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
format_free_parsed_args(argv);
- for (i = 0; i < argc; i += 3) {
- format_free_data_set(values[i / 3], lengths[i / 3]);
+ for (i = 0; i < n_lists; i++) {
+ format_free_data_set(values[i], lengths[i]);
}
free(buffer);
free(values);
free(lengths);
- free(j);
+ free(n_items);
return ret;
}
@@ -3339,6 +3351,7 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e,
&template_len);
if (template == NULL) {
format_free_choices(choices);
+ *data_lengths = NULL;
return NULL;
}
/* Figure out how many results we're going to have. */
@@ -3357,6 +3370,7 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e,
}
if (combinations == 0) {
format_free_choices(choices);
+ *data_lengths = NULL;
return NULL;
}
ret = malloc((combinations + 1) * sizeof(char *));