diff options
author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2009-04-30 15:10:49 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin@dahyabhai.net> | 2009-04-30 15:10:49 -0400 |
commit | e655bd0159fcbb553a168bbe37d6a4f8b6f9b1d6 (patch) | |
tree | 9e05085203cf27b090ebfb62ff90d08f7b31d3b9 | |
parent | 8314613845f5c3a1844a3a08969eaea4f5e06ab2 (diff) | |
download | slapi-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.c | 72 |
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 *)); |