<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">This is not a general security problem, but rather an example of how code that is inside an encapsulation can violate that encapsulation.</p>
<p dir="auto">Because <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Agenda</code> is allowed to mention the type <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">MyList<Month.val></code> which includes the (package-private) type <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month.val</code>, it must be the case that <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Agenda</code> is inside the same package as <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month</code>.  Since <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month</code> has granted access rights to all package-mates, if there is a “leakage” of <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month.default</code> somewhere, it is only because someone in the same package as <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month</code> has given away that value.  In other words, it’s how the encapsulation is written, for better or worse.</p>
<p dir="auto">If the author of <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month</code> wants to distrust package-mates, that author should declare the companion type <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">private</code>, not package-private.  You can’t grant access to code you distrust, and then complain about security, unless you are pointing at yourself!</p>
<p dir="auto">This particular example does not stress autoboxing in any interesting way that I see.  Clearly if somebody has access to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month.val</code> they can then grab <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">Month.default</code> by one of several ways, and then it’s up to them to keep the secret safe, if it is in fact a secret to be kept safe.</p>
<p dir="auto">BTW, this example assumes specialized generics.  Since they don’t exist fully yet, except on paper, we are assuming properties of specialized generics that may not in fact turn out to be true.  But I assume that:</p>
<ul>
<li>
<p dir="auto">Any non-erased type argument, which is set to a privatized class, must be accessible to the code which mentions the type argument (as part of the generic type application).</p>
</li>
<li>
<p dir="auto">Any generic that uses non-erased type parameters which may be bound to privatized types should document how it materializes externally-visible default values and/or arrays of that type, if it in fact does this.  (Most won’t need to.)</p>
</li>
</ul>
<p dir="auto">Perhaps you are pointing to the fact that bugs in generic containers might leak non-constructed values from specialized generics?  (The missing call to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">checkIndex</code> allows an empty value to leak from <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">getFirst</code>.)  We should keep this in mind, I guess.  But note that the fault is not solely in the buggy generic, in your example:  There is also some fault in the client which passed a privatized type to a generic of unknown quality.</p>
<p dir="auto">If necessary, as part of the “opt in” for specialization we could add another layer of “opt in” to handle privatized type arguments.  There is always a reasonable fallback for <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">MyList<Month.val></code> if <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">MyList</code> is not expecting to handle privatized types.  The fallback is to partially erase <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">MyList<Month.val></code> to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">MyList<Month.ref></code>.  That would be a third, intermediate form of erasure:  Lift privatized types to their reference types.</p>
<p dir="auto">In fact, as I’ve noted before, this is a question for non-flat types as well, in the setting of specialized generics:  Perhaps specialized generics should <em>never</em> specialize on inaccessible type arguments of any sort, neither refs to non-public classes nor privatized vals.  It’s a fair question to ponder…</p>
<p dir="auto">If we <em>do</em> allow specialization on non-public type arguments, it’s probably on the grounds that the client “knows what he’s doing” and is consciously sharing access to the non-public type by mentioning it in a type argument.  The generic who gets a non-public type shared with it must handle it with due care, not immediately leaking it to the world.  It’s part of the user contract for specialized generics:  What are the rules for non-public types?</p>
<p dir="auto">— John</p>
<p dir="auto">On 25 Jul 2022, at 13:33, Remi Forax wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">One of the idea of encapsulating C.val is that even with a value class C with no good default, accessing C.val is useful.
<br>
That's true but a unfortunate consequence is that it makes leaking T in a generic code a security issue.</p>
<p dir="auto">It is in fact more secure to use two classes C and CFlat, one with no good default and the other which allow the default value, when using with generics.</p>
<p dir="auto">Here is an example, let say we have a value class Month (1 to 12) and an identity class Agenda that contains several months.
<br>
WE can declare Month like this, with a package-private value companion.</p>
<p dir="auto">value record Month(int value) {
<br>
  /*package-private*/ companion val;</p>
<p dir="auto">  public Month {
<br>
    if (value < 1 || value > 12) throw new IAE();
<br>
  }
<br>
}</p>
<p dir="auto">So we can flatten the Month when stored in a list</p>
<p dir="auto">class Agenda {
<br>
  private final MyList<Month.val> months = new MyList<>();</p>
<p dir="auto">  public void add(Hour hour) {
<br>
    Objects.requireNonNull(hour);
<br>
    months.add(hour);
<br>
  }</p>
<p dir="auto">  public Hour getFirst() {
<br>
    return months.isEmpty()? null: months.getFirst();
<br>
  }
<br>
}</p>
<p dir="auto">Is this code safe ? The trouble is that it depends on the implementation of MyList, by example with</p>
<p dir="auto">class MyList<E> {
<br>
  private E[] array = new E[16];
<br>
  private int size;</p>
<p dir="auto">  public boolean isEmpty() { return size == 0; }</p>
<p dir="auto">  public void add(E element) {
<br>
    array[size++] = element;
<br>
  }</p>
<p dir="auto">  public E getFirst() {
<br>
    // Objects.checkIndex(0, size);
<br>
    return array[0];
<br>
  }
<br>
}</p>
<p dir="auto">MyList.getFirst() leaks E.default, so the implementation of Agenda is not safe.
<br>
Using the encapsulation to hide C.val is only safe if the generics code never leak E.default.</p>
<p dir="auto">Weirdly, if i use different classes to represent C and C.val, i do not have that issue.</p>
<p dir="auto">class Agenda {
<br>
  value record MonthFlat(int value) {
<br>
    public companion val;
<br>
  }</p>
<p dir="auto">  private final MyList<MonthFlat> months = new MyList<>();</p>
<p dir="auto">  public void add(Hour hour) {
<br>
    Objects.requireNonNull(hour);
<br>
    months.add(new MonthFlat(hour.value()));
<br>
  }</p>
<p dir="auto">  public Hour getFirst() {
<br>
    return months.isEmpty()? null: new Month(months.getFirst().value);
<br>
  }
<br>
}</p>
<p dir="auto">because unlike the autoboxing conversion between Month.val to Month, the conversion from MonthFlat to Month does not bypass the constructor.</p>
<br></blockquote></div>
<div class="markdown" style="white-space: normal;">
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;">
<p dir="auto">Rémi</p>
</blockquote>

</div></div></body>

</html>