Skip to content

Fix quoted Python attribute receivers - #159

Merged
ESultanik merged 2 commits into
trailofbits:masterfrom
1cbyc:1cbyc/155-unquote-attribute-receiver
Sep 9, 2026
Merged

ESultanik merged 2 commits into
trailofbits:masterfrom
1cbyc:1cbyc/155-unquote-attribute-receiver

Conversation

@1cbyc

@1cbyc 1cbyc commented Sep 9, 2026

Copy link
Copy Markdown

Closes #155.

PyObjAttribute checked the builtin object, leaving its receiver normalization branch unreachable. Check self.object so string receivers render as attribute names instead of quoted string literals.

Adds a focused output regression for the receiver and member rendering path.

Validation:

  • pytest -q (141 passed)
  • ruff check graphtage test docs bindist
  • make -C docs html (succeeds with two pre-existing duplicate-description warnings)
  • uv build

Co-authored-by: insisong emmanuelisaacnsisong@gmail.com

Co-authored-by: insisong <emmanuelisaacnsisong@gmail.com>
@1cbyc
1cbyc requested a review from ESultanik as a code owner September 9, 2026 13:39
@CLAassistant

CLAassistant commented Sep 9, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@ESultanik ESultanik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for this — the change is correct, and it is the right fix.

isinstance(object, StringNode) was asking whether the builtin type object is a StringNode, so the branch was unreachable and the receiver kept its quotes. Checking self.object makes it do what it was written to do. I confirmed the behavior against master: rendering PyObjAttribute(StringNode("package"), StringNode("member")) produces "package".member before your change and package.member after it, so the new test genuinely fails without the one-line fix rather than passing for an unrelated reason.

Asserting on the rendered output rather than on the quoted flag is the right level for this — it pins the behavior a reader actually cares about, and it would still catch a regression if the quoting decision moved elsewhere in the printing path. Using Printer(ansi_color=False) with a StringIO matches how the rest of the suite captures output.

One note for anyone reading this later: PyObjAttribute is a DataClassNode, and DataClassEdit has no print() override (#150), so edited attribute nodes still render without their syntax. That is a separate bug and out of scope here; this PR is correct on its own.

We cannot merge yet. The CLA check on this PR is still showing as not signed:

https://cla-assistant.io/trailofbits/graphtage?pullRequest=159

Once you sign it, the check will go green and we can land this. If you have already signed and the status has not updated, the recheck link in the CLA bot's comment usually clears it.

@1cbyc

1cbyc commented Sep 9, 2026

Copy link
Copy Markdown
Author
image it looks like this:

@1cbyc

1cbyc commented Sep 9, 2026

Copy link
Copy Markdown
Author

okay, it was my connection.

@ESultanik
ESultanik merged commit 5d84cbc into trailofbits:master Sep 9, 2026
2 checks passed
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.

PyObjAttribute.__init__ tests the builtin object instead of self.object

3 participants