diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/GenerationalHeapParser.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/GenerationalHeapParser.java index 04edccc7a..a76307ea0 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/GenerationalHeapParser.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/GenerationalHeapParser.java @@ -64,6 +64,10 @@ public class GenerationalHeapParser extends PreUnifiedGCLogParser implements Sim private static final Logger LOGGER = Logger.getLogger(GenerationalHeapParser.class.getName()); + // Cached for the CMS remark/weak-reference split-bug path; avoid recompiling on every parse call. + // [^\n]* preserves last-match semantics of greedy .* without a ReDoS hotspot. + private static final Pattern DURATION_GROUP_PATTERN = Pattern.compile("[^\\n]* " + PAUSE_TIME); + private ParNew parNewForwardReference; private GarbageCollectionTypes garbageCollectionTypeForwardReference; private GCCause gcCauseForwardReference; @@ -626,9 +630,11 @@ public void parNewPromotionFailedDetails(GCLogTrace trace, String line) { gcCauseForwardReference = GCCause.PROMOTION_FAILED; ArrayList blocks = new ArrayList<>(); GCLogTrace block = PARNEW_PROMOTION_FAILURE_SIZE_BLOCK.parse(line); - do { - blocks.add(block.getIntegerGroup(1)); - } while (block.hasNext()); + if (block != null) { + do { + blocks.add(block.getIntegerGroup(1)); + } while (block.hasNext()); + } promotionFailureSizesForwardReference = new int[blocks.size()]; for (int index = 0; index < blocks.size(); index++) promotionFailureSizesForwardReference[index] = blocks.get(index); @@ -1817,7 +1823,8 @@ public void concurrentPhaseYields(GCLogTrace trace, String line) { private void precleanTimedoutWithCards(GCLogTrace trace, String line) { abortPrecleanDueToTime = true; GCLogTrace concurrentPhase = new GCParseRule("X",CMS_PHASE_END).parse(line); - endOfConcurrentPhase(concurrentPhase, concurrentPhase.getDateTimeStamp(), 0); + if (concurrentPhase != null) + endOfConcurrentPhase(concurrentPhase, concurrentPhase.getDateTimeStamp(), 0); } private void shouldCollectConcurrent(GCLogTrace trace, String line) { @@ -1917,8 +1924,7 @@ public void splitRemarkReference(GCLogTrace trace, String line) { */ public void splitRemarkReferenceWithWeakReferenceSplitBug(GCLogTrace trace, String line) { GCLogTrace remarkTrace = REMARK_CLAUSE.parse(line); - Pattern durationGroupPattern = Pattern.compile(".* " + PAUSE_TIME); - Matcher matcher = durationGroupPattern.matcher(line); + Matcher matcher = DURATION_GROUP_PATTERN.matcher(line); double duration = 0.0d; if (matcher.find()) { duration = Double.parseDouble(matcher.group(matcher.groupCount())); @@ -2067,6 +2073,10 @@ private void endOfConcurrentPhase(GCLogTrace trace, String line) { private void endConcurrentPrecleanWithReferenceProcessing(GCLogTrace trace, String line) { GCLogTrace concurrentBlock = CONCURRENT_PHASE_END_BLOCK.parse(line); + if (concurrentBlock == null) { + LOGGER.warning("Unable to extract data from " + trace.toString()); + return; + } try { publish(new ConcurrentPreClean(startOfConcurrentPhase, concurrentBlock.getDoubleGroup(11), concurrentBlock.getDoubleGroup(7), concurrentBlock.getDoubleGroup(8))); } catch (Throwable t) {