@@ -398,32 +398,53 @@ private Dictionary<string, object> GetJavaMapData(string methodName) {
398398 return value ;
399399 }
400400
401- private void CallNativeVoidMethod ( string methodName , string methodSig , object [ ] args )
401+ // Manually converts any C# strings in the arguments, replacing invalid chars with the replacement char..
402+ // If we don't do this, C# will coerce them using NewStringUTF, which crashes on invalid UTF-8.
403+ // Arg lists processed this way must be released using ReleaseConvertedStringArgs.
404+ private object [ ] ConvertStringArgsToNative ( object [ ] args )
402405 {
403- if ( ! CanRunJNI ( ) ) {
404- return ;
405- }
406- bool isAttached = bsg_unity_isJNIAttached ( ) ;
407- if ( ! isAttached ) {
408- AndroidJNI . AttachCurrentThread ( ) ;
409- }
410-
411406 object [ ] itemsAsJavaObjects = new object [ args . Length ] ;
412407 for ( int i = 0 ; i < args . Length ; i ++ ) {
413408 var obj = args [ i ] ;
414409
415410 if ( obj is string ) {
416- //TODO:SM Leaking ref here
417411 itemsAsJavaObjects [ i ] = BuildJavaStringDisposable ( obj as string ) ;
418412 } else {
419413 itemsAsJavaObjects [ i ] = obj ;
420414 }
421415 }
416+ return itemsAsJavaObjects ;
417+ }
418+
419+ // Release any strings in a processed argument list.
420+ // @param originalArgs: The original C# args.
421+ // @param convertedArgs: The args list returned by ConvertStringArgsToNative.
422+ private void ReleaseConvertedStringArgs ( object [ ] originalArgs , object [ ] convertedArgs )
423+ {
424+ for ( int i = 0 ; i < originalArgs . Length ; i ++ ) {
425+ if ( originalArgs [ i ] is string ) {
426+ ( convertedArgs [ i ] as AndroidJavaObject ) . Dispose ( ) ;
427+ }
428+ }
429+ }
422430
423- jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( itemsAsJavaObjects ) ;
431+ private void CallNativeVoidMethod ( string methodName , string methodSig , object [ ] args )
432+ {
433+ if ( ! CanRunJNI ( ) ) {
434+ return ;
435+ }
436+ bool isAttached = bsg_unity_isJNIAttached ( ) ;
437+ if ( ! isAttached ) {
438+ AndroidJNI . AttachCurrentThread ( ) ;
439+ }
440+
441+ object [ ] convertedArgs = ConvertStringArgsToNative ( args ) ;
442+ jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( convertedArgs ) ;
424443 IntPtr methodID = AndroidJNI . GetStaticMethodID ( BugsnagNativeInterface , methodName , methodSig ) ;
425444 AndroidJNI . CallStaticVoidMethod ( BugsnagNativeInterface , methodID , jargs ) ;
426- AndroidJNIHelper . DeleteJNIArgArray ( itemsAsJavaObjects , jargs ) ;
445+ AndroidJNIHelper . DeleteJNIArgArray ( convertedArgs , jargs ) ;
446+ ReleaseConvertedStringArgs ( args , convertedArgs ) ;
447+
427448 if ( ! isAttached ) {
428449 AndroidJNI . DetachCurrentThread ( ) ;
429450 }
@@ -439,10 +460,12 @@ private IntPtr CallNativeObjectMethodRef(string methodName, string methodSig, ob
439460 AndroidJNI . AttachCurrentThread ( ) ;
440461 }
441462
442- jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( args ) ;
463+ object [ ] convertedArgs = ConvertStringArgsToNative ( args ) ;
464+ jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( convertedArgs ) ;
443465 IntPtr methodID = AndroidJNI . GetStaticMethodID ( BugsnagNativeInterface , methodName , methodSig ) ;
444466 IntPtr nativeValue = AndroidJNI . CallStaticObjectMethod ( BugsnagNativeInterface , methodID , jargs ) ;
445467 AndroidJNIHelper . DeleteJNIArgArray ( args , jargs ) ;
468+ ReleaseConvertedStringArgs ( args , convertedArgs ) ;
446469
447470 if ( ! isAttached ) {
448471 AndroidJNI . DetachCurrentThread ( ) ;
@@ -483,10 +506,12 @@ private string CallNativeStringMethod(string methodName, string methodSig, objec
483506 AndroidJNI . AttachCurrentThread ( ) ;
484507 }
485508
486- jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( args ) ;
509+ object [ ] convertedArgs = ConvertStringArgsToNative ( args ) ;
510+ jvalue [ ] jargs = AndroidJNIHelper . CreateJNIArgArray ( convertedArgs ) ;
487511 IntPtr methodID = AndroidJNI . GetStaticMethodID ( BugsnagNativeInterface , methodName , methodSig ) ;
488512 IntPtr nativeValue = AndroidJNI . CallStaticObjectMethod ( BugsnagNativeInterface , methodID , jargs ) ;
489513 AndroidJNIHelper . DeleteJNIArgArray ( args , jargs ) ;
514+ ReleaseConvertedStringArgs ( args , convertedArgs ) ;
490515
491516 string value = null ;
492517 if ( nativeValue != null && nativeValue != IntPtr . Zero ) {
0 commit comments