diff --git a/src/dnmd/bytes.c b/src/dnmd/bytes.c index a82ae87b..a9c3a9f4 100644 --- a/src/dnmd/bytes.c +++ b/src/dnmd/bytes.c @@ -257,28 +257,27 @@ bool decompress_i32(uint8_t const** data, size_t* data_len, int32_t* o) uint32_t unsigned_value; size_t original_data_len = *data_len; if (!decompress_u32(data, data_len, &unsigned_value)) - { return false; - } + bool is_signed = (unsigned_value & 1) != 0; unsigned_value >>= 1; if (is_signed) { - switch (*data_len - original_data_len) + switch (original_data_len - *data_len) { // Sign extend the value based on the number of bytes used. case 1: - { unsigned_value |= SIGN_MASK_ONEBYTE; - } + break; case 2: - { unsigned_value |= SIGN_MASK_TWOBYTE; - } - default: - { + break; + case 4: unsigned_value |= SIGN_MASK_FOURBYTE; - } + break; + default: + assert(false); + return false; } } *o = (int32_t)unsigned_value; diff --git a/src/dnmd/pdb_blobs.c b/src/dnmd/pdb_blobs.c index 550ab196..cc73a3ba 100644 --- a/src/dnmd/pdb_blobs.c +++ b/src/dnmd/pdb_blobs.c @@ -14,10 +14,10 @@ md_blob_parse_result_t md_parse_document_name(mdhandle_t handle, uint8_t const* uint8_t separator; if (!read_u8(&blob, &blob_len, &separator)) return mdbpr_InvalidBlob; - + if (separator > 0x7f) return mdbpr_InvalidBlob; - + uint8_t* name_current = (uint8_t*)name; size_t remaining_name_len = *name_len; size_t required_len = 0; @@ -45,13 +45,13 @@ md_blob_parse_result_t md_parse_document_name(mdhandle_t handle, uint8_t const* uint32_t part_offset; if (!decompress_u32(&blob, &blob_len, &part_offset)) return mdbpr_InvalidBlob; - + // The part blob is a UTF-8 string that is not null-terminated. const uint8_t* part; uint32_t part_len; if (!try_get_blob(cxt, part_offset, &part, &part_len)) return mdbpr_InvalidBlob; - + // Add the required space for the part. // If there is space in the buffer, write the part. required_len += part_len; @@ -91,7 +91,7 @@ static uint32_t get_num_sequence_points(mdcursor_t method_debug_information, uin uint32_t ignored; if (!decompress_u32(&blob, &blob_len, &ignored)) // header LocalSignature return UINT32_MAX; - + mdcursor_t document; if (1 != md_get_column_value_as_cursor(method_debug_information, mdtMethodDebugInformation_Document, 1, &document)) return UINT32_MAX; @@ -108,7 +108,7 @@ static uint32_t get_num_sequence_points(mdcursor_t method_debug_information, uin uint32_t il_offset; if (!decompress_u32(&blob, &blob_len, &il_offset)) // ILOffset return UINT32_MAX; - + // The first record cannot be a document record if (!first_record && il_offset == 0) { @@ -124,7 +124,7 @@ static uint32_t get_num_sequence_points(mdcursor_t method_debug_information, uin uint32_t delta_lines; if (!decompress_u32(&blob, &blob_len, &delta_lines)) // DeltaLines return UINT32_MAX; - + uint32_t delta_columns; if (!decompress_u32(&blob, &blob_len, &delta_columns)) // DeltaColumns return UINT32_MAX; @@ -145,11 +145,16 @@ static uint32_t get_num_sequence_points(mdcursor_t method_debug_information, uin return num_records; } -md_blob_parse_result_t md_parse_sequence_points(mdcursor_t method_debug_information, uint8_t const* blob, size_t blob_len, md_sequence_points_t* sequence_points, size_t* buffer_len) +md_blob_parse_result_t md_parse_sequence_points( + mdcursor_t method_debug_information, + uint8_t const* blob, + size_t blob_len, + md_sequence_points_t* sequence_points, + size_t* buffer_len) { if (CursorNull(&method_debug_information) || CursorEnd(&method_debug_information)) return mdbpr_InvalidArgument; - + if (blob == NULL || buffer_len == NULL) return mdbpr_InvalidArgument; @@ -157,7 +162,7 @@ md_blob_parse_result_t md_parse_sequence_points(mdcursor_t method_debug_informat if (num_records == UINT32_MAX) return mdbpr_InvalidBlob; - + size_t required_size = sizeof(md_sequence_points_t) + num_records * sizeof(sequence_points->records[0]); if (sequence_points == NULL || *buffer_len < required_size) { @@ -168,7 +173,7 @@ md_blob_parse_result_t md_parse_sequence_points(mdcursor_t method_debug_informat // header LocalSignature if (!decompress_u32(&blob, &blob_len, &sequence_points->signature)) return mdbpr_InvalidBlob; - + mdcursor_t document; if (1 != md_get_column_value_as_cursor(method_debug_information, mdtMethodDebugInformation_Document, 1, &document)) return mdbpr_InvalidBlob; @@ -176,15 +181,20 @@ md_blob_parse_result_t md_parse_sequence_points(mdcursor_t method_debug_informat // Create a "null" cursor to default-initialize the document field. mdcxt_t* cxt = extract_mdcxt(md_extract_handle_from_cursor(method_debug_information)); sequence_points->document = create_cursor(&cxt->tables[mdtid_Document], 0); - + // header InitialDocument uint32_t document_rid = 0; - if (CursorNull(&document) && !decompress_u32(&blob, &blob_len, &document_rid)) + if (CursorNull(&document) + && !decompress_u32(&blob, &blob_len, &document_rid)) + { return mdbpr_InvalidBlob; - + } + if (document_rid != 0 && !md_token_to_cursor(cxt, CreateTokenType(mdtid_Document) | document_rid, &sequence_points->document)) + { return mdbpr_InvalidBlob; + } bool seen_non_hidden_sequence_point = false; for (uint32_t i = 0; blob_len > 0 && i < num_records; ++i) @@ -192,85 +202,90 @@ md_blob_parse_result_t md_parse_sequence_points(mdcursor_t method_debug_informat uint32_t il_offset; if (!decompress_u32(&blob, &blob_len, &il_offset)) // ILOffset return mdbpr_InvalidBlob; + + // Check if the method transitioned + // into a new source file. if (i != 0 && il_offset == 0) { uint32_t document_row_id; if (!decompress_u32(&blob, &blob_len, &document_row_id)) // Document return mdbpr_InvalidBlob; - + sequence_points->records[i].kind = mdsp_DocumentRecord; if (!md_token_to_cursor(cxt, CreateTokenType(mdtid_Document) | document_row_id, &sequence_points->records[i].document.document)) return mdbpr_InvalidBlob; + + continue; + } + + uint32_t delta_lines; + if (!decompress_u32(&blob, &blob_len, &delta_lines)) // DeltaLines + return mdbpr_InvalidBlob; + + int64_t delta_columns; + if (delta_lines == 0) + { + uint32_t raw_delta_columns; + if (!decompress_u32(&blob, &blob_len, &raw_delta_columns)) // DeltaColumns + return mdbpr_InvalidBlob; + delta_columns = raw_delta_columns; } else { - uint32_t delta_lines; - if (!decompress_u32(&blob, &blob_len, &delta_lines)) // DeltaLines + int32_t raw_delta_columns; + if (!decompress_i32(&blob, &blob_len, &raw_delta_columns)) // DeltaColumns return mdbpr_InvalidBlob; + delta_columns = raw_delta_columns; + } - int64_t delta_columns; - if (delta_lines == 0) - { - uint32_t raw_delta_columns; - if (!decompress_u32(&blob, &blob_len, &raw_delta_columns)) // DeltaColumns - return mdbpr_InvalidBlob; - delta_columns = raw_delta_columns; - } - else - { - int32_t raw_delta_columns; - if (!decompress_i32(&blob, &blob_len, &raw_delta_columns)) // DeltaColumns - return mdbpr_InvalidBlob; - delta_columns = raw_delta_columns; - } - - if (delta_columns == 0) - { - sequence_points->records[i].kind = mdsp_HiddenSequencePointRecord; - sequence_points->records[i].hidden_sequence_point.il_offset = il_offset; - } - else if (!seen_non_hidden_sequence_point) - { - seen_non_hidden_sequence_point = true; - uint32_t start_line; - if (!decompress_u32(&blob, &blob_len, &start_line)) // StartLine - return mdbpr_InvalidBlob; - uint32_t start_column; - if (!decompress_u32(&blob, &blob_len, &start_column)) // StartColumn - return mdbpr_InvalidBlob; - - sequence_points->records[i].kind = mdsp_SequencePointRecord; - sequence_points->records[i].sequence_point.il_offset = il_offset; - sequence_points->records[i].sequence_point.num_lines = delta_lines; - sequence_points->records[i].sequence_point.delta_columns = delta_columns; - sequence_points->records[i].sequence_point.start_line = start_line; - sequence_points->records[i].sequence_point.start_column = start_column; - } - else - { - // If we've seen a non-hidden sequence point, - // then the values are compressed signed integers instead of - // unsigned integers. - int32_t start_line; - if (!decompress_i32(&blob, &blob_len, &start_line)) // StartLine - return mdbpr_InvalidBlob; - int32_t start_column; - if (!decompress_i32(&blob, &blob_len, &start_column)) // StartColumn - return mdbpr_InvalidBlob; + // Check for hidden point + if (delta_lines == 0 && delta_columns == 0) + { + sequence_points->records[i].kind = mdsp_HiddenSequencePointRecord; + sequence_points->records[i].hidden_sequence_point.il_offset = il_offset; + continue; + } - sequence_points->records[i].kind = mdsp_SequencePointRecord; - sequence_points->records[i].sequence_point.il_offset = il_offset; - sequence_points->records[i].sequence_point.num_lines = delta_lines; - sequence_points->records[i].sequence_point.delta_columns = delta_columns; - sequence_points->records[i].sequence_point.start_line = start_line; - sequence_points->records[i].sequence_point.start_column = start_column; - } + int64_t start_line; + int64_t start_column; + if (!seen_non_hidden_sequence_point) + { + seen_non_hidden_sequence_point = true; + uint32_t start_line_raw; + if (!decompress_u32(&blob, &blob_len, &start_line_raw)) // StartLine + return mdbpr_InvalidBlob; + uint32_t start_column_raw; + if (!decompress_u32(&blob, &blob_len, &start_column_raw)) // StartColumn + return mdbpr_InvalidBlob; + start_line = start_line_raw; + start_column = start_column_raw; } + else + { + // If we've seen a non-hidden sequence point, + // then the values are compressed signed integers instead of + // unsigned integers. + int32_t start_line_raw; + if (!decompress_i32(&blob, &blob_len, &start_line_raw)) // StartLine + return mdbpr_InvalidBlob; + int32_t start_column_raw; + if (!decompress_i32(&blob, &blob_len, &start_column_raw)) // StartColumn + return mdbpr_InvalidBlob; + start_line = start_line_raw; + start_column = start_column_raw; + } + + sequence_points->records[i].kind = mdsp_SequencePointRecord; + sequence_points->records[i].sequence_point.il_offset = il_offset; + sequence_points->records[i].sequence_point.num_lines = delta_lines; + sequence_points->records[i].sequence_point.delta_columns = delta_columns; + sequence_points->records[i].sequence_point.start_line = start_line; + sequence_points->records[i].sequence_point.start_column = start_column; } if (blob_len != 0) return mdbpr_InvalidBlob; - + sequence_points->record_count = num_records; return mdbpr_Success; } @@ -289,7 +304,7 @@ md_blob_parse_result_t md_parse_local_constant_sig(mdhandle_t handle, uint8_t co uint32_t element_type; if (!decompress_u32(&custom_modifiers_blob, &custom_modifiers_blob_len, &element_type)) return mdbpr_InvalidBlob; - + if (element_type != ELEMENT_TYPE_CMOD_OPT && element_type != ELEMENT_TYPE_CMOD_REQD) break; @@ -313,7 +328,7 @@ md_blob_parse_result_t md_parse_local_constant_sig(mdhandle_t handle, uint8_t co uint32_t element_type; if (!decompress_u32(&custom_modifiers_blob, &custom_modifiers_blob_len, &element_type)) return mdbpr_InvalidBlob; - + if (element_type != ELEMENT_TYPE_CMOD_OPT && element_type != ELEMENT_TYPE_CMOD_REQD) break; @@ -322,7 +337,7 @@ md_blob_parse_result_t md_parse_local_constant_sig(mdhandle_t handle, uint8_t co uint32_t cindex; if (!decompress_u32(&custom_modifiers_blob, &custom_modifiers_blob_len, &cindex)) return mdbpr_InvalidBlob; - + mdtable_id_t table; uint32_t row_id; // Technically the spec defines this as a TypeDefOrRefOrSpecEncoded token, @@ -330,14 +345,14 @@ md_blob_parse_result_t md_parse_local_constant_sig(mdhandle_t handle, uint8_t co // TypeDefOrRefOrSpec encoding. if (!decompose_coded_index(cindex, mdtc_idx_coded | InsertCodedIndex(mdci_TypeDefOrRef), &table, &row_id)) return mdbpr_InvalidBlob; - + local_constant_sig->custom_modifiers[i].type = CreateTokenType(table) | row_id; } uint32_t type_code; if (!decompress_u32(&blob, &blob_len, &type_code)) return mdbpr_InvalidBlob; - + uint32_t constant_type_index; mdtable_id_t constant_type_table; uint32_t constant_type_row; @@ -444,7 +459,7 @@ md_blob_parse_result_t md_parse_local_constant_sig(mdhandle_t handle, uint8_t co break; } } - + if (blob_len == 0) { local_constant_sig->constant_kind = mdck_PrimitiveConstant; @@ -482,7 +497,7 @@ static uint32_t get_num_imports(uint8_t const* blob, size_t blob_len) uint8_t kind; if (!read_u8(&blob, &blob_len, &kind)) return UINT32_MAX; - + uint32_t raw; switch (kind) { @@ -563,10 +578,10 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, uint8_t kind; if (!read_u8(&blob, &blob_len, &kind)) return mdbpr_InvalidBlob; - + // Zero out this import entry. memset(&imports->imports[i], 0, sizeof(imports->imports[i])); - + imports->imports[i].kind = kind; uint32_t raw; switch (kind) @@ -596,10 +611,10 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, uint32_t row_id; if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!decompose_coded_index(raw, mdtc_idx_coded | InsertCodedIndex(mdci_TypeDefOrRef), &table, &row_id)) return mdbpr_InvalidBlob; - + imports->imports[i].target_type = CreateTokenType(table) | row_id; break; } @@ -607,7 +622,7 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, case mdidk_ImportXmlNamespace: if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!try_get_blob(cxt, raw, (uint8_t const**)&imports->imports[i].alias, &imports->imports[i].alias_len)) return mdbpr_InvalidBlob; @@ -620,34 +635,34 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, case mdidk_ImportAssemblyReferenceAlias: if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!try_get_blob(cxt, raw, (uint8_t const**)&imports->imports[i].alias, &imports->imports[i].alias_len)) return mdbpr_InvalidBlob; break; case mdidk_AliasAssemblyReference: if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!try_get_blob(cxt, raw, (uint8_t const**)&imports->imports[i].alias, &imports->imports[i].alias_len)) return mdbpr_InvalidBlob; if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + imports->imports[i].assembly = CreateTokenType(mdtid_AssemblyRef) | raw; break; case mdidk_AliasAssemblyNamespace: if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!try_get_blob(cxt, raw, (uint8_t const**)&imports->imports[i].alias, &imports->imports[i].alias_len)) return mdbpr_InvalidBlob; if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + imports->imports[i].assembly = CreateTokenType(mdtid_AssemblyRef) | raw; - + if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; @@ -658,7 +673,7 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, { if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!try_get_blob(cxt, raw, (uint8_t const**)&imports->imports[i].alias, &imports->imports[i].alias_len)) return mdbpr_InvalidBlob; @@ -666,10 +681,10 @@ md_blob_parse_result_t md_parse_imports(mdhandle_t handle, uint8_t const* blob, uint32_t row_id; if (!decompress_u32(&blob, &blob_len, &raw)) return mdbpr_InvalidBlob; - + if (!decompose_coded_index(raw, mdtc_idx_coded | InsertCodedIndex(mdci_TypeDefOrRef), &table, &row_id)) return mdbpr_InvalidBlob; - + imports->imports[i].target_type = CreateTokenType(table) | row_id; break; } diff --git a/src/inc/dnmd_pdb.h b/src/inc/dnmd_pdb.h index 18146bfd..e1cfa9c4 100644 --- a/src/inc/dnmd_pdb.h +++ b/src/inc/dnmd_pdb.h @@ -97,7 +97,7 @@ typedef struct md_local_constant_sig__ size_t value_len; uint32_t custom_modifier_count; - + struct { bool required;