Skip to content

Plug soundness hole for reach capabilities #20051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2024

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Mar 29, 2024

To prevent that a reach capability is undermined by passing in a local capability from the outside, we disallow function arguments where reach capabilities appear in contravariant or invariant positions.

New scheme:

Enforce an analogous restriction to the one for creating reach capabilities
for all values. The type of a value cannot both have a reach capability with variance >= 0 and at the same time a universal capability with variance <= 0.

@odersky odersky requested a review from Linyxus March 29, 2024 12:47
@odersky odersky assigned odersky and Linyxus and unassigned odersky Mar 29, 2024
@Linyxus
Copy link
Contributor

Linyxus commented Mar 29, 2024

I found a varation of this counter-example on this branch:

  import language.experimental.captureChecking
  trait File:
    def close(): Unit

  def withFile[R](path: String)(op: File^ => R): R = ???

  trait Foo[+X]:
    def use(x: File^): X
  class Bar extends Foo[File^]:
    def use(x: File^): File^ = x

  def bad(): Unit =
    val backdoor: Foo[File^] = new Bar
    val boom: Foo[File^{backdoor*}] = backdoor

    var escaped: File^{backdoor*} = null
    withFile("hello.txt"): f =>
      escaped = boom.use(f)
        // boom.use: (x: File^) -> File^{backdoor*}, it is a selection so reach capabilities are allowed
        // f: File^, so there is no reach capabilities

@odersky
Copy link
Contributor Author

odersky commented Mar 29, 2024

OK, so we have to tighten the screws further. My intuition is that the restrictions that prevent us from lowering cap to a reach capabaility should also apply to all other values that get reach capabilities through substitution.

Enforce an analogous restriction to the one for creating reach capabilities
for all values. The type of a value cannot both have a reach capability with variance
>= 0 and at the same time a universal capability with variance <= 0.
Plug soundness hole for reach capabilities
@odersky odersky force-pushed the plug-reaches-soundness branch from fd243f7 to f2b7c12 Compare March 31, 2024 11:33
@odersky
Copy link
Contributor Author

odersky commented Mar 31, 2024

The new scheme also excludes the second unsoundness example, and compiles stdlib and all previous pos tests successfully.

Copy link
Contributor

@Linyxus Linyxus left a comment

Choose a reason for hiding this comment

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

thanks, LGTM!

@Linyxus Linyxus merged commit cc55381 into scala:main Mar 31, 2024
@Linyxus Linyxus deleted the plug-reaches-soundness branch March 31, 2024 19:43
@Kordyjan Kordyjan added this to the 3.5.0 milestone May 10, 2024
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