[BUG]: LocatedHeaderDir is mutable, so callers can poison the cached header-directory lookup

Open Beginner friendly
#2,646 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
python
Domain
tooling

Research direction

Start at the LocatedHeaderDir definition and the locate_nvidia_header_directory() and find_nvidia_header_directory() entry points. Compare the implementation with _static_libs/find_static_lib.py and _static_libs/find_bitcode_lib.py, then run the cuda.pathfinder tests. Done means the result is immutable and hashable without changing the lookup behavior.

Written by the indexing model from the issue text.

Description

triage
Component

cuda.pathfinder

What happened?

locate_nvidia_header_directory() is @functools.cache-backed and returns LocatedHeaderDir, which is a plain (mutable) dataclass. The cache hands every caller the same object, so a write to abs_path on a returned instance changes what every later lookup of that libname returns for the rest of the process, including through the find_nvidia_header_directory() wrapper.

LocatedHeaderDir is also the only one of the three public Located* return types that behaves this way: LocatedStaticLib (_static_libs/find_static_lib.py) and LocatedBitcodeLib (_static_libs/find_bitcode_lib.py) are both @dataclass(frozen=True). As a side effect of not being frozen, LocatedHeaderDir is also unhashable, so it cannot be put in a set or used as a dict key the way its two siblings can.

Reproduction
from cuda.pathfinder import locate_nvidia_header_directory, find_nvidia_header_directory

first = locate_nvidia_header_directory("cudart")
print(first.abs_path)                                # e.g. /usr/local/cuda/include

first.abs_path = "/somewhere/else"                   # caller "normalizes" the result in place

print(locate_nvidia_header_directory("cudart").abs_path)  # /somewhere/else
print(find_nvidia_header_directory("cudart"))             # /somewhere/else
>>> LocatedHeaderDir.__dataclass_params__.frozen, LocatedHeaderDir.__hash__ is not None
(False, False)
>>> LocatedStaticLib.__dataclass_params__.frozen, LocatedStaticLib.__hash__ is not None
(True, True)
>>> LocatedBitcodeLib.__dataclass_params__.frozen, LocatedBitcodeLib.__hash__ is not None
(True, True)
Suggested fix

Make LocatedHeaderDir @dataclass(frozen=True) so it matches the other two public Located* types. The __post_init__ path normalization then needs object.__setattr__. Nothing inside cuda_pathfinder or its tests mutates a LocatedHeaderDir, so this is contained to the public type's contract.

Dominant language
Cython
Stars
3.4k
Forks
329
Avg merge
1d 21h
Merged PRs (30d)
113

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from NVIDIA/cuda-python

All issues in NVIDIA/cuda-python

Similar issues

More DevTools issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.