Skip to content

Commit

Permalink
StackTraceDeobfuscator should never provide null methodName (#9997)
Browse files Browse the repository at this point in the history
Improves accuracy of deobfuscated stack traces by using the best answer
between original JS names, symbol maps, and source maps, by both
avoiding taking an identifier from the sourcemap if none is provided,
and normalizing away chromium specific prefixes in stack trace elements.

Fixes #9996
Follow-up #9936
  • Loading branch information
niloc132 authored Sep 5, 2024
1 parent be05c1e commit 15d11a2
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions user/src/com/google/gwt/core/server/StackTraceDeobfuscator.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -186,9 +187,9 @@ public final StackTraceElement[] resymbolize(StackTraceElement[] st, String stro
return null;
}
// Warm the symbol cache for all symbols in this stack trace.
Set<String> requiredSymbols = new HashSet<String>();
Set<String> requiredSymbols = new HashSet<>();
for (StackTraceElement ste : st) {
requiredSymbols.add(ste.getMethodName());
requiredSymbols.add(normalizeSymbol(ste.getMethodName()));
}
loadSymbolMap(strongName, requiredSymbols);

Expand All @@ -199,6 +200,17 @@ public final StackTraceElement[] resymbolize(StackTraceElement[] st, String stro
return newSt;
}

/**
* Helper to clean up client-provided symbols.
*/
private static String normalizeSymbol(String symbol) {
// Chrome prefixes "new " for constructor calls, eliminate the prefix
if (symbol.startsWith("new ")) {
symbol = symbol.substring(4);
}
return symbol;
}

/**
* Best effort resymbolization of a single stack trace element.
*
Expand Down Expand Up @@ -305,7 +317,13 @@ public final StackTraceElement resymbolize(StackTraceElement ste, String strongN

if (declaringClass == null || declaringClass.equals(ste.getClassName())) {
declaringClass = mappingForLine.getOriginalFile();
methodName = mappingForLine.getIdentifier().orElse(null);
if (mappingForLine.getIdentifier().isPresent()) {
// Only overwrite the name if the sourcemap had an explicit identifier
methodName = mappingForLine.getIdentifier().get();
} else if (methodName == null) {
// No other name was provided by symbolMaps, fall back to JS name
methodName = ste.getMethodName();
}
}
fileName = mappingForLine.getOriginalFile();
lineNumber = mappingForLine.getLineNumber();
Expand Down Expand Up @@ -366,9 +384,8 @@ private String loadStreamAsString(InputStream stream) {
}

private String loadOneSymbol(String strongName, String symbol) {
Set<String> symbolSet = new HashSet<String>();
symbolSet.add(symbol);
Map<String, String> symbolMap = loadSymbolMap(strongName, symbolSet);
symbol = normalizeSymbol(symbol);
Map<String, String> symbolMap = loadSymbolMap(strongName, Collections.singleton(symbol));
return symbolMap.get(symbol);
}

Expand Down

0 comments on commit 15d11a2

Please sign in to comment.