Fix crash when parsing native stack frames without symbols#278
Fix crash when parsing native stack frames without symbols#278BartoszLitwiniuk wants to merge 39 commits into
Conversation
Add bounds checks in SetNativeStackTraceInformation Add NativeParserTests to validate safe native frame parsing
…ve_stack_frames_fix # Conflicts: # Runtime/Model/BacktraceRawStackTraceParser.cs
…mes_fix # Conflicts: # Runtime/Model/BacktraceRawStackTraceParser.cs # Tests/Runtime/Model/BacktraceRawStackTraceParserTests.cs
|
can you link sample BT reports @BartoszLitwiniuk ? |
|
|
||
| # Platforms | ||
| iOS/ | ||
| Mac/ No newline at end of file |
# Conflicts: # Tests/Editor.meta # Tests/Tests.meta
| int methodNameEndIndex = frameString.IndexOf(')'); | ||
| int openParentIndex = frameString.LastIndexOf('(', methodNameEndIndex); // we require a '(' that appears before this ')' |
There was a problem hiding this comment.
This can throw before the invalid-frame check.
If frameString is non-empty and has no ), then methodNameEndIndex is -1,
and LastIndexOf('(', -1) throws ArgumentOutOfRangeException.
That changes behaviour from the previous implementation which preserved frames without )as raw BacktraceStackFrame instances.
With the current code, the catch returns null, and ConvertStackFrames drops the frame entirely.
I suggest something like this :
| int methodNameEndIndex = frameString.IndexOf(')'); | |
| int openParentIndex = frameString.LastIndexOf('(', methodNameEndIndex); // we require a '(' that appears before this ')' | |
| int methodNameEndIndex = frameString.IndexOf(')'); | |
| if (methodNameEndIndex == -1) | |
| { | |
| return new BacktraceStackFrame | |
| { | |
| FunctionName = frame, | |
| InvalidFrame = true | |
| }; | |
| } | |
| int openParentIndex = frameString.LastIndexOf('(', methodNameEndIndex); | |
| if (openParentIndex == -1 || openParentIndex > methodNameEndIndex) | |
| { | |
| return new BacktraceStackFrame | |
| { | |
| FunctionName = frame, | |
| InvalidFrame = true | |
| }; | |
| } |
| Debug.LogError($"Exception while parsing stack frame: '{frame}'. Exception: {e}"); | ||
| return null; |
There was a problem hiding this comment.
Returning null here causes the frame to be dropped.
I think parser failure should preserve the raw frame, not remove diagnostic data from the report.
Also, logging with Debug.LogError from report construction is risky in this SDK: Unity error logs are reportable, so a parser failure can create a secondary Backtrace report or another capture.
| if (methodNameEndIndex == -1 || openParentIndex == -1 || openParentIndex > methodNameEndIndex) | ||
| { | ||
| // If either index is missing, it's an invalid frame | ||
| Debug.LogWarning($"Invalid stack frame format: '{frameString}'."); |
There was a problem hiding this comment.
I would avoid logging from the parser for the same reason.
| return stackFrame; | ||
| } | ||
|
|
||
| frameString = frameString.Substring(frameString.IndexOf(' ')).Trim(); |
There was a problem hiding this comment.
This remains unsafe;
If a JIT frame starts with # but does not contain a space, IndexOf(' ') returns -1 and Substring(-1) throws.
With the current wrapper logic, that exception causes the frame to be dropped.
| return stackFrame; | ||
| } | ||
|
|
||
| frameString = frameString.Substring(frameString.IndexOf(' ')).Trim(); |
There was a problem hiding this comment.
something like :
| frameString = frameString.Substring(frameString.IndexOf(' ')).Trim(); | |
| int firstSpace = frameString.IndexOf(' '); | |
| if (firstSpace == -1 || firstSpace == frameString.Length - 1) | |
| { | |
| stackFrame.FunctionName = frameString; | |
| return stackFrame; | |
| } | |
| frameString = frameString.Substring(firstSpace + 1).Trim(); |
|
|
||
| namespace Backtrace.Unity.Tests.Runtime | ||
| { | ||
| public class BacktraceRawStackTraceParserTests |
There was a problem hiding this comment.
needs more coverage especially through ConvertStackFrames and ConvertStackFrames
| namespace Backtrace.Unity.Types | ||
| { | ||
| enum BacktraceStackFrameType | ||
| public enum BacktraceStackFrameType |
There was a problem hiding this comment.
Why does this need to become public ?
|
|
||
| namespace Backtrace.Unity.Tests.Runtime | ||
| { | ||
| public class BacktraceRawStackTraceParserTests |
There was a problem hiding this comment.
Let's add an end-to-end serialization test or attach a sample Backtrace report here.
Summary
Fixes a crash in the native stack trace parser when frames are missing symbol information. Refactors BacktraceRawStackTraceParser for safer parsing and adds unit test coverage.
It's a follow up of changes made in #258 and bug
BT-5953.Changes
SetNativeStackTraceInformationto prevent out-of-range access when a native frame lacks symbol dataBacktraceRawStackTraceParserfor clearer, more defensive frame parsingBacktraceRawStackTraceParserTestscovering native frame parsing edge casesBacktraceRawStackTraceParserinBacktraceUnhandledExceptioninstead of mixing unhandled exception handler with parsing logicTesting