Skip to content
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

Add support for reflection access filter #1905

Merged

Conversation

Marcono1234
Copy link
Collaborator

Adds a ReflectionAccessFilter which allows preventing to use the reflection based type adapter by accident, instead throwing an exception. This is quite useful to avoid depending on Java platform implementation details.

A use case where this would help is stripe/stripe-java#1197, that pull request adds a check whether a returned adapter is com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; the addition of a ReflectionAccessFilter would allow implementing this without having to rely on Gson internal implementation details.

In the future it would probably be good to apply some of these access filters by default since it appears users are often by accident depending on implementation details, or are not aware of the consequences of this. However, the way ReflectionAccessFilter is designed would still allow overwriting this by registering a filter which returns FilterResult.ALLOW for all classes, in case users for some reason want to serialize or deserialize Java platform classes using reflection.
Moshi by default prevents reflective access for platform classes, see internal Util.isPlatformType(Class) and its callers.

@google-cla google-cla bot added the cla: yes label Jun 4, 2021
@Marcono1234
Copy link
Collaborator Author

Marcono1234 commented Aug 12, 2021

Alternatively FilterResult could be a regular class with a nullable String filterName and a FilterResultType type, where FilterResultType would be an enum with ALLOW, INDECISIVE, BLOCK_INACCESSIBLE and BLOCK_ALL.
Then a filter could optionally specify its name (for example "platform type filter") for the filter result. This could help with debugging and would allow including it in the message of the exception thrown when not allowed reflective access occurs.

But I am not sure if this is worth it. What do you think?

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

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

Sorry for taking so long to get to this. I think this is an excellent addition. Accidental reflective access seems to be a major problem with Gson, and this will go some way towards mitigating that.

If you merge to HEAD I will try running this against Google's internal tests. I don't really expect any failures but we are sometimes surprised. Feel free to do just the merge initially and hold off on the documentation changes I suggested, until we know the results. Or go ahead and make them, as you prefer.

@Marcono1234
Copy link
Collaborator Author

Have improved the documentation and fixed some issues with the previous implementation. I chose a slightly different wording for the sentences describing the standard platform packages. Please let me know if it is alright like this.

As mentioned in #1905 (comment), should this be extended to support describing which filter returned the final result? Or do you think that is not worth it?

@@ -101,6 +102,7 @@
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
private final LinkedList<ReflectionAccessFilter> reflectionFilters = new LinkedList<ReflectionAccessFilter>();
Copy link
Member

Choose a reason for hiding this comment

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

We're on Java 7 now, right? So we should be able to use new LinkedList<>(), and similarly in other places in the PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point! I completely forgot that Java 7 added that feature already. Would you mind if I create a separate PR which replaces all redundant type arguments with the diamond operator, and include these changes there?

Copy link
Member

Choose a reason for hiding this comment

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

Seems fair.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks! Have created #2104 for that.

@eamonnmcmanus
Copy link
Member

Google's internal tests pass with this change, so we can merge it once the conflicts have been resolved and the remaining minor comments addressed.

For Java < 9, AccessibleObject.canAccess is not available and therefore checks
might pass even if object is not accessible, causing IllegalAccessException
later.
@Marcono1234
Copy link
Collaborator Author

Thanks for running this against Google's internal tests! Just to verify: You do not think that supporting specifying which filter returned a result (see #1905 (comment)) is worth it, correct?

I have added one commit improving IllegalAccessException handling. Currently when Gson users use Java < 9, but use FilterResult.BLOCK_INACCESSIBLE, they might run into IllegalAccessException because ReflectionAccessFilterHelper.canAccess(AccessibleObject, Object) won't validate whether the object is accessible. Do you think that is acceptable, or should it try to emulate the access check (but in a simplified way because package-private and protected checks are irrelevant because Gson is in a different package)?

@Marcono1234
Copy link
Collaborator Author

@eamonnmcmanus, what do you think?

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

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

