From 3c23bc2ac9064de30140786719492c8497a8b639 Mon Sep 17 00:00:00 2001 From: Zihe Jia Date: Tue, 13 Jun 2023 00:07:55 -0700 Subject: [PATCH] fix Null reference used for synchronization (monitor-enter) --- .../MixpanelReactNativeModule.java | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/android/src/main/java/com/mixpanel/reactnative/MixpanelReactNativeModule.java b/android/src/main/java/com/mixpanel/reactnative/MixpanelReactNativeModule.java index 45b50348..aba52321 100644 --- a/android/src/main/java/com/mixpanel/reactnative/MixpanelReactNativeModule.java +++ b/android/src/main/java/com/mixpanel/reactnative/MixpanelReactNativeModule.java @@ -44,6 +44,10 @@ public void initialize(String token, boolean trackAutomaticEvents, boolean optOu @ReactMethod public void setServerURL(final String token, final String serverURL, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.setServerURL(serverURL); promise.resolve(null); @@ -53,6 +57,10 @@ public void setServerURL(final String token, final String serverURL, Promise pro @ReactMethod public void setUseIpAddressForGeolocation(final String token, boolean useIpAddressForGeolocation, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.setUseIpAddressForGeolocation(useIpAddressForGeolocation); promise.resolve(null); @@ -62,6 +70,10 @@ public void setUseIpAddressForGeolocation(final String token, boolean useIpAddre @ReactMethod public void setLoggingEnabled(final String token, boolean enableLogging, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.setEnableLogging(enableLogging); promise.resolve(null); @@ -71,6 +83,10 @@ public void setLoggingEnabled(final String token, boolean enableLogging, Promise @ReactMethod public void hasOptedOutTracking(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { promise.resolve(instance.hasOptedOutTracking()); } @@ -79,6 +95,10 @@ public void hasOptedOutTracking(final String token, Promise promise) { @ReactMethod public void optInTracking(final String token, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.optInTracking(); promise.resolve(null); @@ -88,6 +108,10 @@ public void optInTracking(final String token, Promise promise) throws JSONExcept @ReactMethod public void optOutTracking(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.optOutTracking(); promise.resolve(null); @@ -97,6 +121,10 @@ public void optOutTracking(final String token, Promise promise) { @ReactMethod public void identify(final String token, final String distinctId, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.identify(distinctId); promise.resolve(null); @@ -106,6 +134,10 @@ public void identify(final String token, final String distinctId, Promise promis @ReactMethod public void getDistinctId(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { promise.resolve(instance.getDistinctId()); } @@ -114,6 +146,10 @@ public void getDistinctId(final String token, Promise promise) { @ReactMethod public void getDeviceId(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { promise.resolve(instance.getAnonymousId()); } @@ -122,6 +158,10 @@ public void getDeviceId(final String token, Promise promise) { @ReactMethod public void track(final String token, final String eventName, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject eventProperties = ReactNativeHelper.reactToJSON(properties); AutomaticProperties.appendLibraryProperties(eventProperties); @@ -133,6 +173,10 @@ public void track(final String token, final String eventName, ReadableMap proper @ReactMethod public void registerSuperProperties(final String token, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject superProperties = ReactNativeHelper.reactToJSON(properties); instance.registerSuperProperties(superProperties); @@ -143,6 +187,10 @@ public void registerSuperProperties(final String token, ReadableMap properties, @ReactMethod public void registerSuperPropertiesOnce(final String token, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject superProperties = ReactNativeHelper.reactToJSON(properties); instance.registerSuperPropertiesOnce(superProperties); @@ -153,6 +201,10 @@ public void registerSuperPropertiesOnce(final String token, ReadableMap properti @ReactMethod public void unregisterSuperProperty(final String token, String superPropertyName, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.unregisterSuperProperty(superPropertyName); promise.resolve(null); @@ -162,6 +214,10 @@ public void unregisterSuperProperty(final String token, String superPropertyName @ReactMethod public void union(final String token, String name, ReadableArray value, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONArray propertyValue = ReactNativeHelper.reactToJSON(value); instance.getPeople().union(name, propertyValue); @@ -172,6 +228,10 @@ public void union(final String token, String name, ReadableArray value, Promise @ReactMethod public void getSuperProperties(final String token, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { promise.resolve(ReactNativeHelper.convertJsonToMap(instance.getSuperProperties())); } @@ -180,6 +240,10 @@ public void getSuperProperties(final String token, Promise promise) throws JSONE @ReactMethod public void clearSuperProperties(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.clearSuperProperties(); promise.resolve(null); @@ -189,6 +253,10 @@ public void clearSuperProperties(final String token, Promise promise) { @ReactMethod public void alias(final String token, String alias, String original, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.alias(alias, original); promise.resolve(null); @@ -198,6 +266,10 @@ public void alias(final String token, String alias, String original, Promise pro @ReactMethod public void reset(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.reset(); promise.resolve(null); @@ -207,6 +279,10 @@ public void reset(final String token, Promise promise) { @ReactMethod public void flush(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.flush(); promise.resolve(null); @@ -216,6 +292,10 @@ public void flush(final String token, Promise promise) { @ReactMethod public void timeEvent(final String token, final String eventName, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.timeEvent(eventName); promise.resolve(null); @@ -225,6 +305,10 @@ public void timeEvent(final String token, final String eventName, Promise promis @ReactMethod public void eventElapsedTime(final String token, final String eventName, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { promise.resolve(instance.eventElapsedTime(eventName)); } @@ -233,6 +317,10 @@ public void eventElapsedTime(final String token, final String eventName, Promise @ReactMethod public void set(final String token, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject sendProperties = ReactNativeHelper.reactToJSON(properties); AutomaticProperties.appendLibraryProperties(sendProperties); @@ -244,6 +332,10 @@ public void set(final String token, ReadableMap properties, Promise promise) thr @ReactMethod public void unset(final String token, String propertyName, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().unset(propertyName); promise.resolve(null); @@ -253,6 +345,10 @@ public void unset(final String token, String propertyName, Promise promise) { @ReactMethod public void setOnce(final String token, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject sendProperties = ReactNativeHelper.reactToJSON(properties); AutomaticProperties.appendLibraryProperties(sendProperties); @@ -264,6 +360,10 @@ public void setOnce(final String token, ReadableMap properties, Promise promise) @ReactMethod public void trackCharge(final String token, double charge, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject transactionValue = ReactNativeHelper.reactToJSON(properties); instance.getPeople().trackCharge(charge, transactionValue); @@ -274,6 +374,10 @@ public void trackCharge(final String token, double charge, ReadableMap propertie @ReactMethod public void clearCharges(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().clearCharges(); promise.resolve(null); @@ -284,6 +388,10 @@ public void clearCharges(final String token, Promise promise) { public void increment(final String token, ReadableMap properties, Promise promise) { Map incrementProperties = ReactNativeHelper.toMap(properties); MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().increment(incrementProperties); promise.resolve(null); @@ -293,6 +401,10 @@ public void increment(final String token, ReadableMap properties, Promise promis @ReactMethod public void append(final String token, String name, Dynamic value, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().append(name, ReactNativeHelper.dynamicToObject(value)); promise.resolve(null); @@ -302,6 +414,10 @@ public void append(final String token, String name, Dynamic value, Promise promi @ReactMethod public void deleteUser(final String token, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().deleteUser(); promise.resolve(null); @@ -311,6 +427,10 @@ public void deleteUser(final String token, Promise promise) { @ReactMethod public void remove(final String token, String name, Dynamic value, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getPeople().remove(name, ReactNativeHelper.dynamicToObject(value)); promise.resolve(null); @@ -320,6 +440,10 @@ public void remove(final String token, String name, Dynamic value, Promise promi @ReactMethod public void trackWithGroups(final String token, String eventName, ReadableMap properties, ReadableMap groups, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { Map eventProperties = ReactNativeHelper.toMap(properties); Map eventGroups = ReactNativeHelper.toMap(groups); @@ -332,6 +456,10 @@ public void trackWithGroups(final String token, String eventName, ReadableMap pr @ReactMethod public void setGroup(final String token, String groupKey, Dynamic groupID, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.setGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)); promise.resolve(null); @@ -341,6 +469,10 @@ public void setGroup(final String token, String groupKey, Dynamic groupID, Promi @ReactMethod public void setGroups(final String token, String groupKey, ReadableArray groupIDs, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.setGroup(groupKey, Arrays.asList(ReactNativeHelper.toArray(groupIDs))); promise.resolve(null); @@ -350,6 +482,10 @@ public void setGroups(final String token, String groupKey, ReadableArray groupID @ReactMethod public void addGroup(final String token, String groupKey, Dynamic groupID, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.addGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)); promise.resolve(null); @@ -359,6 +495,10 @@ public void addGroup(final String token, String groupKey, Dynamic groupID, Promi @ReactMethod public void removeGroup(final String token, String groupKey, Dynamic groupID, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.removeGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)); promise.resolve(null); @@ -368,6 +508,10 @@ public void removeGroup(final String token, String groupKey, Dynamic groupID, Pr @ReactMethod public void deleteGroup(final String token, String groupKey, Dynamic groupID, Promise promise) { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).deleteGroup(); promise.resolve(null); @@ -377,6 +521,10 @@ public void deleteGroup(final String token, String groupKey, Dynamic groupID, Pr @ReactMethod public void groupSetProperties(final String token, String groupKey, Dynamic groupID, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject sendProperties = ReactNativeHelper.reactToJSON(properties); instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).set(sendProperties); @@ -387,6 +535,10 @@ public void groupSetProperties(final String token, String groupKey, Dynamic grou @ReactMethod public void groupSetPropertyOnce(final String token, String groupKey, Dynamic groupID, ReadableMap properties, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONObject sendProperties = ReactNativeHelper.reactToJSON(properties); instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).setOnce(sendProperties); @@ -397,6 +549,10 @@ public void groupSetPropertyOnce(final String token, String groupKey, Dynamic gr @ReactMethod public void groupUnsetProperty(final String token, String groupKey, Dynamic groupID, String propertyName, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).unset(propertyName); promise.resolve(null); @@ -406,6 +562,10 @@ public void groupUnsetProperty(final String token, String groupKey, Dynamic grou @ReactMethod public void groupRemovePropertyValue(final String token, String groupKey, Dynamic groupID, String name, Dynamic value, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).remove(name, ReactNativeHelper.dynamicToObject(value)); promise.resolve(null); @@ -415,6 +575,10 @@ public void groupRemovePropertyValue(final String token, String groupKey, Dynami @ReactMethod public void groupUnionProperty(final String token, String groupKey, Dynamic groupID, String name, ReadableArray values, Promise promise) throws JSONException { MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true); + if (instance == null) { + promise.reject("Instance Error", "Failed to get Mixpanel instance"); + return; + } synchronized (instance) { JSONArray arrayValues = ReactNativeHelper.reactToJSON(values); instance.getGroup(groupKey, ReactNativeHelper.dynamicToObject(groupID)).union(name, arrayValues);