Skip to content

Clarify fromJson(Class) Javadoc: type registry does not exist - #1095

Open
Lyin-OTTF wants to merge 1 commit into
stleary:masterfrom
Lyin-OTTF:fix/gh-1076-fromjson-binding-javadoc
Open

Lyin-OTTF wants to merge 1 commit into
stleary:masterfrom
Lyin-OTTF:fix/gh-1076-fromjson-binding-javadoc

Conversation

@Lyin-OTTF

Copy link
Copy Markdown

Description

Fixes #1076.

The fromJson(Class) Javadoc documented a protection that was never implemented:

Only classes that are explicitly supported and registered within the JSONObject context can be deserialized ... This ensures that only a limited and controlled set of types can be instantiated from JSON for safety and predictability.

There is no registry anywhere in the source. The method calls setAccessible(true) on every non-static declared field and writes it when its name matches a key in the JSON, so private, transient and @JSONPropertyIgnore-exposed fields are all populated from whatever keys the input contains. The @throws IllegalArgumentException line was wrong too: nothing in the method throws it, failures surface as JSONException.

Since the binding rules themselves are already released, this PR leaves them untouched, per #1076 (comment), and only makes the Javadoc match reality:

  • the registry paragraph is replaced with what actually happens, including a note that key-driven binding means untrusted JSON should be validated, or reduced to the expected keys, before being passed in
  • @throws IllegalArgumentException is replaced with the JSONException the method throws when the class has no accessible no-arg constructor or a field cannot be set
  • the static fromJson(String, Class) now links to those rules instead of silently inheriting them

Tests

JSONObjectTest#jsonObjectParseFromJson_10 binds a bean with a private admin, a private tenantId, a transient sessionKey and a superAdmin hidden behind an @JSONPropertyIgnore getter. It asserts all four are populated, which is the behavior the Javadoc now describes. This is a characterization test: it passes before and after the change, and exists so the documentation cannot drift from the implementation again without a failing test.

mvn test
Tests run: 825, Failures: 0, Errors: 0, Skipped: 6

mvn javadoc:javadoc succeeds, so the new {@link} references and HTML are valid.

No behavior change.

The fromJson(Class) Javadoc claimed that only classes "explicitly supported
and registered within the JSONObject context" can be deserialized, and
declared an IllegalArgumentException for classes outside that set. No such
registry exists: fromJson instantiates any class with a no-arg constructor and
writes every non-static declared field whose name matches a JSON key, widening
access with setAccessible(true). Private and transient fields are populated,
and JSONPropertyIgnore does not apply because it only suppresses the bean to
JSONObject direction.

The binding rules are already released, so changing them here would break
existing users. Instead document what actually happens, point out that binding
is driven by whatever keys the JSON contains, and replace the non-existent
IllegalArgumentException with the JSONException the method really throws.

Adds JSONObjectTest#jsonObjectParseFromJson_10 to pin the current binding
behavior so the documentation cannot drift from the implementation again.

Fixes stleary#1076
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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.

Security: fromJson() performs unrestricted reflective field binding (mass assignment); Javadoc claims a non-existent allowlist

1 participant