Skip to content

Class: don't route internal callers through the notModelled forName - #43

Draft
tautschnig wants to merge 1 commit into
masterfrom
fix-primitive-class-clinit
Draft

Class: don't route internal callers through the notModelled forName#43
tautschnig wants to merge 1 commit into
masterfrom
fix-primitive-class-clinit

Conversation

@tautschnig

Copy link
Copy Markdown
Collaborator

Class.forName's body is deliberately CProver.notModelled() + throw new AssertionError() (its singleton/lookup semantics are unimplemented) -- but getPrimitiveClass(String), getPrimitiveClass(int) and getSuperclass() still routed through it. getPrimitiveClass is called from every boxed-primitive (Integer. calls getPrimitiveClass("int")), so ANY program that autoboxes -- e.g. any use of HashMap<Integer, ...> -- failed verification with forName's spurious AssertionError before its own assertions were even considered.

Add a private cproverClassWithName factory (a fresh Class with the given name, exactly what forName's pre-notModelled body used to build) and route the three internal callers through it. forName itself stays notModelled for user code. isPrimitive()'s literal-pointer-equality trick is preserved: the factory receives the same constant string literals.

Verified with JBMC: HashMap/ArrayList put/get/size/enhanced-for probes now VERIFICATION SUCCESSFUL (previously failed in Integer.); Integer.TYPE.isPrimitive() and getName() prove; a deliberately-false HashMap property still fails (no vacuity).

Class.forName's body is deliberately CProver.notModelled() +
throw new AssertionError() (its singleton/lookup semantics are
unimplemented) -- but getPrimitiveClass(String), getPrimitiveClass(int)
and getSuperclass() still routed through it. getPrimitiveClass is called
from every boxed-primitive <clinit> (Integer.<clinit> calls
getPrimitiveClass("int")), so ANY program that autoboxes -- e.g. any use
of HashMap<Integer, ...> -- failed verification with forName's spurious
AssertionError before its own assertions were even considered.

Add a private cproverClassWithName factory (a fresh Class with the given
name, exactly what forName's pre-notModelled body used to build) and route
the three internal callers through it. forName itself stays notModelled
for user code. isPrimitive()'s literal-pointer-equality trick is preserved:
the factory receives the same constant string literals.

Verified with JBMC: HashMap/ArrayList put/get/size/enhanced-for probes now
VERIFICATION SUCCESSFUL (previously failed in Integer.<clinit>);
Integer.TYPE.isPrimitive() and getName() prove; a deliberately-false
HashMap property still fails (no vacuity).

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 29, 2026 00:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents internal java.lang.Class helpers (primitive-class lookup and getSuperclass()) from calling Class.forName(String), which is intentionally CProver.notModelled() + AssertionError in this model library. This avoids spurious verification failures triggered during boxed-primitive <clinit> execution (e.g., Integer.TYPE initialization).

Changes:

  • Add a private cproverClassWithName(String) factory to create Class instances with a known name without routing through forName.
  • Route getPrimitiveClass(String), getPrimitiveClass(int), and getSuperclass() through the new factory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 405 to +407
public Class getSuperclass(){
// TODO: here we assume no superclass which may not be correct
return Class.forName(null);
return cproverClassWithName(null);
@tautschnig
tautschnig marked this pull request as draft July 30, 2026 09:06
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.

2 participants