Skip to content

Commit 58ddf9e

Browse files
Merge pull request #342 from simaoseica-dd/feature/dynamic_size
Make crash report size configurable
1 parent c071db4 commit 58ddf9e

File tree

6 files changed

+116
-27
lines changed

6 files changed

+116
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* **[Improvement]** Update target iOS and tvOS version to 12.0.
66
* **[Improvement]** Support Xcode 16 build.
77
* **[Fix]** Fix endless loop when PLCrashReporter was set up during `load`.
8+
* **[Improvement]** Make crash report size configurable.
89

910
___
1011

Source/PLCrashReport.m

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,11 @@ - (Plcrash__CrashReport *) decodeCrashData: (NSData *) data error: (NSError **)
329329
return NULL;
330330
}
331331

332-
Plcrash__CrashReport *crashReport = plcrash__crash_report__unpack(NULL, [data length] - sizeof(struct PLCrashReportFileHeader), header->data);
332+
NSUInteger stackTraceSize = [data length] - sizeof(struct PLCrashReportFileHeader);
333+
Plcrash__CrashReport *crashReport = plcrash__crash_report__unpack(NULL, stackTraceSize, header->data);
333334
if (crashReport == NULL) {
334-
populate_nserror(outError, PLCrashReporterErrorCrashReportInvalid, NSLocalizedString(@"An unknown error occured decoding the crash report",
335-
@"Crash log decoding error message"));
335+
populate_nserror(outError, PLCrashReporterErrorCrashReportInvalid, [NSString stringWithFormat: NSLocalizedString(@"Could not decode crash report with size of %lu bytes.",
336+
@"Crash log decoding error message"), stackTraceSize]);
336337
return NULL;
337338
}
338339

Source/PLCrashReporter.m

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,6 @@
6464
* Directory containing crash reports queued for sending. */
6565
static NSString *PLCRASH_QUEUED_DIR = @"queued_reports";
6666

67-
/** @internal
68-
* Maximum number of bytes that will be written to the crash report.
69-
* Used as a safety measure in case of implementation malfunction.
70-
*
71-
* We provide for a generous 1m here. Most crash reports
72-
* are approximately 7k, however, we've seen 283k report
73-
* generated by an app that loads a pathologically
74-
* large number (~1080) of shared libraries.
75-
*/
76-
#define MAX_REPORT_BYTES (1024 * 1024)
77-
7867
/**
7968
* @internal
8069
* Fatal signals to be monitored.
@@ -103,6 +92,9 @@
10392
/** Path to the output file */
10493
const char *path;
10594

95+
/** Maximum number of bytes that will be written to the crash report. */
96+
NSUInteger max_report_size;
97+
10698
#if PLCRASH_FEATURE_MACH_EXCEPTIONS
10799
/* Previously registered Mach exception ports, if any. Will be left uninitialized if PLCrashReporterSignalHandlerTypeMach
108100
* is not enabled. */
@@ -159,8 +151,8 @@ static plcrash_error_t plcrash_write_report (plcrashreporter_handler_ctx_t *sigc
159151
}
160152

161153
/* Initialize the output context */
162-
plcrash_async_file_init(&file, fd, MAX_REPORT_BYTES);
163-
154+
plcrash_async_file_init(&file, fd, sigctx->max_report_size);
155+
164156
/* Write the crash log using the already-initialized writer */
165157
err = plcrash_log_writer_write(&sigctx->writer, crashed_thread, &shared_image_list, &file, siginfo, thread_state);
166158

@@ -754,7 +746,7 @@ - (NSData *) generateLiveReportWithThread: (thread_t) thread exception: (NSExcep
754746

755747
/* Initialize the output context */
756748
plcrash_log_writer_init(&writer, _applicationIdentifier, _applicationVersion, _applicationMarketingVersion, [self mapToAsyncSymbolicationStrategy: _config.symbolicationStrategy], true);
757-
plcrash_async_file_init(&file, fd, MAX_REPORT_BYTES);
749+
plcrash_async_file_init(&file, fd, _config.maxReportBytes);
758750

759751
/* Set custom data, if already set before enabling */
760752
if (self.customData != nil) {

Source/PLCrashReporterConfig.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ typedef NS_OPTIONS(NSUInteger, PLCrashReporterSymbolicationStrategy) {
168168
shouldRegisterUncaughtExceptionHandler: (BOOL) shouldRegisterUncaughtExceptionHandler
169169
basePath: (NSString *) basePath;
170170

171+
- (instancetype) initWithSignalHandlerType: (PLCrashReporterSignalHandlerType) signalHandlerType
172+
symbolicationStrategy: (PLCrashReporterSymbolicationStrategy) symbolicationStrategy
173+
shouldRegisterUncaughtExceptionHandler: (BOOL) shouldRegisterUncaughtExceptionHandler
174+
basePath: (NSString *) basePath
175+
maxReportBytes: (NSUInteger) maxReportByte;
176+
171177
/** The base path to save the crash data. */
172178
@property(nonatomic, readonly) NSString *basePath;
173179

@@ -177,8 +183,11 @@ typedef NS_OPTIONS(NSUInteger, PLCrashReporterSymbolicationStrategy) {
177183
/** The configured symbolication strategy. */
178184
@property(nonatomic, readonly) PLCrashReporterSymbolicationStrategy symbolicationStrategy;
179185

180-
/** Should PLCrashReporter regiser an uncaught exception handler? This is entended to be used in Xamarin apps */
186+
/** Should PLCrashReporter register an uncaught exception handler? This is intended to be used in Xamarin apps */
181187
@property(nonatomic, readonly) BOOL shouldRegisterUncaughtExceptionHandler;
182188

189+
/** Maximum number of bytes that will be written to the crash report */
190+
@property(nonatomic, readonly) NSUInteger maxReportBytes;
191+
183192
@end
184193

Source/PLCrashReporterConfig.m

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@
3232
#import "PLCrashReporterConfig.h"
3333
#endif
3434

35+
/** @internal
36+
* Maximum number of bytes that will be written to the crash report
37+
* when not explicitly defined in PLCrashReporterConfig.
38+
*
39+
* Default: 1MB.
40+
*
41+
* For reference, most crash reports
42+
* are approximately 7k, however, we've seen 283k report
43+
* generated by an app that loads a pathologically
44+
* large number (~1080) of shared libraries.
45+
*/
46+
#define MAX_REPORT_BYTES (1024 * 1024)
47+
3548
/**
3649
* Crash Reporter Configuration.
3750
*
@@ -41,20 +54,28 @@ @implementation PLCrashReporterConfig {
4154

4255
/** The configured signal handler type. */
4356
PLCrashReporterSignalHandlerType _signalHandlerType;
44-
57+
4558
/** The configured symbolication strategy. */
4659
PLCrashReporterSymbolicationStrategy _symbolicationStrategy;
47-
48-
/**
49-
* Flag indicating if the uncaughtExceptionHandler should be initialized or not. It usually is, except in a
50-
* Xamarin environment.
51-
*/
52-
BOOL _shouldRegisterUncaughtExceptionHandler;
60+
61+
/**
62+
* Flag indicating if the uncaughtExceptionHandler should be initialized or not. It usually is, except in a
63+
* Xamarin environment.
64+
*/
65+
BOOL _shouldRegisterUncaughtExceptionHandler;
66+
67+
/**
68+
* Maximum number of bytes that will be written to the crash report.
69+
*
70+
* If not provided, the default value will be MAX_REPORT_BYTES (1MB).
71+
*/
72+
NSUInteger _maxReportBytes;
5373
}
5474

5575
@synthesize signalHandlerType = _signalHandlerType;
5676
@synthesize symbolicationStrategy = _symbolicationStrategy;
5777
@synthesize shouldRegisterUncaughtExceptionHandler = _shouldRegisterUncaughtExceptionHandler;
78+
@synthesize maxReportBytes = _maxReportBytes;
5879

5980
/**
6081
* Return the default local configuration.
@@ -119,7 +140,11 @@ - (instancetype) initWithSignalHandlerType: (PLCrashReporterSignalHandlerType) s
119140
symbolicationStrategy: (PLCrashReporterSymbolicationStrategy) symbolicationStrategy
120141
shouldRegisterUncaughtExceptionHandler: (BOOL) shouldRegisterUncaughtExceptionHandler
121142
{
122-
return [self initWithSignalHandlerType: signalHandlerType symbolicationStrategy: symbolicationStrategy shouldRegisterUncaughtExceptionHandler: shouldRegisterUncaughtExceptionHandler basePath: nil];
143+
return [self initWithSignalHandlerType: signalHandlerType
144+
symbolicationStrategy: symbolicationStrategy
145+
shouldRegisterUncaughtExceptionHandler: shouldRegisterUncaughtExceptionHandler
146+
basePath: nil
147+
maxReportBytes: MAX_REPORT_BYTES];
123148
}
124149

125150
/**
@@ -134,6 +159,28 @@ - (instancetype) initWithSignalHandlerType: (PLCrashReporterSignalHandlerType) s
134159
symbolicationStrategy: (PLCrashReporterSymbolicationStrategy) symbolicationStrategy
135160
shouldRegisterUncaughtExceptionHandler: (BOOL) shouldRegisterUncaughtExceptionHandler
136161
basePath: (NSString *) basePath
162+
{
163+
return [self initWithSignalHandlerType: signalHandlerType
164+
symbolicationStrategy: symbolicationStrategy
165+
shouldRegisterUncaughtExceptionHandler: shouldRegisterUncaughtExceptionHandler
166+
basePath: basePath
167+
maxReportBytes: MAX_REPORT_BYTES];
168+
}
169+
170+
/**
171+
* Initialize a new PLCrashReporterConfig instance.
172+
*
173+
* @param signalHandlerType The requested signal handler type.
174+
* @param symbolicationStrategy A local symbolication strategy.
175+
* @param shouldRegisterUncaughtExceptionHandler Flag indicating if an uncaught exception handler should be set.
176+
* @param basePath The base path to save the crash data. May be nil.
177+
* @param maxReportBytes Maximum number of bytes that will be written to the crash report.
178+
*/
179+
- (instancetype) initWithSignalHandlerType: (PLCrashReporterSignalHandlerType) signalHandlerType
180+
symbolicationStrategy: (PLCrashReporterSymbolicationStrategy) symbolicationStrategy
181+
shouldRegisterUncaughtExceptionHandler: (BOOL) shouldRegisterUncaughtExceptionHandler
182+
basePath: (NSString *) basePath
183+
maxReportBytes: (NSUInteger) maxReportBytes
137184
{
138185
if ((self = [super init]) == nil)
139186
return nil;
@@ -142,7 +189,8 @@ - (instancetype) initWithSignalHandlerType: (PLCrashReporterSignalHandlerType) s
142189
_symbolicationStrategy = symbolicationStrategy;
143190
_shouldRegisterUncaughtExceptionHandler = shouldRegisterUncaughtExceptionHandler;
144191
_basePath = basePath;
145-
192+
_maxReportBytes = maxReportBytes;
193+
146194
return self;
147195
}
148196

Tests/PLCrashReporterTests.m

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,44 @@ - (void) testGenerateLiveReportWithException {
7979
STAssertEqualStrings(report.exceptionInfo.exceptionReason, exc.reason, @"Incorrect exception reason");
8080
}
8181

82+
/**
83+
* Test generation of a 'live' crash report that exceeds maxReportBytes.
84+
*/
85+
- (void) testGenerateLiveReportExceedingMaxReportBytes {
86+
NSError *error;
87+
NSData *reportData;
88+
plcrash_test_thread_t thr;
89+
NSUInteger maxReportBytes = 1024;
90+
91+
/* Spawn a thread and generate a report for it */
92+
plcrash_test_thread_spawn(&thr);
93+
94+
NSException *exc = [NSException exceptionWithName: NSInvalidArgumentException reason: @"Testing" userInfo: nil];
95+
96+
/* CrashReporter config with maximum 1024 bytes to write the crash report */
97+
PLCrashReporterConfig * config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType: PLCrashReporterSignalHandlerTypeBSD
98+
symbolicationStrategy: PLCrashReporterSymbolicationStrategyNone
99+
shouldRegisterUncaughtExceptionHandler: YES
100+
basePath: nil
101+
maxReportBytes: maxReportBytes];
102+
103+
PLCrashReporter *reporter = [[PLCrashReporter alloc] initWithConfiguration: config];
104+
105+
/* The report exceeds the 1024 bytes defined in the config. */
106+
reportData = [reporter generateLiveReportWithThread: pthread_mach_thread_np(thr.thread)
107+
exception: exc
108+
error: &error];
109+
plcrash_test_thread_stop(&thr);
110+
STAssertNotNil(reportData, @"Failed to generate live report: %@", error);
111+
112+
/* Try parsing the result */
113+
PLCrashReport *report = [[PLCrashReport alloc] initWithData: reportData error: &error];
114+
STAssertNil(report, @"Could not parse generated live report: %@", error);
115+
116+
NSString* errorDescription = [NSString stringWithFormat: @"Could not decode crash report with size of %lu bytes.", (maxReportBytes - sizeof(struct PLCrashReportFileHeader))];
117+
STAssertEqualStrings([error localizedDescription], errorDescription, @"Error is not about exceeding MaxReportBytes");
118+
}
119+
82120
/**
83121
* Test generation of a 'live' crash report for a specific thread.
84122
*/

0 commit comments

Comments
 (0)