From d0364dc39cba59e05a2051f8b107881879b8565c Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 15 Apr 2026 15:21:39 -0700 Subject: [PATCH] minor fixes for handling cyclic and corrupted types --- src/linker/lnk_debug_info.c | 35 ++++++++++++++++++-------------- src/linker/pdb_ext/msf_builder.c | 10 +++++++-- src/torture/torture_radlink.c | 5 +++-- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 76c3ad8b..2cdef26f 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -467,8 +467,8 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_fla U64 lf_idx = debug_p->count - (i + 1); CV_LeafHeader *lf = cv_debug_t_get_leaf_header(debug_p, lf_idx); if (lf->kind == CV_LeafKind_ENDPRECOMP) { + memory_write16(&lf->size, sizeof(lf->kind)); memory_write16(&lf->kind, CV_LeafKind_NOTYPE); - memory_write16(&lf->size, sizeof(CV_LeafKind)); break; } } @@ -602,14 +602,6 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf // init hasher blake3_hasher hasher; blake3_hasher_init(&hasher); - // hash leaf header - { - CV_LeafHeader header; - header.size = (U16)leaf.data.size; - header.kind = leaf.kind; - blake3_hasher_update(&hasher, &header, sizeof(header)); - } - // hash bytes around indices { U64 last_ti_off = 0; @@ -638,17 +630,23 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf } if (sub_ti >= debug_t->ti_ranges[sub_ti_n->source].max) { - Temp scratch = scratch_begin(0,0); + // discard type + U32 leaf_idx = curr_ti - debug_t->ti_ranges[curr_ti_source].min; + U8 *leaf_header = debug_t->data.str + debug_t->offsets[leaf_idx]; + memory_write16(leaf_header + OffsetOf(CV_LeafHeader, kind), CV_LeafKind_NOTYPE); + memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind)); - String8 out_of_bounds_data = push_str8f(scratch.arena, "out_of_bounds_ti_%u_in_%u", sub_ti, leaf_ref.obj_idx); - blake3_hasher_update(&hasher, out_of_bounds_data.str, out_of_bounds_data.size); + // reset hasher + blake3_hasher_init(&hasher); + // log error + Temp scratch = scratch_begin(0,0); String8 leaf_kind_str = cv_string_from_leaf_kind(leaf.kind); String8 error_msg = push_str8f(scratch.arena, "LF_%S(type_index: 0x%x) out of bounds type index 0x%x (leaf struct offset: 0x%llx)", leaf_kind_str, curr_ti, sub_ti, sub_ti_n->offset); lnk_error_obj(LNK_Error_InvalidTypeIndex, input->obj_arr[leaf_ref.obj_idx], "%S", error_msg); - scratch_end(scratch); - continue; + + break; } // discard type with a cyclic-ref @@ -660,6 +658,9 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf memory_write16(leaf_header + OffsetOf(CV_LeafHeader, kind), CV_LeafKind_NOTYPE); memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind)); + // reset hasher + blake3_hasher_init(&hasher); + // log error Temp scratch = scratch_begin(0,0); String8 leaf_kind_str = cv_string_from_leaf_kind(leaf.kind); @@ -667,7 +668,7 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf lnk_error_obj(LNK_Error_InvalidTypeIndex, input->obj_arr[leaf_ref.obj_idx], "%S", error_msg); scratch_end(scratch); - continue; + break; } // type index -> hash @@ -678,6 +679,10 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf blake3_hasher_update(&hasher, &sub_hash, sizeof(sub_hash)); } + // hash leaf header + CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_ref.leaf_idx); + blake3_hasher_update(&hasher, leaf_header, sizeof(*leaf_header)); + U64 hash; blake3_hasher_finalize(&hasher, (U8 *) &hash, sizeof(hash)); diff --git a/src/linker/pdb_ext/msf_builder.c b/src/linker/pdb_ext/msf_builder.c index af5e8305..b19560af 100644 --- a/src/linker/pdb_ext/msf_builder.c +++ b/src/linker/pdb_ext/msf_builder.c @@ -1224,7 +1224,7 @@ msf_data_from_sn(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn) String8 page = msf_data_from_pn(msf->page_data_list, msf->page_size, n->pn); if (acc.str + acc.size != page.str) { - if (acc.size > 0) { + if (acc.size) { str8_list_push(arena, &result, acc); } acc = page; @@ -1233,6 +1233,11 @@ msf_data_from_sn(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn) } } + if (acc.size) { + str8_list_push(arena, &result, acc); + MemoryZeroStruct(&acc); + } + if (n) { String8 page = msf_data_from_pn(msf->page_data_list, msf->page_size, n->pn); if (acc.str + acc.size != page.str) { @@ -1243,11 +1248,12 @@ msf_data_from_sn(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn) acc.size = Min(stream->size - result.total_size, acc.size); - if (acc.size > 0) { + if (acc.size) { str8_list_push(arena, &result, acc); } } + Assert(result.total_size == stream->size); return result; } diff --git a/src/torture/torture_radlink.c b/src/torture/torture_radlink.c index 62478a8b..ab332910 100644 --- a/src/torture/torture_radlink.c +++ b/src/torture/torture_radlink.c @@ -4594,7 +4594,7 @@ T_BeginTest(get_msf_stream_pages) String8List stream_data = msf_data_from_sn(arena, msf, sn); T_Ok(stream_data.total_size == stream_size); - T_Ok(stream_data.node_count == 11); + T_Ok(stream_data.node_count == 12); String8Array a = str8_array_from_list(arena, &stream_data); T_Ok(a.v[0].size == 0xffd000); @@ -4607,7 +4607,8 @@ T_BeginTest(get_msf_stream_pages) T_Ok(a.v[7].size == 0xffd000); T_Ok(a.v[8].size == 0x1000); T_Ok(a.v[9].size == 0xffe000); - T_Ok(a.v[10].size == 0x613001); + T_Ok(a.v[10].size == 0x613000); + T_Ok(a.v[11].size == 1); String8Node buf = *stream_data.first; U64 buf_pos = 0;