Skip to content

Fix TypeDesc.__str__ crash on certain DIEs - #664

Closed
celskeggs wants to merge 1 commit into
eliben:mainfrom
celskeggs:celskeggs-patch-1
Closed

Fix TypeDesc.__str__ crash on certain DIEs#664
celskeggs wants to merge 1 commit into
eliben:mainfrom
celskeggs:celskeggs-patch-1

Conversation

@celskeggs

Copy link
Copy Markdown

When my team attempted to upgrade from pyelftools==0.32 to pyelftools==0.33, we found that some of our binary inspection tools were broken by the upgrade. In particular, elftools.dwarf.datatype_cpp.describe_cpp_datatype crashes when fed certain inputs, such as:

DIE DW_TAG_variable, size=18, has_children=False
    |DW_AT_specification:  AttributeValue(name='DW_AT_specification', form='DW_FORM_ref4', value=97, raw_value=97, offset=332360, indirection_length=0)
    |DW_AT_location    :  AttributeValue(name='DW_AT_location', form='DW_FORM_exprloc', value=[161, 61, 148, 1, 52, 30, 48, 34, 159], raw_value=[161, 61, 148, 1, 52, 30, 48, 34, 159], offset=332364, indirection_length=0)
    |DW_AT_linkage_name:  AttributeValue(name='DW_AT_linkage_name', form='DW_FORM_strx2', value=b'_ZN9Va416x0Os12TimerRawTime10s_timer_hiE', raw_value=4207, offset=332374, indirection_length=0)

Here is the specific error we encountered:

File /workspaces/<...>/inspection.py:1014, in get_symbol_location_by_linkage(dwarfinfo, link_name, search_tag, verbose, follow_reference)
   1013 file_info_attr = variable_die.attributes.get("DW_AT_decl_file")
-> 1014 ctype = elftools.dwarf.datatype_cpp.describe_cpp_datatype(variable_die)
   1015 if str(ctype) == "None":

File /usr/local/lib/python3.12/site-packages/elftools/dwarf/datatype_cpp.py:27, in describe_cpp_datatype(var_die)
     26 def describe_cpp_datatype(var_die: DIE) -> str:
---> 27     return str(parse_cpp_datatype(var_die))

File /usr/local/lib/python3.12/site-packages/elftools/dwarf/datatype_cpp.py:156, in TypeDesc.__str__(self)
    151 def __str__(self) -> str:
    152     # Some reference points from dwarfdump:
    153     # const->pointer->const->char = const char *const
    154     # const->reference->const->int = const const int &
    155     # const->reference->int = const int &
--> 156     name = str(self.name)
    157     mods = self.modifiers

AttributeError: 'TypeDesc' object has no attribute 'name'

This appears likely to be related to this change:

v0.32...v0.33#diff-266d689a3956c69d57de4c617fb8e426c32469e6e7f4f0459df93d7fc6b5ae65L133-R151

Since TypeDesc.name is no longer being initialized to None, there are code paths where it does not get initialized before __str__ is called, which results in the AttributeError shown above. I propose to resume initializing the variable to None, which fixes the crash for us.

@celskeggs
celskeggs marked this pull request as ready for review June 19, 2026 02:40
@eliben

eliben commented Jun 19, 2026

Copy link
Copy Markdown
Owner

@pmhahn PTAL - this is likely related to the typing changes

@eliben eliben left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR fails the type checker

However, simply initializing the name to the empty string should do the trick?

@celskeggs

Copy link
Copy Markdown
Author

I would have to look closer... I can imagine that change would make the type checker pass but I think it would also change the behavior of __str__; it would no longer return the string "None" in this case. We'll probably stick with 0.32 for now as a workaround, though, so I'm not sure when I'll have the chance to dig more into this.

@pmhahn pmhahn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My cd4da4b is the relevant change, which no longer initializes self.name = None

Can you please provide a (minimal) sample of the ELF file, so we can add it to the test suite? It's probably enough if you can publish the C-code, which generates such a problematic DIE, so we can add the C code as a minimal example, compile it ourself and add the resulting ELF file to the repository.


class ClassDesc:
def __init__(self) -> None:
self.scopes: tuple[str, ...] = ()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required because of line 204, where the name: str | None are collected:

Suggested change
self.scopes: tuple[str | None, ...] = ()

@eliben eliben closed this in e5fa2a4 Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants