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

Prevent NREX when instantiating Java.Lang.StackTraceElement #8795

Merged
merged 8 commits into from
Mar 17, 2024

Conversation

grendello
Copy link
Contributor

Context: #8788 (comment)
Context: https://developer.android.com/reference/java/lang/StackTraceElement?hl=en#StackTraceElement(java.lang.String,%20java.lang.String,%20java.lang.String,%20int)

Java.Lang.StackTraceElement constructor requires the declaringClass
and methodName parameters to never be null. Pass the string
Unknown whenever any of this information is missing from the managed
stack frame.

Additionally, the lineNumber parameter is now set to -2 if we think
a stack frame points to native code.

Context: #8788 (comment)
Context: https://developer.android.com/reference/java/lang/StackTraceElement?hl=en#StackTraceElement(java.lang.String,%20java.lang.String,%20java.lang.String,%20int)

`Java.Lang.StackTraceElement` constructor requires the `declaringClass`
and `methodName` parameters to never be `null`.  Pass the string
`Unknown` whenever any of this information is missing from the managed
stack frame.

Additionally, the `lineNumber` parameter is now set to `-2` if we think
a stack frame points to native code.
@grendello grendello requested a review from jonpryor as a code owner March 7, 2024 10:33
@grendello
Copy link
Contributor Author

@jonpryor our Java.Lang.StackTraceElement MCW generates the following signature which is, IMO, incorrect according to the Java API docs:

