Skip to content

[JIT] Disallow plain List type annotation without arg#38130

Closed
SplitInfinity wants to merge 1 commit intopytorch:masterfrom
SplitInfinity:segfault
Closed

[JIT] Disallow plain List type annotation without arg#38130
SplitInfinity wants to merge 1 commit intopytorch:masterfrom
SplitInfinity:segfault

Conversation

@SplitInfinity
Copy link
Copy Markdown

@SplitInfinity SplitInfinity commented May 8, 2020

Summary
This commit detects and prohibits the case in which typing.List is
used as an annotation without a type argument (i.e. typing.List[T]).
At present, typing.List is always assumed to have one argument, and
when it is used without one, typing.List.__args__[0] is nonempty and
set to some typing.TypeVar instance, which has no JIT type equivalent.
Consequently, trying to convert typing.List to a JIT type results in
a c10::ListType with nullptr for its element type, which can cause
a segmentation fault.

This is fixed by returning a ListType from
jit.annotations.try_ann_to_type only if the element type is converted
successfully to a JIT type and returning None otherwise.

Test Plan
I ran the code from the issue (#37530) that reported this problem and also ran some unit tests.

Before

$ python3 segfault.py 
Segmentation fault (core dumped)

After

$ python3 segfault.py 
Traceback (most recent call last):
...
RuntimeError: 
Unknown type name 'List':
  File "segfault.py", line 9
    @classmethod
    def cat(cls, box_lists: List):
                            ~~~~ <--- HERE
        return cls(torch.cat([x for x in box_lists]))
'Boxes.cat' is being compiled since it was called from 'Boxes'
  File "segfault.py", line 13
def f(t: torch.Tensor):
    b = Boxes(t)
        ~~~~~ <--- HERE
    c = Boxes(torch.tensor([3, 4]))
    return Boxes.cat([b, c])
'Boxes' is being compiled since it was called from 'f'
  File "segfault.py", line 13
def f(t: torch.Tensor):
    b = Boxes(t)
    ~~~~~~~~~~~ <--- HERE
    c = Boxes(torch.tensor([3, 4]))
    return Boxes.cat([b, c])

Fixes
This pull request fixes #37530.

@SplitInfinity SplitInfinity requested a review from apaszke as a code owner May 8, 2020 17:47
@SplitInfinity SplitInfinity requested review from eellison, suo and zdevito May 8, 2020 17:48
@facebook-github-bot facebook-github-bot added the oncall: jit Add this issue/PR to JIT oncall triage queue label May 8, 2020
@SplitInfinity
Copy link
Copy Markdown
Author

Note that an annotation of Dict with no key or value annotation can also cause a segmentation fault (for the same reason).

Copy link
Copy Markdown
Member

@suo suo left a comment

Choose a reason for hiding this comment

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

Nice! Can we add a test that asserts that a failure is properly thrown when we hit this condition? In particular, I want to see if the string frontend is affected by this failure as well.

Summary:
This commit detects and prohibits the case in which `typing.List` is
used as an annotation without a type argument (i.e. `typing.List[T]`).
At present, `typing.List` is always assumed to have one argument, and
when it is used without one, `typing.List.__args__[0]` is nonempty and
set to some `typing.TypeVar` instance, which has no JIT type equivalent.
Consequently, trying to convert `typing.List` to a JIT type results in
a `c10::ListType` with `nullptr` for its element type, which can cause
a segmentation fault.

This is fixed by returning a `ListType` from
`jit.annotations.try_ann_to_type` only if the element type is converted
successfully to a JIT type and returning `None` otherwise.

Test Plan:
I ran the code from the issue that reported this segmentation fault, and
also added some unit tests.
@SplitInfinity
Copy link
Copy Markdown
Author

I think both are affected because the problem is in the PythonResolver that is used either way:

  TypePtr resolveType(const std::string& name, const SourceRange& loc)
      override {
<some stuff>

    auto annotation_type = py::module::import("torch.jit.annotations")
                               .attr("try_ann_to_type")(obj, loc);
    if (!annotation_type.is_none()) {
      return py::cast<TypePtr>(annotation_type);
    }
    return resolveTypeFromObject(obj, loc);
  }

@SplitInfinity SplitInfinity requested a review from suo May 8, 2020 20:33
Copy link
Copy Markdown
Member

@suo suo left a comment

Choose a reason for hiding this comment

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

lgtm! minor comment inline

a: List = x.tolist()
return a

with self.assertRaisesRegex(RuntimeError, r"Unknown type name"):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

self.checkScriptRaisesRegex is a useful utility for doing this; it will check eager/source FE/ast FE and compare results.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No exception is raised in eager though, and there is no way to opt out of asserting that eager raises the exception too.

@SplitInfinity
Copy link
Copy Markdown
Author

Also, should we wait until someone tries to use an Dict annotation with no key/value types, or fix that now as well?

Copy link
Copy Markdown
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

@SplitInfinity has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Copy Markdown
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

@SplitInfinity has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Copy Markdown
Contributor

@SplitInfinity merged this pull request in 1456515.

SplitInfinity pushed a commit that referenced this pull request Sep 12, 2020
**Summary**
This commit extends the work done in #38130 and disallows plain
Python3-style `List` type annotations.

**Test Plan**
This commit extends `TestList.test_no_element_type_annotation` to the
Python3-style type annotation.

[ghstack-poisoned]
facebook-github-bot pushed a commit that referenced this pull request Sep 16, 2020
Summary:
Pull Request resolved: #44584

**Summary**
This commit extends the work done in #38130 and disallows plain
Python3-style `List` type annotations.

**Test Plan**
This commit extends `TestList.test_no_element_type_annotation` to the
Python3-style type annotation.

Test Plan: Imported from OSS

Reviewed By: gmagogsfm

Differential Revision: D23721514

Pulled By: SplitInfinity

fbshipit-source-id: 48957868286f44ab6d5bf5e1bf97f0a4ebf955df
xuzhao9 pushed a commit that referenced this pull request Sep 18, 2020
Summary:
Pull Request resolved: #44584

**Summary**
This commit extends the work done in #38130 and disallows plain
Python3-style `List` type annotations.

**Test Plan**
This commit extends `TestList.test_no_element_type_annotation` to the
Python3-style type annotation.

Test Plan: Imported from OSS

Reviewed By: gmagogsfm

Differential Revision: D23721514

Pulled By: SplitInfinity

fbshipit-source-id: 48957868286f44ab6d5bf5e1bf97f0a4ebf955df
laurentdupin pushed a commit to laurentdupin/pytorch that referenced this pull request Apr 24, 2026
Summary:
**Summary**
This commit detects and prohibits the case in which `typing.List` is
used as an annotation without a type argument (i.e. `typing.List[T]`).
At present, `typing.List` is always assumed to have one argument, and
when it is used without one, `typing.List.__args__[0]` is nonempty and
set to some `typing.TypeVar` instance, which has no JIT type equivalent.
Consequently, trying to convert `typing.List` to a JIT type results in
a `c10::ListType` with `nullptr` for its element type, which can cause
a segmentation fault.

This is fixed by returning a `ListType` from
`jit.annotations.try_ann_to_type` only if the element type is converted
successfully to a JIT type and returning `None` otherwise.

**Test Plan**
I ran the code from the issue (pytorch#37530) that reported this problem and also ran some unit tests.

*Before*
```
$ python3 segfault.py
Segmentation fault (core dumped)
```

*After*
```
$ python3 segfault.py
Traceback (most recent call last):
...
RuntimeError:
Unknown type name 'List':
  File "segfault.py", line 9
    classmethod
    def cat(cls, box_lists: List):
                            ~~~~ <--- HERE
        return cls(torch.cat([x for x in box_lists]))
'Boxes.cat' is being compiled since it was called from 'Boxes'
  File "segfault.py", line 13
def f(t: torch.Tensor):
    b = Boxes(t)
        ~~~~~ <--- HERE
    c = Boxes(torch.tensor([3, 4]))
    return Boxes.cat([b, c])
'Boxes' is being compiled since it was called from 'f'
  File "segfault.py", line 13
def f(t: torch.Tensor):
    b = Boxes(t)
    ~~~~~~~~~~~ <--- HERE
    c = Boxes(torch.tensor([3, 4]))
    return Boxes.cat([b, c])
```

**Fixes**
This pull request fixes pytorch#37530.
Pull Request resolved: pytorch#38130

Differential Revision: D21485284

Pulled By: SplitInfinity

fbshipit-source-id: 9b51ef6340485a24c8b7cfb85832d4668b8ac51a
laurentdupin pushed a commit to laurentdupin/pytorch that referenced this pull request Apr 24, 2026
Summary:
Pull Request resolved: pytorch#44584

**Summary**
This commit extends the work done in pytorch#38130 and disallows plain
Python3-style `List` type annotations.

**Test Plan**
This commit extends `TestList.test_no_element_type_annotation` to the
Python3-style type annotation.

Test Plan: Imported from OSS

Reviewed By: gmagogsfm

Differential Revision: D23721514

Pulled By: SplitInfinity

fbshipit-source-id: 48957868286f44ab6d5bf5e1bf97f0a4ebf955df
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged oncall: jit Add this issue/PR to JIT oncall triage queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

torch.jit.script segfault

4 participants