This is an archive of the discontinued LLVM Phabricator instance.

Fix Issue #61706
Needs ReviewPublic

Authored by jwnhy on Mar 26 2023, 9:21 AM.

Details

Summary

As described in #61706, the ValueObjectChild::UpdateValue(...) may underflow the unsigned m_bitfield_bit_offset.

This is due to that in ValueObjectChild::UpdateValue(...), the moved overhang_bytes only considers the bitfield_end - *type_bit_size. However, under certain cases, the m_bitfield_bit_offset may not strictly aligned to *type_bit_size, e.g. 27 < 32.

This results 27 - 32 = -5 underflows the unsigned uint8_t m_bitfield_bit_offset.

This patch fixes this issue by setting the overhang_bytes to the smaller value between bitfield_end - *type_bit_size and m_bitfield_bit_offset to avoid underflow.

This patch also resolves the issue that m_value.GetScalar() being moved over the bitfield boundary, which leads to the truncation issue and is not addressed in the previous patch.

I am quite new to this community, any helps/guidance are much appreciated.

Diff Detail

Event Timeline

jwnhy created this revision.Mar 26 2023, 9:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 26 2023, 9:21 AM
jwnhy requested review of this revision.Mar 26 2023, 9:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 26 2023, 9:21 AM
Michael137 added a subscriber: Michael137.EditedMar 26 2023, 9:28 AM

You might be interested in taking over/pinging the following patch instead, which makes the offset signed. Though there we had to force dwarf-2 in the tests, so it might be slightly different. But worth trying to see if that patch resolves this also

EDIT: sorry forgot to add patch link
https://reviews.llvm.org/D138197

jwnhy edited the summary of this revision. (Show Details)Mar 26 2023, 10:10 AM
jwnhy added a comment.EditedMar 26 2023, 5:52 PM

It seems this is more complicated than I originally thought.
My fix is also flawed when it comes the following program.
Let overhang_bytes = 0 will overflow the otherside by 1 bit and thus output a wrong value.

But changing everything to signed does not resolve this issue as the following line is a concern.

m_value.GetScalar() += m_byte_offset; // ValueObjectChild.cpp:181
#pragma pack(1)
struct  {
  signed long long f0 : 1;
  unsigned f5 : 32;
} g_96 = {1, 0xffffffff};
int main() {return 0;}

I kind of illustrated the current situation in this picture. I am not sure what will be the best practice to solve this issue right now.