// Metadata.xml XPath constructor reference: path="/api/package[@name='java.lang']/class[@name='StackTraceElement']/constructor[@name='StackTraceElement' and count(parameter)=4 and parameter[1][@type='java.lang.String'] and parameter[2][@type='java.lang.String'] and parameter[3][@type='java.lang.String'] and parameter[4][@type='int']]"
[Register (".ctor", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V", "")]
public unsafe StackTraceElement (string? declaringClass, string? methodName, string? fileName, int lineNumber) : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)

Shouldn't declaringClass and methodName be declared as non-nullable string?

@grendello
Copy link
Contributor Author

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello
Copy link
Contributor Author

/azp run

* main:
  Bump to xamarin/Java.Interop/main@a7e09b7 (#8793)
* main:
  [templates] Remove redundant "template" from display name. (#8773)
@jpobst
Copy link
Contributor

jpobst commented Mar 11, 2024

Shouldn't declaringClass and methodName be declared as non-nullable string?

We do not manually assign nullability, we simply pass along what Google has annotated, and it appears this method has no @NonNull annotations declared in android.jar:

public final class StackTraceElement implements Serializable {
  public StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber) {
    throw new RuntimeException("Stub!");
  }
  ...
}

@jonpryor
Copy link
Member

jonpryor commented Mar 11, 2024

@grendello asked:

Shouldn't declaringClass and methodName be declared as non-nullable string?

We only flag a parameter or return type as non-null if it contains one of these annotations: https://github.com/xamarin/java.interop/blob/e557044f81917b61031f2ee887700ac43a526475/src/Xamarin.Android.Tools.Bytecode/XmlClassDeclarationBuilder.cs#L503-L512

By default, then, everything is allowed to be null, which is the behavior you're seeing.

We can use Metadata to update these parameters so that null is not allowed.

@jpobst would such an update be a good idea?

  <attr
      path="/api/package[@name='java.lang']/class[@name='StackTraceElement']/constructor/parameter[@type='java.lang.String']"
      name="not-null">true</attr>

It should be noted that (1) the above metadata is an oversimplication -- the filename String parameter should be allowed to be null -- and (2) the above Metadata results in a build break:

error RS0016: Symbol 'StackTraceElement' is not part of the declared public API
error RS0017: Symbol 'Java.Lang.StackTraceElement.StackTraceElement(string? declaringClass, string? methodName, string? fileName, int lineNumber) -> void' is part of the declared API, but is either not public or could not be found

@jpobst
Copy link
Contributor

jpobst commented Mar 11, 2024

@jpobst would such an update be a good idea?

There are likely thousands of Android APIs that are missing nullability information. Thus our stated policy is that we will not manually fix them: https://learn.microsoft.com/en-us/xamarin/android/release-notes/11/11.0#monoandroid-nullable-reference-types-compatibility.

@grendello
Copy link
Contributor Author

@jpobst would such an update be a good idea?

There are likely thousands of Android APIs that are missing nullability information. Thus our stated policy is that we will not manually fix them: https://learn.microsoft.com/en-us/xamarin/android/release-notes/11/11.0#monoandroid-nullable-reference-types-compatibility.

While it was fine before nullable support was added to .NET, I think now it would be good to change that policy... I realize it's a lot of work, but this is where the compiler (or the IDE) can help avoid mistakes like this one.

for (int i = 0; i < frames.Length; i++) {
StackFrame managedFrame = frames[i];
MethodBase? managedMethod = StackFrameGetMethod (managedFrame);

// https://developer.android.com/reference/java/lang/StackTraceElement?hl=en#StackTraceElement(java.lang.String,%20java.lang.String,%20java.lang.String,%20int)
int lineNumber;
Copy link
Member

Choose a reason for hiding this comment

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

I'm reminded of: https://github.com/xamarin/xamarin-android/pull/8758/files#r1504920023

wherein StackFrame.GetMethod() may return null, while StackFrame.ToString() contains useful information.

I suspect that we should instead "lean in" to using StackFrame.ToString(), as we know managedFrame is not null (if it were, we'd get a NullReferenceException from here!).

Copy link
Contributor Author

@grendello grendello Mar 12, 2024

Choose a reason for hiding this comment

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

I don't want to use ToString() output, as it's unwieldy to handle in a presentable manner. However, the information mentioned above can be obtained using the StackFrame extension methods (which this PR already uses in a small capacity). We can get this kind of output:

MainActivity.OnCreate() + 0x37 at offset 55 in file:line:column <filename unknown>:0:0

Only I'm not sure how useful it really is.

Copy link
Member

Choose a reason for hiding this comment

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

@grendello: parsing MainActivity.OnCreate() is more useful than providing Unknown.Unknown:-1 as the stack frame information to Java. Is it perfect? No. But it's better than the alternative.

* main:
  [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707)
  Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803)
  Bump to xamarin/monodroid@77124dc1 (#8804)
  Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802)
  Bump to xamarin/Java.Interop/main@3436a30 (#8799)
* main:
  [runtime] Remove the last vestiges of desktop builds (#8810)
  [ci] Don't auto-retry APK test suites. (#8811)
  [Microsoft.Android.Templates] Update EN l10n template strings (#8808)
  Bump to xamarin/Java.Interop/main@651de42 (#8809)
  [Mono.Android] is now "trimming safe" (#8778)
@jonpryor jonpryor merged commit dd40c1a into main Mar 17, 2024
48 checks passed
@jonpryor jonpryor deleted the dev/grendel/fix-proxy-throwable branch March 17, 2024 16:40
grendello added a commit that referenced this pull request Mar 20, 2024
…8795)

Context: #8788 (comment)
Context: 1aa0ea7

The [`java.lang.StackTraceElement(String, String, String, int)`][0]
constructor requires that the `declaringClass` and `methodName`
parameters never be `null`.  Failure to do so results in a
`NullPointerException`:

	I DOTNET  : JavaProxyThrowable: translation threw an exception: Java.Lang.NullPointerException: Declaring class is null
	I DOTNET  :    at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args)
	I DOTNET  :    at Java.Interop.JniPeerMembers.JniInstanceMethods.FinishCreateInstance(String constructorSignature, IJavaPeerable self, JniArgumentValue* parameter s)
	I DOTNET  :    at Java.Lang.StackTraceElement..ctor(String declaringClass, String methodName, String fileName, Int32 lineNumber)
	I DOTNET  :    at Android.Runtime.JavaProxyThrowable.TranslateStackTrace()
	I DOTNET  :    at Android.Runtime.JavaProxyThrowable.Create(Exception innerException)
	I DOTNET  :   --- End of managed Java.Lang.NullPointerException stack trace ---
	I DOTNET  : java.lang.NullPointerException: Declaring class is null
	I DOTNET  :      at java.util.Objects.requireNonNull(Objects.java:228)
	I DOTNET  :      at java.lang.StackTraceElement.<init>(StackTraceElement.java:71)
	I DOTNET  :      at crc6431345fe65afe8d98.AvaloniaMainActivity_1.n_onCreate(Native Method)

Update `JavaProxyThrowable.TranslateStackTrace()` (1aa0ea7) so that
if `StackFrame.GetMethod()` returns `null`, we fallback to:

 1. Trying to extract class name and method name from
    [`StackFrame.ToString()`][1]:

        MainActivity.OnCreate() + 0x37 at offset 55 in file:line:column <filename unknown>:0:0

 2. If (1) fails, pass `Unknown` for `declaringClass` and `methodName`.

Additionally, the `lineNumber` parameter is now set to `-2` if we
think a stack frame points to native code.

[0]: https://developer.android.com/reference/java/lang/StackTraceElement#StackTraceElement(java.lang.String,%20java.lang.String,%20java.lang.String,%20int)
[1]: https://github.com/xamarin/xamarin-android/pull/8758/files#r1504920023
grendello added a commit that referenced this pull request Mar 20, 2024
* main:
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
grendello added a commit that referenced this pull request Mar 20, 2024
* main:
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
  [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
grendello added a commit that referenced this pull request Mar 20, 2024
* main:
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
  [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
  [runtime] Remove the last vestiges of desktop builds (#8810)
  [ci] Don't auto-retry APK test suites. (#8811)
  [Microsoft.Android.Templates] Update EN l10n template strings (#8808)
  Bump to xamarin/Java.Interop/main@651de42 (#8809)
  [Mono.Android] is now "trimming safe" (#8778)
  [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707)
  Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803)
  Bump to xamarin/monodroid@77124dc1 (#8804)
  Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802)
  Bump to xamarin/Java.Interop/main@3436a30 (#8799)
  [templates] Remove redundant "template" from display name. (#8773)
grendello added a commit that referenced this pull request Mar 20, 2024
* main:
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
  [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
  [runtime] Remove the last vestiges of desktop builds (#8810)
  [ci] Don't auto-retry APK test suites. (#8811)
  [Microsoft.Android.Templates] Update EN l10n template strings (#8808)
  Bump to xamarin/Java.Interop/main@651de42 (#8809)
  [Mono.Android] is now "trimming safe" (#8778)
  [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707)
  Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803)
  Bump to xamarin/monodroid@77124dc1 (#8804)
  Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802)
  Bump to xamarin/Java.Interop/main@3436a30 (#8799)
grendello added a commit that referenced this pull request Mar 20, 2024
* main:
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
  [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
grendello added a commit that referenced this pull request Mar 20, 2024
* main: (99 commits)
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
  [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
  [runtime] Remove the last vestiges of desktop builds (#8810)
  [ci] Don't auto-retry APK test suites. (#8811)
  [Microsoft.Android.Templates] Update EN l10n template strings (#8808)
  Bump to xamarin/Java.Interop/main@651de42 (#8809)
  [Mono.Android] is now "trimming safe" (#8778)
  [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707)
  Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803)
  Bump to xamarin/monodroid@77124dc1 (#8804)
  Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802)
  Bump to xamarin/Java.Interop/main@3436a30 (#8799)
  [templates] Remove redundant "template" from display name. (#8773)
  Bump to xamarin/Java.Interop/main@a7e09b7 (#8793)
  ...
grendello added a commit that referenced this pull request Mar 27, 2024
* main:
  [ci] Use managed identity for ApiScan (#8823)
  [Xamarin.Android.Build.Tasks] DTBs should not rm generator output (#8706)
  [Xamarin.Android.Build.Tasks] Bump to NuGet 6.7.1 (#8833)
  $(AndroidPackVersionSuffix)=preview.4; net9 is 34.99.0.preview.4 (#8831)
  Localized file check-in by OneLocBuild Task (#8824)
  [Xamarin.Android.Build.Tasks] Enable POM verification features. (#8649)
  [runtime] Optionally disable inlining (#8798)
  Fix assembly count when satellite assemblies are present (#8790)
  [One .NET] new "greenfield" projects are trimmed by default (#8805)
  Localized file check-in by OneLocBuild Task (#8819)
  LEGO: Merge pull request 8820
  LEGO: Merge pull request 8818
  Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817)
  Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816)
  [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795)
  Localized file check-in by OneLocBuild Task (#8815)
  [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478)
  Localized file check-in by OneLocBuild Task (#8813)
@github-actions github-actions bot locked and limited conversation to collaborators Apr 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants