Skip to content

False positive SE_PREVENT_EXT_OBJ_OVERWRITE #2750

@rovarga

Description

@rovarga

The logic to detect readExternal() guards introduced in #2426 requires a very strict shape of the guard.

The first example is:

class Foo implements Externalizable {
  private Object result;
  private boolean initialized;

  @Override
  public final void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    if (initialized) {
      throw new IllegalStateException("already initialized");
    }

    // stuff and then ...
    result = new Object();
    initialized = true;
  }

  @java.io.Serial
  final Object readResolve() {
    return requireNonNull(result);
  }
}

This differs from GoodExternalizableTest only in the bytecode shape, code reachability remains exactly the same.

A second example, common when using Externalizable Serialization Proxies, is:

class Bar implements Externalizable {
  private Object result = null;

  @Override
  public final void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    if (result == null) {
      // stuff and then ...
      result = new Object();
    } else {
      throw new IllegalStateException("already initialized");
    }
  }

  @java.io.Serial
  final Object readResolve() {
    return requireNonNull(result);
  }
}

Here the difference is the use of IFNULL/IFNONNULL instead of IFEQ/IFNE to check state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions