Skip to content
This repository has been archived by the owner on Feb 19, 2020. It is now read-only.

Move max length check into contentsOfFile #392

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.junit.runner.RunWith;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.UUID;

Expand Down Expand Up @@ -140,4 +142,28 @@ public void invalidStackTrace() throws Exception {
verify(listener).onCrashesNotSent();
assertEquals(0, CrashManager.stackTracesCount);
}

@Test
public void largeStackTrace() throws Exception {
String stackTrace = "java.lang.OutOfMemoryError: Failed to allocate a 37657308 byte allocation with 16776928 free bytes and 27MB until OOM\n" +
"\tat java.lang.String.<init>(String.java:400)\n" +
"\tat java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:633)\n" +
"\tat java.lang.StringBuilder.toString(StringBuilder.java:663)\n" +
"\tat net.hockeyapp.android.CrashManager.contentsOfFile(CrashManager.java:772)\n" +
"\tat net.hockeyapp.android.CrashManager.submitStackTrace(CrashManager.java:379)\n" +
"\tat net.hockeyapp.android.CrashManager.access$500(CrashManager.java:47)\n" +
"\tat net.hockeyapp.android.CrashManager$8.doInBackground(CrashManager.java:647)\n" +
"\tat net.hockeyapp.android.CrashManager$8.doInBackground(CrashManager.java:639)\n";

String filename = UUID.randomUUID().toString() + ".stacktrace";
File file = new File(filesDirectory, filename);
PrintWriter writer = new PrintWriter(file);
writer.print(stackTrace);
writer.flush();
writer.close();

WeakReference<Context> weakContext = new WeakReference<>(InstrumentationRegistry.getTargetContext());
String result = CrashManager.contentsOfFile(weakContext, filename, 500);
assertTrue(result.endsWith("submitStackTrace(CrashManager.java:379)\n"));
}
}
32 changes: 19 additions & 13 deletions hockeysdk/src/main/java/net/hockeyapp/android/CrashManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
Expand Down Expand Up @@ -406,7 +408,7 @@ public static synchronized void submitStackTraces(final WeakReference<Context> w
private static void submitStackTrace(final WeakReference<Context> weakContext, String filename, CrashManagerListener listener, CrashMetaData crashMetaData) {
String stacktrace = null;
try {
stacktrace = contentsOfFile(weakContext, filename);
stacktrace = contentsOfFile(weakContext, filename, HttpURLConnectionBuilder.FORM_FIELD_LIMIT);
} catch (Exception e) {
HockeyLog.error("Failed to read crash data", e);
}
Expand All @@ -424,14 +426,10 @@ private static void submitStackTrace(final WeakReference<Context> weakContext, S
try {
// Transmit stack trace with POST request
HockeyLog.debug("Transmitting crash data: \n" + stacktrace);
if (stacktrace.length() > HttpURLConnectionBuilder.FORM_FIELD_LIMIT) {
HockeyLog.info("The stack trace is too large, truncate a bit");
stacktrace = stacktrace.substring(0, stacktrace.lastIndexOf('\n', HttpURLConnectionBuilder.FORM_FIELD_LIMIT - 1) + 1);
}

// Retrieve user ID and contact information if given
String userID = contentsOfFile(weakContext, filename.replace(".stacktrace", ".user"));
String contact = contentsOfFile(weakContext, filename.replace(".stacktrace", ".contact"));
String userID = contentsOfFile(weakContext, filename.replace(".stacktrace", ".user"), 0);
String contact = contentsOfFile(weakContext, filename.replace(".stacktrace", ".contact"), 0);

if (crashMetaData != null) {
final String crashMetaDataUserID = crashMetaData.getUserID();
Expand All @@ -445,7 +443,7 @@ private static void submitStackTrace(final WeakReference<Context> weakContext, S
}

// Append application log to user provided description if present, if not, just send application log
final String applicationLog = contentsOfFile(weakContext, filename.replace(".stacktrace", ".description"));
final String applicationLog = contentsOfFile(weakContext, filename.replace(".stacktrace", ".description"), 0);
String description = crashMetaData != null ? crashMetaData.getUserDescription() : "";
if (!TextUtils.isEmpty(applicationLog)) {
if (!TextUtils.isEmpty(description)) {
Expand Down Expand Up @@ -794,21 +792,29 @@ private static void deleteStackTrace(final WeakReference<Context> weakContext, S
/**
* Returns the content of a file as a string.
*/
private static String contentsOfFile(final WeakReference<Context> weakContext, String filename) {
static String contentsOfFile(final WeakReference<Context> weakContext, String filename, int maxLength) {
Context context = weakContext != null ? weakContext.get() : null;
if (context != null) {
File file = context.getFileStreamPath(filename);
if(file == null || !file.exists()) {
return "";
}
StringBuilder contents = new StringBuilder();
final StringWriter result = new StringWriter();
final PrintWriter writer = new PrintWriter(result);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(context.openFileInput(filename)));
String line;
while ((line = reader.readLine()) != null) {
contents.append(line);
contents.append(System.getProperty("line.separator"));

// Break if the line is too long
if (maxLength > 0 && result.getBuffer().length() + line.length() + 1 >= maxLength) {
HockeyLog.info(filename + " is too large, truncate a bit");
break;
}

// Write line + line separator
writer.println(line);
}
} catch (IOException e) {
HockeyLog.error("Failed to read content of " + filename, e);
Expand All @@ -820,7 +826,7 @@ private static String contentsOfFile(final WeakReference<Context> weakContext, S
}
}
}
return contents.toString();
return result.toString();
}
return "";
}
Expand Down