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

Fix crash when $ sign is in external user ID #1589

Merged
merged 1 commit into from
May 16, 2022
Merged

Conversation

nan-li
Copy link
Contributor

@nan-li nan-li commented May 16, 2022

Description

One Line Summary

Fix (1) a crash when a user has a dollar sign ($) in the external_user_id, and (2) only un-escape forward slashes in the external_user_id and not from others values such as timezone which can have a value with a slash like England/London.

Question for Reviewers on Better Regex

I couldn't find the right regex that would match only $1$\/abc\/de$f\/ from a string like the following. The previous regex of (?<=\"external_user_id\":\").*\\\\/.*?(?=\",|\"\\}) would result in $1$\/abc\/de$f\/","app_id":"b4f7","timezone":"$Europe\/London

{"external_user_id":"$1$\/abc\/de$f\/","app_id":"b4f7","timezone":"$Europe\/London"}

So I just matched the value of the external user ID, regardless of having any slashes in the value, and went from there.

Details

Motivation

A customer reported crashes when using a dollar sign ($) in an external user ID. Examples of the exception raised are:

Illegal group reference
java.lang.IllegalArgumentException: Illegal group reference
	at java.base/java.util.regex.Matcher.appendExpandedReplacement(Matcher.java:1068)
	at java.base/java.util.regex.Matcher.appendReplacement(Matcher.java:998)
	at java.base/java.util.regex.Matcher.replaceAll(Matcher.java:1182)
No group 1
java.lang.IndexOutOfBoundsException: No group 1
	at java.base/java.util.regex.Matcher.start(Matcher.java:483)
	at java.base/java.util.regex.Matcher.appendExpandedReplacement(Matcher.java:1091)
	at java.base/java.util.regex.Matcher.appendReplacement(Matcher.java:998)
	at java.base/java.util.regex.Matcher.replaceAll(Matcher.java:1182)

Related PRs

JSONObject.toString() will escape any forward slashes / with \/, and this will be sent in a request, and show up in the dashboard as \/. A previous related PR was made to to "unescape" this for a customer request where it is used in external user ID: #1478.

Scope and Background

Affects JSON serialization when sending the json string in a request, and in cases where there are forward slashes in an external user ID, those slashes are not escaped. After the changes in the previous PR mentioned above, we may have inadvertently been escaping timezone for many requests, but it doesn't seem to have been any ill effects.

  • Extracted the logic from the rest client to a helper method called toUnescapedEUIDString().

  • If a user has a dollar sign ($) in the external user ID, and our code is trying to escape the forward slashes via a string replacement, this will cause a crash as $ has a non-literal meaning when used in the replacement string. The solution is to call quoteReplacement to escape any $ or \ signs. See https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String-

  • Also fix the pattern matching for external user ID. Previously in a JSONObject like {"app_id": "abc", "external_user_id": "user1", "timezone": "Europe/London"}, the regex would match user1", "timezone": "Europe/London, grabbing the forward slash in ANY values that come after the external_user_id. This can lead to the above crash even if the user does not have any forward slashes themselves (because it can come from timezone). See https://regexr.com/6lmm0. This is fixed to match the external user ID value only.

  • There may now be more calls to String methods than necessary as the method now finds the value for external_user_id in the JSON string first, and regardless of whether it has forward slashes or not, we replace all instances of \/ with / (just no changes happen if it doesn't exist in the string). There is probably a better regex to use, but after trying for a while, I couldn't come up with it.

Testing

Unit testing

Added unit tests for the method toUnescapedEUIDString(), with different JSON values. The testing was primarily done via unit testing and examining the values throughout the life of the method call.

Manual testing

No pertinent manual testing.

Affected code checklist

  • Notifications
    • Display
    • Open
    • Push Processing
    • Confirm Deliveries
  • Outcomes
  • Sessions
  • In-App Messaging
  • REST API requests
  • Public API changes
  • Requests

Checklist

Overview

  • I have filled out all REQUIRED sections above
  • PR does one thing
  • Any Public API changes are explained in the PR details and conform to existing APIs

Testing

  • I have included test coverage for these changes, or explained why they are not needed
  • All automated tests pass, or I explained why that is not possible
  • I have personally tested this on my device, or explained why that is not possible

Final pass

  • Code is as readable as possible.
  • I have reviewed this PR myself, ensuring it meets each checklist item

This change is Reviewable

@nan-li nan-li changed the title Fix crash from $ in external user ID Fix crash when $ sign is in external user ID May 16, 2022
@nan-li nan-li marked this pull request as ready for review May 16, 2022 02:42
@nan-li nan-li requested review from adamschlesinger and a team May 16, 2022 02:42
* If a user has a dollar sign ($) in the external user ID, and our code is trying to escape the forward slashes via a string replacement, this will cause a crash as `$` has a non-literal meaning when used in the replacement string. The solution is to call `quoteReplacement` to escape any $ or \ signs. See https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String-

* Also fix the pattern matching for external user ID. Previously in a JSONObject like {"app_id": "abc", "external_user_id": "user1", "timezone": "Europe/London"}, the regex would match `def", "timezone": "Europe/London`, grabbing the forward slash in ANY values that come after the external_user_id. Fix this to match the external user ID value only.
@nan-li nan-li force-pushed the fix/euid_with_dollar_sign branch from f3fe50f to 1023b01 Compare May 16, 2022 20:15
Copy link
Member

@jkasten2 jkasten2 left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 4 of 4 files at r1, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @adamschlesinger)

@nan-li nan-li merged commit a6295ad into main May 16, 2022
@nan-li nan-li deleted the fix/euid_with_dollar_sign branch May 16, 2022 23:20
@jkasten2 jkasten2 mentioned this pull request May 18, 2022
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