Sorry, I lost track of this.

@@ -101,6 +102,7 @@
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
private final LinkedList<ReflectionAccessFilter> reflectionFilters = new LinkedList<ReflectionAccessFilter>();
Copy link
Member

Choose a reason for hiding this comment

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

Seems fair.

sgammon added a commit to elide-dev/elide that referenced this pull request Jan 15, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [com.google.code.gson:gson-parent](https://togithub.com/google/gson) |
`2.9.0` -> `2.10.1` |
[![age](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson-parent/2.10.1/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson-parent/2.10.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson-parent/2.10.1/compatibility-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson-parent/2.10.1/confidence-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/)
|
| [com.google.code.gson:gson](https://togithub.com/google/gson) |
`2.9.0` -> `2.10.1` |
[![age](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson/2.10.1/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson/2.10.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson/2.10.1/compatibility-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/maven/com.google.code.gson:gson/2.10.1/confidence-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/)
|

---

### ⚠ Dependency Lookup Warnings ⚠

Warnings were logged while processing this repo. Please check the
Dependency Dashboard for more information.

---

### Release Notes

<details>
<summary>google/gson</summary>

###
[`v2.10`](https://togithub.com/google/gson/blob/HEAD/CHANGELOG.md#Version-210)

- Support for serializing and deserializing Java records, on Java ≥ 16.
([google/gson#2201)
- Add `JsonArray.asList` and `JsonObject.asMap` view methods
([google/gson#2225)
- Fix `TypeAdapterRuntimeTypeWrapper` not detecting reflective
`TreeTypeAdapter` and `FutureTypeAdapter`
([google/gson#1787)
- Improve `JsonReader.skipValue()`
([google/gson#2062)
- Perform numeric conversion for primitive numeric type adapters
([google/gson#2158)
- Add `Gson.fromJson(..., TypeToken)` overloads
([google/gson#1700)
- Fix changes to `GsonBuilder` affecting existing `Gson` instances
([google/gson#1815)
- Make `JsonElement` conversion methods more consistent and fix javadoc
([google/gson#2178)
- Throw `UnsupportedOperationException` when `JsonWriter.jsonValue` is
not supported
([google/gson#1651)
- Disallow `JsonObject` `Entry.setValue(null)`
([google/gson#2167)
- Fix `TypeAdapter.toJson` throwing AssertionError for custom
IOException
([google/gson#2172)
- Convert null to JsonNull for `JsonArray.set`
([google/gson#2170)
- Fixed nullSafe usage.
([google/gson#1555)
- Validate `TypeToken.getParameterized` arguments
([google/gson#2166)
- Fix [#&#8203;1702](https://togithub.com/google/gson/issues/1702):
Gson.toJson creates CharSequence which does not implement toString
([google/gson#1703)
- Prefer existing adapter for concurrent `Gson.getAdapter` calls
([google/gson#2153)
- Improve `ArrayTypeAdapter` for `Object[]`
([google/gson#1716)
- Improve `AppendableWriter` performance
([google/gson#1706)

###
[`v2.9.1`](https://togithub.com/google/gson/blob/HEAD/CHANGELOG.md#Version-291)

- Make `Object` and `JsonElement` deserialization iterative rather than

recursi[google/gson#1912)
- Added parsing support for enum that has overridden toString() method
([google/gson#1950)
- Removed support for building Gson with Gradle
([google/gson#2081)
- Removed obsolete `codegen` hierarchy
([google/gson#2099)
- Add support for reflection access filter
([google/gson#1905)
- Improve `TypeToken` creation validation
([google/gson#2072)
- Add explicit support for `float` in `JsonWriter`
([google/gson#2130,
[google/gson#2132)
- Fail when parsing invalid local date
([google/gson#2134)

Also many small improvements to javadoc.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/elide-dev/v3).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xMDIuMCIsInVwZGF0ZWRJblZlciI6IjM0LjEwMi4wIn0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants