Skip to content

Commit bd80509

Browse files
authored
Fix crash call stack filtering. (#13397)
* Fix crash call stack filtering. * Save regex object. Fix newlines.
1 parent 56968c5 commit bd80509

File tree

1 file changed

+93
-78
lines changed

1 file changed

+93
-78
lines changed

Extension/src/LanguageServer/extension.ts

Lines changed: 93 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,8 @@ function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, d
11611161
logMacCrashTelemetry(data);
11621162
}
11631163

1164+
const regex: RegExp = /(key|token|sig|secret|signature|password|passwd|pwd|android:value)[^a-zA-Z0-9]/i;
11641165
function containsFilteredTelemetryData(str: string): boolean {
1165-
const regex: RegExp = /(key|token|sig|secret|signature|password|passwd|pwd|android:value)[^a-zA-Z0-9]/i;
11661166
return regex.test(str);
11671167
}
11681168

@@ -1175,139 +1175,154 @@ async function handleCrashFileRead(crashDirectory: string, crashFile: string, cr
11751175
}
11761176

11771177
const lines: string[] = data.split("\n");
1178-
let addressData: string = ".\n.";
1178+
let addressData: string = ".\n";
11791179
const isCppToolsSrv: boolean = crashFile.startsWith("cpptools-srv");
11801180
const telemetryHeader: string = (isCppToolsSrv ? "cpptools-srv.txt" : crashFile) + "\n";
11811181
const filtPath: string | null = which.sync("c++filt", { nothrow: true });
11821182
const isMac: boolean = process.platform === "darwin";
11831183
const startStr: string = isMac ? " _" : "<";
11841184
const offsetStr: string = isMac ? " + " : "+";
11851185
const endOffsetStr: string = isMac ? " " : " <";
1186-
const dotStr: string = "\n…";
1186+
const dotStr: string = "…\n";
11871187
let signalType: string;
11881188
let crashLog: string = "";
11891189
let crashStackStartLine: number = 0;
11901190
if (lines[0] === "LOG") {
11911191
let crashLogLine: number = 1;
11921192
for (; crashLogLine < lines.length; ++crashLogLine) {
1193-
const pendingCrashLogLine = lines[crashLogLine];
1193+
let pendingCrashLogLine = lines[crashLogLine];
11941194
if (pendingCrashLogLine === "ENDLOG") {
11951195
break;
11961196
}
1197+
pendingCrashLogLine += "\n";
11971198
if (containsFilteredTelemetryData(pendingCrashLogLine)) {
11981199
crashLog += "?\n";
11991200
} else {
1200-
crashLog += pendingCrashLogLine + "\n";
1201+
crashLog += pendingCrashLogLine;
12011202
}
12021203
}
12031204
crashLog = crashLog.trimEnd();
12041205
crashStackStartLine = ++crashLogLine;
12051206
}
12061207
if (lines[crashStackStartLine].startsWith("SIG")) {
1207-
signalType = lines[crashStackStartLine];
1208+
signalType = lines[crashStackStartLine] + "\n";
12081209
} else {
12091210
// The signal type may fail to be written.
12101211
signalType = "SIG-??\n"; // Intentionally different from SIG-? from cpptools.
12111212
}
1213+
data = telemetryHeader + signalType;
12121214
let crashCallStack: string = "";
12131215
let validFrameFound: boolean = false;
12141216
for (let lineNum: number = crashStackStartLine; lineNum < lines.length - 3; ++lineNum) { // skip last lines
12151217
const line: string = lines[lineNum];
12161218
const startPos: number = line.indexOf(startStr);
1219+
let pendingCallStack: string = "";
12171220
if (startPos === -1 || line[startPos + (isMac ? 1 : 4)] === "+") {
12181221
if (!validFrameFound) {
12191222
continue; // Skip extra … at the start.
12201223
}
1221-
crashCallStack += dotStr;
1224+
pendingCallStack = dotStr;
12221225
const startAddressPos: number = line.indexOf("0x");
12231226
const endAddressPos: number = line.indexOf(endOffsetStr, startAddressPos + 2);
1224-
addressData += "\n";
12251227
if (startAddressPos === -1 || endAddressPos === -1 || startAddressPos >= endAddressPos) {
1226-
addressData += "Unexpected offset";
1228+
addressData += "Unexpected offset\n";
12271229
} else {
1228-
addressData += line.substring(startAddressPos, endAddressPos);
1229-
}
1230-
continue;
1231-
}
1232-
const offsetPos: number = line.indexOf(offsetStr, startPos + startStr.length);
1233-
if (offsetPos === -1) {
1234-
crashCallStack += "\nMissing offsetStr";
1235-
addressData += "\n";
1236-
continue; // unexpected
1237-
}
1238-
const startPos2: number = startPos + 1;
1239-
let funcStr: string = line.substring(startPos2, offsetPos);
1240-
if (filtPath && filtPath.length !== 0) {
1241-
let ret: util.ProcessReturnType | undefined = await util.spawnChildProcess(filtPath, ["--no-strip-underscore", funcStr], undefined, true).catch(logAndReturn.undefined);
1242-
if (ret?.output === funcStr) {
1243-
ret = await util.spawnChildProcess(filtPath, [funcStr], undefined, true).catch(logAndReturn.undefined);
1244-
}
1245-
if (ret !== undefined && ret.succeeded && !ret.output.startsWith("Could not open input file")) {
1246-
funcStr = ret.output;
1247-
funcStr = funcStr.replace(/std::(?:__1|__cxx11)/g, "std"); // simplify std namespaces.
1248-
funcStr = funcStr.replace(/std::basic_/g, "std::");
1249-
funcStr = funcStr.replace(/ >/g, ">");
1250-
funcStr = funcStr.replace(/, std::(?:allocator|char_traits)<char>/g, "");
1251-
funcStr = funcStr.replace(/<char>/g, "");
1252-
funcStr = funcStr.replace(/, std::allocator<std::string>/g, "");
1253-
}
1254-
}
1255-
if (containsFilteredTelemetryData(funcStr)) {
1256-
funcStr = "?";
1257-
} else if (!validFrameFound && (funcStr.startsWith("crash_handler(") || funcStr.startsWith("_sigtramp"))) {
1258-
continue; // Skip these on early frames.
1259-
}
1260-
validFrameFound = true;
1261-
crashCallStack += "\n";
1262-
addressData += "\n";
1263-
crashCallStack += funcStr + offsetStr;
1264-
const offsetPos2: number = offsetPos + offsetStr.length;
1265-
if (isMac) {
1266-
const pendingOffset: string = line.substring(offsetPos2);
1267-
if (containsFilteredTelemetryData(pendingOffset)) {
1268-
crashCallStack += "?";
1269-
} else {
1270-
crashCallStack += pendingOffset;
1271-
}
1272-
const startAddressPos: number = line.indexOf("0x");
1273-
if (startAddressPos === -1 || startAddressPos >= startPos) {
1274-
// unexpected
1275-
crashCallStack += "<Missing 0x>";
1276-
continue;
1230+
let pendingAddressData: string = line.substring(startAddressPos, endAddressPos) + "\n";
1231+
if (containsFilteredTelemetryData(pendingAddressData)) {
1232+
pendingAddressData = "?\n";
1233+
}
1234+
addressData += pendingAddressData;
12771235
}
1278-
addressData += `${line.substring(startAddressPos, startPos)}`;
12791236
} else {
1280-
const endPos: number = line.indexOf(">", offsetPos2);
1281-
if (endPos === -1) {
1282-
crashCallStack += "<Missing > >";
1283-
continue; // unexpected
1284-
}
1285-
const pendingOffset: string = line.substring(offsetPos2, endPos);
1286-
if (containsFilteredTelemetryData(pendingOffset)) {
1287-
crashCallStack += "?";
1237+
const offsetPos: number = line.indexOf(offsetStr, startPos + startStr.length);
1238+
if (offsetPos === -1) {
1239+
pendingCallStack = "Missing offsetStr\n";
1240+
addressData += "\n";
12881241
} else {
1289-
crashCallStack += pendingOffset;
1242+
const startPos2: number = startPos + 1;
1243+
let funcStr: string = line.substring(startPos2, offsetPos);
1244+
let origFuncStr: string = "";
1245+
if (filtPath && filtPath.length !== 0) {
1246+
let ret: util.ProcessReturnType | undefined = await util.spawnChildProcess(filtPath, ["--no-strip-underscore", funcStr], undefined, true).catch(logAndReturn.undefined);
1247+
if (ret?.output === funcStr) {
1248+
ret = await util.spawnChildProcess(filtPath, [funcStr], undefined, true).catch(logAndReturn.undefined);
1249+
}
1250+
if (ret !== undefined && ret.succeeded && !ret.output.startsWith("Could not open input file")) {
1251+
origFuncStr = funcStr;
1252+
funcStr = ret.output;
1253+
funcStr = funcStr.replace(/std::(?:__1|__cxx11)/g, "std"); // simplify std namespaces.
1254+
funcStr = funcStr.replace(/std::basic_/g, "std::");
1255+
funcStr = funcStr.replace(/ >/g, ">");
1256+
funcStr = funcStr.replace(/, std::(?:allocator|char_traits)<char>/g, "");
1257+
funcStr = funcStr.replace(/<char>/g, "");
1258+
funcStr = funcStr.replace(/, std::allocator<std::string>/g, "");
1259+
}
1260+
}
1261+
if (!validFrameFound && (funcStr.startsWith("crash_handler(") || funcStr.startsWith("_sigtramp"))) {
1262+
continue; // Skip these on early frames.
1263+
}
1264+
validFrameFound = true;
1265+
1266+
let pendingOffset: string = offsetStr;
1267+
const offsetPos2: number = offsetPos + offsetStr.length;
1268+
// Compute pendingOffset.
1269+
if (isMac) {
1270+
pendingOffset += line.substring(offsetPos2);
1271+
const startAddressPos: number = line.indexOf("0x");
1272+
if (startAddressPos === -1 || startAddressPos >= startPos) {
1273+
// unexpected
1274+
pendingOffset += "<Missing 0x>";
1275+
addressData += "\n";
1276+
} else {
1277+
let pendingAddressData: string = line.substring(startAddressPos, startPos) + "\n";
1278+
if (containsFilteredTelemetryData(pendingAddressData)) {
1279+
pendingAddressData = "?\n";
1280+
}
1281+
addressData += pendingAddressData;
1282+
}
1283+
} else {
1284+
const endPos: number = line.indexOf(">", offsetPos2);
1285+
if (endPos === -1) {
1286+
pendingOffset += "<Missing > >"; // unexpected
1287+
} else {
1288+
pendingOffset += line.substring(offsetPos2, endPos);
1289+
}
1290+
addressData += "\n";
1291+
// TODO: It seems like addressData should be obtained on Linux in case the function is filtered.
1292+
}
1293+
pendingOffset += "\n";
1294+
pendingCallStack = funcStr + pendingOffset;
1295+
if (containsFilteredTelemetryData(pendingCallStack)) {
1296+
if (origFuncStr.length > 0 && origFuncStr !== funcStr) {
1297+
pendingCallStack = origFuncStr + pendingOffset;
1298+
if (containsFilteredTelemetryData(pendingCallStack)) {
1299+
pendingCallStack = "?\n";
1300+
}
1301+
} else {
1302+
pendingCallStack = "?\n";
1303+
}
1304+
}
12901305
}
12911306
}
1307+
if (data.length + crashCallStack.length + pendingCallStack.length > 8191) { // The API has an 8k limit.
1308+
crashCallStack += "…";
1309+
break;
1310+
}
1311+
crashCallStack += pendingCallStack;
12921312
}
12931313

1314+
crashCallStack = crashCallStack.trimEnd();
1315+
addressData = addressData.trimEnd();
1316+
12941317
if (crashCallStack !== prevCppCrashCallStackData) {
12951318
prevCppCrashCallStackData = crashCallStack;
12961319

12971320
if (lines.length >= 6 && util.getLoggingLevel() >= 1) {
1298-
getCrashCallStacksChannel().appendLine(`\n${isCppToolsSrv ? "cpptools-srv" : "cpptools"}\n${crashDate.toLocaleString()}\n${signalType}${crashCallStack}\n\n${crashLog}`);
1321+
getCrashCallStacksChannel().appendLine(`\n${isCppToolsSrv ? "cpptools-srv" : "cpptools"}\n${crashDate.toLocaleString()}\n${signalType}${crashCallStack}${crashLog.length > 0 ? "\n\n" + crashLog : ""}`);
12991322
}
13001323
}
13011324

1302-
data = telemetryHeader + signalType + crashCallStack;
1303-
1304-
if (data.length > 8192) { // The API has an 8k limit.
1305-
data = data.substring(0, 8191) + "…";
1306-
}
1307-
1308-
if (containsFilteredTelemetryData(addressData)) {
1309-
addressData = "?";
1310-
}
1325+
data += crashCallStack;
13111326

13121327
logCppCrashTelemetry(data, addressData, crashLog);
13131328

0 commit comments

Comments
 (0)