Skip to content
Merged
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
artifacts/
_codeql_build_dir/
.vs/
.idea/
*~
TestResults/
.DS_Store
_codeql_detected_source_root
3 changes: 3 additions & 0 deletions src/dnmd/editor.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ bool create_and_fill_indirect_table(mdcxt_t* cxt, mdtable_id_t original_table, m

target_table->row_count = editor->tables[original_table].table->row_count;
target_table->cxt = editor->cxt;

// Introducing a Ptr table means the table heap is now uncompressed.
cxt->context_flags |= mdc_uncompressed_table_heap;
return true;
}

Expand Down
13 changes: 5 additions & 8 deletions src/dnmd/entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ bool md_create_handle(void const* data, size_t data_len, mdhandle_t* handle)
if ((bool)(cxt.context_flags & mdc_minimal_delta) && !tables_heap_uncompressed)
return false;

// Record whether the table heap is uncompressed (#-).
if (tables_heap_uncompressed)
cxt.context_flags |= mdc_uncompressed_table_heap;

// Header initialization is complete.
cxt.magic = MDLIB_MAGIC_NUMBER;
cxt.raw_metadata.ptr = data;
Expand Down Expand Up @@ -968,13 +972,10 @@ bool md_write_to_buffer(mdhandle_t handle, uint8_t* buffer, size_t* len)
if (cxt->user_string_heap.size != 0)
stream_count++;

char const* tables_stream_name = "#~";
char const* tables_stream_name = (cxt->context_flags & mdc_uncompressed_table_heap) ? "#-" : "#~";

if (cxt->context_flags & mdc_minimal_delta)
{
tables_stream_name = "#-";
stream_count++;
}

uint64_t valid_tables = 0;
uint64_t sorted_tables = 0;
Expand All @@ -989,10 +990,6 @@ bool md_write_to_buffer(mdhandle_t handle, uint8_t* buffer, size_t* len)
valid_tables |= (1ULL << i);
if (cxt->tables[i].is_sorted)
sorted_tables |= (1ULL << i);

// Indirect tables only exist in images that use the uncompresed stream.
if (table_is_indirect_table((mdtable_id_t)i))
tables_stream_name = "#-";
}
}

Expand Down
15 changes: 8 additions & 7 deletions src/dnmd/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,14 @@ typedef enum
// Flags and masks for context details
typedef enum
{
mdc_none = 0x0000,
mdc_large_string_heap = 0x0001,
mdc_large_guid_heap = 0x0002,
mdc_large_blob_heap = 0x0004,
mdc_extra_data = 0x0040,
mdc_image_flags = 0xffff,
mdc_minimal_delta = 0x00010000,
mdc_none = 0x0000,
mdc_large_string_heap = 0x0001,
mdc_large_guid_heap = 0x0002,
mdc_large_blob_heap = 0x0004,
mdc_extra_data = 0x0040,
mdc_image_flags = 0xffff,
mdc_minimal_delta = 0x00010000,
mdc_uncompressed_table_heap = 0x00020000,
} mdcxt_flag_t;

// Macros used to insert/extract the column offset.
Expand Down
72 changes: 69 additions & 3 deletions src/dnmd/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,76 @@ bool initialize_tables(mdcxt_t* cxt)
bool validate_tables(mdcxt_t* cxt)
{
assert(cxt != NULL);
(void)cxt;

// [TODO] Reference ECMA-335 and encode table verification.
// [TODO] Validate that tables marked as sorted are actually sorted.
// [TODO] Do not allow the *Ptr tables to be present in a compressed table heap.

// Do not allow the *Ptr indirection tables
// to be present in a compressed table heap (#~).
if (!(cxt->context_flags & mdc_uncompressed_table_heap))
{
for (size_t i = 0; i < MDTABLE_MAX_COUNT; ++i)
{
if (table_is_indirect_table((mdtable_id_t)i) && cxt->tables[i].row_count != 0)
return false;
}
}

// II.22 - Validate that tables marked as sorted are actually sorted.
for (size_t i = 0; i < MDTABLE_MAX_COUNT; ++i)
{
mdtable_t* table = &cxt->tables[i];
if (!table->is_sorted || table->row_count <= 1)
continue;

md_key_info_t const* keys;
uint8_t key_count = get_table_keys((mdtable_id_t)i, &keys);
if (key_count == 0)
continue;

for (uint32_t r = 1; r < table->row_count; ++r)
{
mdcursor_t row = create_cursor(table, r);
mdcursor_t next_row = create_cursor(table, r + 1);

for (uint8_t k = 0; k < key_count; ++k)
{
col_index_t key_col = index_to_col(keys[k].index, (mdtable_id_t)i);

access_cxt_t row_acxt;
if (!create_access_context(&row, key_col, false, &row_acxt))
return false;

access_cxt_t next_acxt;
if (!create_access_context(&next_row, key_col, false, &next_acxt))
return false;

uint32_t row_value;
if (!read_column_data(&row_acxt, &row_value))
return false;

uint32_t next_value;
if (!read_column_data(&next_acxt, &next_value))
return false;

// Compare by sort direction - ascending or descending.
if (keys[k].descending)
{
if (row_value < next_value)
return false;
if (row_value > next_value)
break;
}
else
{
if (row_value > next_value)
return false;
if (row_value < next_value)
break;
}
}
}
}

return true;
}

Expand Down