From 73f1a6793dd383c8f038d5af1d01fabe87dbb1a4 Mon Sep 17 00:00:00 2001 From: Ben Jeffery Date: Tue, 22 Jun 2021 16:09:13 +0100 Subject: [PATCH] Fix overflow checks and factor out ragged column expansion --- c/CHANGELOG.rst | 3 + c/tests/test_tables.c | 99 ++++++++++++- c/tskit/tables.c | 324 +++++++++++------------------------------- 3 files changed, 177 insertions(+), 249 deletions(-) diff --git a/c/CHANGELOG.rst b/c/CHANGELOG.rst index b7c0f3671b..72706f7aa0 100644 --- a/c/CHANGELOG.rst +++ b/c/CHANGELOG.rst @@ -8,6 +8,9 @@ **Fixes** +- Fix segfault when very large columns overflow + (:user:`bhaller`, :user:`benjeffery`, :issue:`1509`, :pr:`1511`). + ---------------------- [0.99.12] - 2021-05-14 ---------------------- diff --git a/c/tests/test_tables.c b/c/tests/test_tables.c index 8a0784fb68..2975dfe622 100644 --- a/c/tests/test_tables.c +++ b/c/tests/test_tables.c @@ -5441,60 +5441,147 @@ test_column_overflow(void) ret = tsk_table_collection_init(&tables, 0); CU_ASSERT_EQUAL_FATAL(ret, 0); + // location /* We can't trigger a column overflow with one element because the parameter * value is 32 bit */ ret_id = tsk_individual_table_add_row( &tables.individuals, 0, &zero, 1, NULL, 0, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, 0); + // Check normal overflow from additional length ret_id = tsk_individual_table_add_row( &tables.individuals, 0, NULL, too_big, NULL, 0, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // Check overflow from minimum increment + ret = tsk_individual_table_set_max_location_length_increment( + &tables.individuals, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); ret_id = tsk_individual_table_add_row( - &tables.individuals, 0, NULL, 0, NULL, 0, zeros, 1); + &tables.individuals, 0, NULL, 1, NULL, 0, NULL, 0); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // parents + ret_id = tsk_individual_table_add_row( + &tables.individuals, 0, NULL, 0, id_zeros, 1, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, 1); ret_id = tsk_individual_table_add_row( - &tables.individuals, 0, NULL, 0, NULL, 0, NULL, too_big); + &tables.individuals, 0, NULL, 0, NULL, too_big, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_individual_table_set_max_parents_length_increment( + &tables.individuals, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); ret_id = tsk_individual_table_add_row( - &tables.individuals, 0, NULL, 0, id_zeros, 1, NULL, 0); + &tables.individuals, 0, NULL, 0, NULL, 1, NULL, 0); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // metadata + ret_id = tsk_individual_table_add_row( + &tables.individuals, 0, NULL, 0, NULL, 0, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 2); ret_id = tsk_individual_table_add_row( - &tables.individuals, 0, NULL, 0, NULL, too_big, NULL, 0); + &tables.individuals, 0, NULL, 0, NULL, 0, NULL, too_big); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_individual_table_set_max_metadata_length_increment( + &tables.individuals, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_individual_table_add_row( + &tables.individuals, 0, NULL, 0, NULL, 0, NULL, 1); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); ret_id = tsk_node_table_add_row(&tables.nodes, 0, 0, 0, 0, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 0); ret_id = tsk_node_table_add_row(&tables.nodes, 0, 0, 0, 0, NULL, too_big); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_node_table_set_max_metadata_length_increment(&tables.nodes, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_node_table_add_row(&tables.nodes, 0, 0, 0, 0, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + + ret_id = tsk_edge_table_add_row(&tables.edges, 0, 0, 0, 0, zeros, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, 0); + ret_id = tsk_edge_table_add_row(&tables.edges, 0, 0, 0, 0, NULL, too_big); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_edge_table_set_max_metadata_length_increment(&tables.edges, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_edge_table_add_row(&tables.edges, 0, 0, 0, 0, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); ret_id = tsk_site_table_add_row(&tables.sites, 0, zeros, 1, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 0); + // ancestral state ret_id = tsk_site_table_add_row(&tables.sites, 0, NULL, too_big, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_site_table_set_max_ancestral_state_length_increment( + &tables.sites, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_site_table_add_row(&tables.sites, 0, NULL, 1, NULL, 0); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // metadata ret_id = tsk_site_table_add_row(&tables.sites, 0, NULL, 0, NULL, too_big); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_site_table_set_max_metadata_length_increment(&tables.sites, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_site_table_add_row(&tables.sites, 0, NULL, 0, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); ret_id = tsk_mutation_table_add_row(&tables.mutations, 0, 0, 0, 0, zeros, 1, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 0); + // derived state ret_id = tsk_mutation_table_add_row( - &tables.mutations, 0, 0, 0, 0, NULL, 0, NULL, too_big); + &tables.mutations, 0, 0, 0, 0, NULL, too_big, NULL, 0); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_mutation_table_set_max_derived_state_length_increment( + &tables.mutations, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_mutation_table_add_row(&tables.mutations, 0, 0, 0, 0, NULL, 1, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // metadata ret_id = tsk_mutation_table_add_row( - &tables.mutations, 0, 0, 0, 0, NULL, too_big, NULL, 0); + &tables.mutations, 0, 0, 0, 0, NULL, 0, NULL, too_big); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_mutation_table_set_max_metadata_length_increment( + &tables.mutations, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_mutation_table_add_row(&tables.mutations, 0, 0, 0, 0, NULL, 0, NULL, 1); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); ret_id = tsk_provenance_table_add_row(&tables.provenances, zeros, 1, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 0) + // timestamp ret_id = tsk_provenance_table_add_row(&tables.provenances, NULL, too_big, NULL, 0); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_provenance_table_set_max_timestamp_length_increment( + &tables.provenances, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_provenance_table_add_row(&tables.provenances, NULL, 1, NULL, 0); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + // record ret_id = tsk_provenance_table_add_row(&tables.provenances, NULL, 0, NULL, too_big); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_provenance_table_set_max_record_length_increment( + &tables.provenances, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_provenance_table_add_row(&tables.provenances, NULL, 0, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); ret_id = tsk_population_table_add_row(&tables.populations, zeros, 1); CU_ASSERT_EQUAL_FATAL(ret_id, 0); ret_id = tsk_population_table_add_row(&tables.populations, NULL, too_big); CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_population_table_set_max_metadata_length_increment( + &tables.populations, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_population_table_add_row(&tables.populations, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + + ret_id = tsk_migration_table_add_row(&tables.migrations, 0, 0, 0, 0, 0, 0, zeros, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, 0); + ret_id = tsk_migration_table_add_row( + &tables.migrations, 0, 0, 0, 0, 0, 0, NULL, too_big); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); + ret = tsk_migration_table_set_max_metadata_length_increment( + &tables.migrations, too_big); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret_id = tsk_migration_table_add_row(&tables.migrations, 0, 0, 0, 0, 0, 0, NULL, 1); + CU_ASSERT_EQUAL_FATAL(ret_id, TSK_ERR_COLUMN_OVERFLOW); tsk_table_collection_free(&tables); } diff --git a/c/tskit/tables.c b/c/tskit/tables.c index a5e5dbca0b..a3ae0ed890 100644 --- a/c/tskit/tables.c +++ b/c/tskit/tables.c @@ -405,6 +405,38 @@ expand_column(void **column, size_t new_max_rows, size_t element_size) return ret; } +static int +expand_ragged_column(tsk_size_t current_length, tsk_size_t additional_length, + tsk_size_t max_length_increment, tsk_size_t *max_length, void **column, + size_t element_size) +{ + int ret = 0; + tsk_size_t increment = TSK_MAX(additional_length, max_length_increment); + + if (check_offset_overflow(current_length, additional_length)) { + ret = TSK_ERR_COLUMN_OVERFLOW; + goto out; + } + if ((current_length + additional_length) > *max_length) { + if (check_offset_overflow(*max_length, increment)) { + /* Here we could allocate to the maximum size. + * Instead we are erroring out as this is much easier to test. + * The cost is that (at most) the last "max_length_increment"-1 + * bytes of the possible array space can't be used. */ + ret = TSK_ERR_COLUMN_OVERFLOW; + goto out; + } + + ret = expand_column(column, *max_length + increment, element_size); + if (ret != 0) { + goto out; + } + *max_length += increment; + } +out: + return ret; +} + static int replace_string( char **str, tsk_size_t *len, const char *new_str, const tsk_size_t new_len) @@ -481,72 +513,27 @@ static int tsk_individual_table_expand_location( tsk_individual_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_location_length_increment); - tsk_size_t new_size = self->max_location_length + increment; - - if (check_offset_overflow(self->location_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->location_length + additional_length) > self->max_location_length) { - ret = expand_column((void **) &self->location, new_size, sizeof(double)); - if (ret != 0) { - goto out; - } - self->max_location_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->location_length, additional_length, + self->max_location_length_increment, &self->max_location_length, + (void **) &self->location, sizeof(*self->location)); } static int tsk_individual_table_expand_parents( tsk_individual_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_parents_length_increment); - tsk_size_t new_size = self->max_parents_length + increment; - - if (check_offset_overflow(self->parents_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->parents_length + additional_length) > self->max_parents_length) { - ret = expand_column((void **) &self->parents, new_size, sizeof(tsk_id_t)); - if (ret != 0) { - goto out; - } - self->max_parents_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->parents_length, additional_length, + self->max_parents_length_increment, &self->max_parents_length, + (void **) &self->parents, sizeof(*self->parents)); } static int tsk_individual_table_expand_metadata( tsk_individual_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -1222,24 +1209,9 @@ tsk_node_table_expand_main_columns(tsk_node_table_t *self, tsk_size_t additional static int tsk_node_table_expand_metadata(tsk_node_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -1762,24 +1734,9 @@ tsk_edge_table_expand_main_columns(tsk_edge_table_t *self, size_t additional_row static int tsk_edge_table_expand_metadata(tsk_edge_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -2362,50 +2319,20 @@ tsk_site_table_expand_main_columns(tsk_site_table_t *self, tsk_size_t additional } static int -tsk_site_table_expand_ancestral_state(tsk_site_table_t *self, size_t additional_length) +tsk_site_table_expand_ancestral_state( + tsk_site_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment = (tsk_size_t) TSK_MAX( - additional_length, self->max_ancestral_state_length_increment); - tsk_size_t new_size = self->max_ancestral_state_length + increment; - - if (check_offset_overflow(self->ancestral_state_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->ancestral_state_length + additional_length) - > self->max_ancestral_state_length) { - ret = expand_column((void **) &self->ancestral_state, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_ancestral_state_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->ancestral_state_length, additional_length, + self->max_ancestral_state_length_increment, &self->max_ancestral_state_length, + (void **) &self->ancestral_state, sizeof(*self->ancestral_state)); } static int -tsk_site_table_expand_metadata(tsk_site_table_t *self, size_t additional_length) +tsk_site_table_expand_metadata(tsk_site_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = (tsk_size_t) TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -2959,50 +2886,20 @@ tsk_mutation_table_expand_main_columns( static int tsk_mutation_table_expand_derived_state( - tsk_mutation_table_t *self, size_t additional_length) + tsk_mutation_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment = (tsk_size_t) TSK_MAX( - additional_length, self->max_derived_state_length_increment); - tsk_size_t new_size = self->max_derived_state_length + increment; - - if (check_offset_overflow(self->derived_state_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->derived_state_length + additional_length) - > self->max_derived_state_length) { - ret = expand_column((void **) &self->derived_state, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_derived_state_length = (tsk_size_t) new_size; - } -out: - return ret; + return expand_ragged_column(self->derived_state_length, additional_length, + self->max_derived_state_length_increment, &self->max_derived_state_length, + (void **) &self->derived_state, sizeof(*self->derived_state)); } static int -tsk_mutation_table_expand_metadata(tsk_mutation_table_t *self, size_t additional_length) +tsk_mutation_table_expand_metadata( + tsk_mutation_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = (tsk_size_t) TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -3600,24 +3497,9 @@ static int tsk_migration_table_expand_metadata( tsk_migration_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -4106,24 +3988,9 @@ static int tsk_population_table_expand_metadata( tsk_population_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_metadata_length_increment); - tsk_size_t new_size = self->max_metadata_length + increment; - - if (check_offset_overflow(self->metadata_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->metadata_length + additional_length) > self->max_metadata_length) { - ret = expand_column((void **) &self->metadata, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_metadata_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->metadata_length, additional_length, + self->max_metadata_length_increment, &self->max_metadata_length, + (void **) &self->metadata, sizeof(*self->metadata)); } int @@ -4563,47 +4430,18 @@ static int tsk_provenance_table_expand_timestamp( tsk_provenance_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment - = TSK_MAX(additional_length, self->max_timestamp_length_increment); - tsk_size_t new_size = self->max_timestamp_length + increment; - - if (check_offset_overflow(self->timestamp_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->timestamp_length + additional_length) > self->max_timestamp_length) { - ret = expand_column((void **) &self->timestamp, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_timestamp_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->timestamp_length, additional_length, + self->max_timestamp_length_increment, &self->max_timestamp_length, + (void **) &self->timestamp, sizeof(*self->timestamp)); } static int -tsk_provenance_table_expand_provenance( +tsk_provenance_table_expand_record( tsk_provenance_table_t *self, tsk_size_t additional_length) { - int ret = 0; - tsk_size_t increment = TSK_MAX(additional_length, self->max_record_length_increment); - tsk_size_t new_size = self->max_record_length + increment; - - if (check_offset_overflow(self->record_length, increment)) { - ret = TSK_ERR_COLUMN_OVERFLOW; - goto out; - } - if ((self->record_length + additional_length) > self->max_record_length) { - ret = expand_column((void **) &self->record, new_size, sizeof(char)); - if (ret != 0) { - goto out; - } - self->max_record_length = new_size; - } -out: - return ret; + return expand_ragged_column(self->record_length, additional_length, + self->max_record_length_increment, &self->max_record_length, + (void **) &self->record, sizeof(*self->record)); } int @@ -4659,7 +4497,7 @@ tsk_provenance_table_init(tsk_provenance_table_t *self, tsk_flags_t TSK_UNUSED(o goto out; } self->timestamp_offset[0] = 0; - ret = tsk_provenance_table_expand_provenance(self, 1); + ret = tsk_provenance_table_expand_record(self, 1); if (ret != 0) { goto out; } @@ -4749,7 +4587,7 @@ tsk_provenance_table_append_columns(tsk_provenance_table_t *self, tsk_size_t num self->record_offset[self->num_rows + j] = self->record_length + record_offset[j]; } record_length = record_offset[num_rows]; - ret = tsk_provenance_table_expand_provenance(self, record_length); + ret = tsk_provenance_table_expand_record(self, record_length); if (ret != 0) { goto out; } @@ -4800,7 +4638,7 @@ tsk_provenance_table_add_row(tsk_provenance_table_t *self, const char *timestamp if (ret != 0) { goto out; } - ret = tsk_provenance_table_expand_provenance(self, record_length); + ret = tsk_provenance_table_expand_record(self, record_length); if (ret != 0) { goto out; }