From df6296e89a30a8b91280d97addd61ee763ad5c72 Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 10:53:25 +0100 Subject: [PATCH 1/8] Refactor SMAP parser Simplify code, reduce allocations remove checked exceptions use an enum for builders --- .../agent/tooling/iast/stratum/FileInfo.java | 24 +-- .../agent/tooling/iast/stratum/LineInfo.java | 33 ++-- .../tooling/iast/stratum/ParserException.java | 12 -- .../agent/tooling/iast/stratum/Resolver.java | 10 +- .../iast/stratum/SourceMapException.java | 12 -- .../agent/tooling/iast/stratum/Stratum.java | 4 +- .../tooling/iast/stratum/StratumExt.java | 10 +- .../tooling/iast/stratum/StratumManager.java | 5 +- .../tooling/iast/stratum/parser/Builder.java | 165 ++++++++++++++++- .../tooling/iast/stratum/parser/Builders.java | 175 ------------------ .../tooling/iast/stratum/parser/Parser.java | 125 ++++--------- .../tooling/iast/stratum/parser/State.java | 39 ++-- 12 files changed, 246 insertions(+), 368 deletions(-) delete mode 100755 dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/ParserException.java delete mode 100755 dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/SourceMapException.java delete mode 100644 dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builders.java diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java index 09e63b4bd4f..d0c69768fa2 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java @@ -5,28 +5,26 @@ * href="https://jakarta.ee/specifications/debugging/2.0/jdsol-spec-2.0#filesection">... */ public class FileInfo { - private int fileId = -1; + private final String fileId; - private String inputFileName; + private final String inputFileName; - private String inputFilePath; + private final String inputFilePath; - public int getFileId() { - return fileId; + public FileInfo(String fileId, String inputFileName, String inputFilePath) { + this.fileId = fileId; + this.inputFileName = inputFileName; + this.inputFilePath = inputFilePath; } - public void setFileId(final int fileId) { - this.fileId = fileId; + public String getFileId() { + return fileId; } public String getInputFileName() { return inputFileName; } - public void setInputFileName(final String inputFileName) { - this.inputFileName = inputFileName; - } - public String getInputFilePath() { if (inputFilePath == null) { return inputFileName; @@ -34,10 +32,6 @@ public String getInputFilePath() { return inputFilePath; } - public void setInputFilePath(final String inputFilePath) { - this.inputFilePath = inputFilePath; - } - @Override public String toString() { return "FileInfo [fileId=" diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/LineInfo.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/LineInfo.java index 8e275784f00..4fc8c065e96 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/LineInfo.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/LineInfo.java @@ -16,24 +16,24 @@ * href="https://jakarta.ee/specifications/debugging/2.0/jdsol-spec-2.0#stratumsection">... */ public class LineInfo { - private int fileId; + private String fileId; - int inputStartLine; + final int inputStartLine; - int repeatCount; + final int repeatCount; - int outputStartLine; + final int outputStartLine; - int outputLineIncrement; + final int outputLineIncrement; private FileInfo fileInfo; public LineInfo( - final int fileId, - final int inputStartLine, - final int repeatCount, - final int outputStartLine, - final int outputLineIncrement) { + String fileId, + int inputStartLine, + int repeatCount, + int outputStartLine, + int outputLineIncrement) { this.fileId = fileId; fileInfo = null; this.inputStartLine = inputStartLine; @@ -43,12 +43,11 @@ public LineInfo( } public LineInfo( - final FileInfo fileInfo, - final int inputStartLine, - final int repeatCount, - final int outputStartLine, - final int outputLineIncrement) { - fileId = -1; + FileInfo fileInfo, + int inputStartLine, + int repeatCount, + int outputStartLine, + int outputLineIncrement) { this.fileInfo = fileInfo; this.inputStartLine = inputStartLine; this.repeatCount = repeatCount; @@ -56,7 +55,7 @@ public LineInfo( this.outputLineIncrement = outputLineIncrement; } - public int getFileId() { + public String getFileId() { return fileId; } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/ParserException.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/ParserException.java deleted file mode 100755 index f5eb877f9f9..00000000000 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/ParserException.java +++ /dev/null @@ -1,12 +0,0 @@ -package datadog.trace.agent.tooling.iast.stratum; - -public class ParserException extends SourceMapException { - /** */ - private static final long serialVersionUID = 4991227723777615317L; - - public ParserException() {} - - public ParserException(final String msg) { - super(msg); - } -} diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Resolver.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Resolver.java index ae6cb321437..21f61d7ab74 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Resolver.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Resolver.java @@ -4,7 +4,7 @@ import java.util.List; public class Resolver { - public SourceMap resolve(final SourceMap sourceMap) { + public static SourceMap resolve(final SourceMap sourceMap) { for (EmbeddedStratum stratum : sourceMap.getEmbeddedStratumList()) { StratumExt outerStratum = sourceMap.getStratum(stratum.getName()); if (outerStratum != null) { @@ -26,13 +26,13 @@ public SourceMap resolve(final SourceMap sourceMap) { return sourceMap; } - private void resolve(final Context context) { + private static void resolve(final Context context) { for (LineInfo eli : context.embeddedStratum.getLineInfo()) { resolve(context, eli); } } - private void resolve(final Context context, final LineInfo eli) { + private static void resolve(final Context context, final LineInfo eli) { Iterator iter; if (eli.getRepeatCount() > 0) { for (iter = context.outerStratum.getLineInfo().iterator(); iter.hasNext(); ) { @@ -106,7 +106,7 @@ private void resolve(final Context context, final LineInfo eli) { } } - private FileInfo getByPath(final List list, final String filePath) { + private static FileInfo getByPath(final List list, final String filePath) { for (FileInfo fileInfo : list) { if (fileInfo.getInputFilePath().compareTo(filePath) == 0) { return fileInfo; @@ -115,7 +115,7 @@ private FileInfo getByPath(final List list, final String filePath) { return null; } - private class Context { + private static class Context { StratumExt outerStratum; diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/SourceMapException.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/SourceMapException.java deleted file mode 100755 index 9c6f2647f34..00000000000 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/SourceMapException.java +++ /dev/null @@ -1,12 +0,0 @@ -package datadog.trace.agent.tooling.iast.stratum; - -public class SourceMapException extends Exception { - /** */ - private static final long serialVersionUID = 254089927846131094L; - - public SourceMapException() {} - - public SourceMapException(final String msg) { - super(msg); - } -} diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Stratum.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Stratum.java index 8342315c0b9..2cc9968672d 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Stratum.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/Stratum.java @@ -9,8 +9,8 @@ public interface Stratum { * * @param outputLineNumber the class line number */ - Pair getInputLine(final int outputLineNumber); + Pair getInputLine(int outputLineNumber); /** Returns the source file for the given file id. */ - String getSourceFile(final int fileId); + String getSourceFile(String fileId); } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumExt.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumExt.java index cac2ebdb1d9..d4dfae0bb85 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumExt.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumExt.java @@ -17,16 +17,12 @@ public class StratumExt extends AbstractStratum implements Stratum { private static final Logger LOG = LoggerFactory.getLogger(StratumExt.class); - public StratumExt() { - this(""); - } - public StratumExt(final String name) { super(name); } @Override - public Pair getInputLine(final int outputLineNumber) { + public Pair getInputLine(final int outputLineNumber) { try { List info = getLineInfo(); int startPoint = Arrays.binarySearch(getLineStart(), outputLineNumber); @@ -57,12 +53,12 @@ public Pair getInputLine(final int outputLineNumber) { } @Override - public String getSourceFile(final int fileId) { + public String getSourceFile(String fileId) { if (fileInfo.isEmpty()) { return null; } return fileInfo.stream() - .filter(f -> f.getFileId() == fileId) + .filter(f -> f.getFileId().equals(fileId)) .findFirst() .map(FileInfo::getInputFilePath) .orElse(null); diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumManager.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumManager.java index 4318e8a93f4..f5725fee9b8 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumManager.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/StratumManager.java @@ -4,6 +4,7 @@ import datadog.trace.api.Config; import datadog.trace.api.iast.telemetry.IastMetric; import datadog.trace.api.iast.telemetry.IastMetricCollector; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import net.bytebuddy.utility.OpenedClassReader; @@ -53,9 +54,9 @@ public Stratum get(final String classname) { private SourceMap getResolvedSmap(final String smap) { try { - SourceMap[] sourceMaps = new Parser().parse(smap); + List sourceMaps = Parser.parse(smap); - SourceMap result = new Resolver().resolve(sourceMaps[0]); + SourceMap result = Resolver.resolve(sourceMaps.get(0)); // clean result object to minimize memory usage result .getStratumList() diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builder.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builder.java index 2a2bc452d2f..cc2f074224c 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builder.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builder.java @@ -1,18 +1,163 @@ package datadog.trace.agent.tooling.iast.stratum.parser; -import datadog.trace.agent.tooling.iast.stratum.SourceMapException; +import datadog.trace.agent.tooling.iast.stratum.EmbeddedStratum; +import datadog.trace.agent.tooling.iast.stratum.FileInfo; +import datadog.trace.agent.tooling.iast.stratum.LineInfo; +import datadog.trace.agent.tooling.iast.stratum.SourceMap; +import datadog.trace.agent.tooling.iast.stratum.StratumExt; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -abstract class Builder { +/** + * A collection of builders to parse SMAP Information. + * https://jakarta.ee/specifications/debugging/2.0/jdsol-spec-2.0#smap-syntax + */ +enum Builder { + CLOSE_STRATUM { + @Override + public void build(State state, List lines) { + String[] tokens = SPACE_PATTERN.split(lines.get(0), 2); + if (tokens.length < 2 || tokens[1].equals("")) { + throw new IllegalArgumentException("Stratum name expected"); + } + EmbeddedStratum embeddedStratum = new EmbeddedStratum(tokens[1]); + state.pop(embeddedStratum); + } + }, + END_SOURCE { + @Override + public void build(final State state, final List lines) { + state.endSourceMap(); + } + }, + FILE_INFO { + @Override + public void build(final State state, final List lines) { + if (!state.getStratum().getFileInfo().isEmpty()) { + throw new IllegalArgumentException("Only one file section allowed"); + } + for (int i = 1; i < lines.size(); ) { + String s = lines.get(i++); + String fileId; + String fileName; + String filePath; + if (s.startsWith("+")) { + String[] tokens = SPACE_PATTERN.split(s, 3); + fileId = tokens[1]; + fileName = tokens[2]; + if (i == lines.size()) { + throw new IllegalStateException("File path expected"); + } + filePath = lines.get(i++); + } else { + String[] tokens = SPACE_PATTERN.split(s, 2); + fileId = tokens[0]; + fileName = tokens[1]; + filePath = fileName; + } + state.getStratum().getFileInfo().add(new FileInfo(fileId, fileName, filePath)); + } + } + }, + LINE_INFO { + @Override + public void build(final State state, final List lines) { + if (!state.getStratum().getLineInfo().isEmpty()) { + throw new IllegalStateException("Only one line section allowed"); + } + String fileId = "0"; // spec says default is zero + for (int i = 1; i < lines.size(); i++) { + int inputStartLine = 1; + int repeatCount = 1; + int outputStartLine = 1; + int outputLineIncrement = 1; + Matcher m = LINE_INFO_PATTERN.matcher(lines.get(i)); + if (!m.matches()) { + throw new IllegalArgumentException("Invalid line info: " + lines.get(i)); + } + try { + inputStartLine = Integer.parseInt(m.group(1)); + if (m.group(3) != null) { + fileId = m.group(3); + } + if (m.group(5) != null) { + repeatCount = Integer.parseInt(m.group(5)); + } + outputStartLine = Integer.parseInt(m.group(6)); + if (m.group(8) != null) { + outputLineIncrement = Integer.parseInt(m.group(8)); + } + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException("Invalid line info: " + lines.get(i)); + } + LineInfo lineInfo = + new LineInfo(fileId, inputStartLine, repeatCount, outputStartLine, outputLineIncrement); + state.getStratum().addLineInfo(lineInfo); + } + } + }, + SOURCE_MAP { + @Override + public void build(final State state, final List lines) { + if (lines.size() < 3) { + throw new IllegalStateException("Source map information expected"); + } + SourceMap sourceMap = new SourceMap(lines.get(1), lines.get(2)); + state.getParentStratum().getSourceMapList().add(sourceMap); + state.setSourceMap(sourceMap); + } + }, + OPEN_EMBEDDED_STRATUM { + @Override + public void build(final State state, final List lines) { + String[] tokens = SPACE_PATTERN.split(lines.get(0), 2); + if (tokens.length < 2 || tokens[1].equals("")) { + throw new IllegalStateException("Stratum name expected"); + } + EmbeddedStratum embeddedStratum = new EmbeddedStratum(tokens[1]); + state.getSourceMap().getEmbeddedStratumList().add(embeddedStratum); + state.push(embeddedStratum); + } + }, + STRATUM { + @Override + public void build(final State state, final List lines) { + String[] tokens = SPACE_PATTERN.split(lines.get(0), 2); + if (tokens.length < 2 || tokens[1].isEmpty()) { + throw new IllegalStateException("Stratum name expected"); + } + StratumExt stratum = new StratumExt(tokens[1]); + state.getSourceMap().getStratumList().add(stratum); + state.setStratum(stratum); + } + }; - private final String section; + private static final Pattern LINE_INFO_PATTERN = + Pattern.compile("(\\d++)(#(\\d++))?(,(\\d++))?:(\\d++)(,(\\d++))?($)"); - Builder(final String section) { - this.section = section; - } + static final Pattern SPACE_PATTERN = Pattern.compile(" "); - String getSectionName() { - return section; - } + abstract void build(State paramState, List lines); - abstract void build(State paramState, String[] paramArrayOfString) throws SourceMapException; + public static Builder get(String sectionName) { + switch (sectionName) { + case "C": + return CLOSE_STRATUM; + case "E": + return END_SOURCE; + case "F": + return FILE_INFO; + case "L": + return LINE_INFO; + case "SMAP": + return SOURCE_MAP; + case "O": + return OPEN_EMBEDDED_STRATUM; + case "S": + return STRATUM; + default: + throw new IllegalArgumentException("Invalid section name: " + sectionName); + } + } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builders.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builders.java deleted file mode 100644 index 82492174db4..00000000000 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Builders.java +++ /dev/null @@ -1,175 +0,0 @@ -package datadog.trace.agent.tooling.iast.stratum.parser; - -import datadog.trace.agent.tooling.iast.stratum.EmbeddedStratum; -import datadog.trace.agent.tooling.iast.stratum.FileInfo; -import datadog.trace.agent.tooling.iast.stratum.LineInfo; -import datadog.trace.agent.tooling.iast.stratum.SourceMap; -import datadog.trace.agent.tooling.iast.stratum.SourceMapException; -import datadog.trace.agent.tooling.iast.stratum.StratumExt; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A collection of builders to parse SMAP Information. - * https://jakarta.ee/specifications/debugging/2.0/jdsol-spec-2.0#smap-syntax - */ -class Builders { - - private static final String LineInfoPattern = - "(\\d++)(#(\\d++))?(,(\\d++))?:(\\d++)(,(\\d++))?($)"; - - static final Pattern SPLITTER = Pattern.compile(" "); - - public static final Builder closeStratumBuilder() { - return new Builder("C") { - - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - String[] tokens = SPLITTER.split(lines[0], 2); - if (tokens.length < 2 || tokens[1].equals("")) { - throw new SourceMapException("Stratum name expected"); - } - EmbeddedStratum embeddedStratum = new EmbeddedStratum(tokens[1]); - state.pop(embeddedStratum); - } - }; - } - - public static final Builder endSourceMapBuilder() { - return new Builder("E") { - - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - state.endSourceMap(); - } - }; - } - - public static final Builder fileInfoBuilder() { - return new Builder("F") { - - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - if (!state.getStratum().getFileInfo().isEmpty()) { - throw new SourceMapException("Only one file section allowed"); - } - for (int i = 1; i < lines.length; ) { - FileInfo fileInfo = new FileInfo(); - String s = lines[i++]; - String fileId = "0"; - String fileName = ""; - String filePath = ""; - if (s.startsWith("+")) { - String[] tokens = SPLITTER.split(s, 3); - fileId = tokens[1]; - fileName = tokens[2]; - if (i == lines.length) { - throw new SourceMapException("File path expected"); - } - filePath = lines[i++]; - } else { - String[] tokens = SPLITTER.split(s, 2); - fileId = tokens[0]; - fileName = tokens[1]; - filePath = fileName; - } - try { - fileInfo.setFileId(Integer.parseInt(fileId)); - } catch (NumberFormatException nfe) { - throw new SourceMapException("Invalid file id: " + fileId); - } - fileInfo.setInputFileName(fileName); - fileInfo.setInputFilePath(filePath); - state.getStratum().getFileInfo().add(fileInfo); - } - } - }; - } - - public static Builder lineInfoBuilder() { - return new Builder("L") { - - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - if (!state.getStratum().getLineInfo().isEmpty()) { - throw new SourceMapException("Only one line section allowed"); - } - Pattern p = Pattern.compile(LineInfoPattern); - int fileId = 0; - for (int i = 1; i < lines.length; i++) { - int inputStartLine = 1; - int repeatCount = 1; - int outputStartLine = 1; - int outputLineIncrement = 1; - Matcher m = p.matcher(lines[i]); - if (!m.matches()) { - throw new SourceMapException("Invalid line info: " + lines[i]); - } - try { - inputStartLine = Integer.parseInt(m.group(1)); - if (m.group(3) != null) { - fileId = Integer.parseInt(m.group(3)); - } - if (m.group(5) != null) { - repeatCount = Integer.parseInt(m.group(5)); - } - outputStartLine = Integer.parseInt(m.group(6)); - if (m.group(8) != null) { - outputLineIncrement = Integer.parseInt(m.group(8)); - } - } catch (NumberFormatException nfe) { - throw new SourceMapException("Invalid line info: " + lines[i]); - } - LineInfo lineInfo = - new LineInfo( - fileId, inputStartLine, repeatCount, outputStartLine, outputLineIncrement); - state.getStratum().addLineInfo(lineInfo); - } - } - }; - } - - public static Builder sourceMapBuilder() { - return new Builder("SMAP") { - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - if (lines.length < 3) { - throw new SourceMapException("Source map information expected"); - } - SourceMap sourceMap = new SourceMap(lines[1], lines[2]); - state.getParentStratum().getSourceMapList().add(sourceMap); - state.setSourceMap(sourceMap); - } - }; - } - - public static Builder openEmbeddedStratumBuilder() { - return new Builder("O") { - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - String[] tokens = SPLITTER.split(lines[0], 2); - if (tokens.length < 2 || tokens[1].equals("")) { - throw new SourceMapException("Stratum name expected"); - } - EmbeddedStratum embeddedStratum = new EmbeddedStratum(tokens[1]); - state.getSourceMap().getEmbeddedStratumList().add(embeddedStratum); - state.push(embeddedStratum); - } - }; - } - - public static Builder stratumBuilder() { - return new Builder("S") { - @Override - public void build(final State state, final String[] lines) throws SourceMapException { - String[] tokens = SPLITTER.split(lines[0], 2); - if (tokens.length < 2 || tokens[1].equals("")) { - throw new SourceMapException("Stratum name expected"); - } - StratumExt stratum = new StratumExt(tokens[1]); - state.getSourceMap().getStratumList().add(stratum); - state.setStratum(stratum); - } - }; - } -} diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Parser.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Parser.java index cd3d9d25b33..481d544eeb8 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Parser.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/Parser.java @@ -1,151 +1,102 @@ package datadog.trace.agent.tooling.iast.stratum.parser; -import static datadog.trace.agent.tooling.iast.stratum.parser.Builders.SPLITTER; +import static datadog.trace.agent.tooling.iast.stratum.parser.Builder.SPACE_PATTERN; import datadog.trace.agent.tooling.iast.stratum.EmbeddedStratum; import datadog.trace.agent.tooling.iast.stratum.FileInfo; import datadog.trace.agent.tooling.iast.stratum.LineInfo; -import datadog.trace.agent.tooling.iast.stratum.ParserException; import datadog.trace.agent.tooling.iast.stratum.SourceMap; -import datadog.trace.agent.tooling.iast.stratum.SourceMapException; import datadog.trace.agent.tooling.iast.stratum.StratumExt; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.TreeMap; +import java.util.regex.Pattern; public class Parser { - private final Map builders = new TreeMap(); + private static final Pattern END_OF_LINE_PATTERN = Pattern.compile("\n"); - private final State state = new State(); - - public Parser() { - registerBuilders(); - } - - protected void registerBuilders() { - add(Builders.sourceMapBuilder()); - add(Builders.endSourceMapBuilder()); - add(Builders.stratumBuilder()); - add(Builders.fileInfoBuilder()); - add(Builders.lineInfoBuilder()); - add(Builders.openEmbeddedStratumBuilder()); - add(Builders.closeStratumBuilder()); - } - - private void parseInit() throws SourceMapException { - state.init(); - } - - private SourceMap[] parseDone() throws SourceMapException { + private static List parseDone(State state) { EmbeddedStratum result = state.done(); resolveLineFileInfo(result); - return result.getSourceMapList().toArray(new SourceMap[0]); + return result.getSourceMapList(); } - private void resolveLineFileInfo(final EmbeddedStratum embeddedStratum) - throws SourceMapException { - for (Iterator iter = embeddedStratum.getSourceMapList().iterator(); - iter.hasNext(); ) { - SourceMap sourceMap = iter.next(); + private static void resolveLineFileInfo(final EmbeddedStratum embeddedStratum) { + for (SourceMap sourceMap : embeddedStratum.getSourceMapList()) { resolveLineFileInfo(sourceMap); } } - private void resolveLineFileInfo(final SourceMap sourceMap) throws SourceMapException { - for (Iterator iter = sourceMap.getStratumList().iterator(); iter.hasNext(); ) { - StratumExt stratum = iter.next(); + private static void resolveLineFileInfo(final SourceMap sourceMap) { + for (StratumExt stratum : sourceMap.getStratumList()) { resolveLineFileInfo(stratum); } - for (Iterator iter = sourceMap.getEmbeddedStratumList().iterator(); - iter.hasNext(); ) { - EmbeddedStratum stratum = iter.next(); + for (EmbeddedStratum stratum : sourceMap.getEmbeddedStratumList()) { resolveLineFileInfo(stratum); } } - private void resolveLineFileInfo(final StratumExt stratum) throws SourceMapException { - for (Iterator iter = stratum.getLineInfo().iterator(); iter.hasNext(); ) { - LineInfo lineInfo = iter.next(); + private static void resolveLineFileInfo(final StratumExt stratum) { + for (LineInfo lineInfo : stratum.getLineInfo()) { FileInfo fileInfo = get(stratum.getFileInfo(), lineInfo.getFileId()); if (fileInfo == null) { - throw new ParserException("Invalid file id: " + lineInfo.getFileId()); + throw new IllegalArgumentException("Invalid file id: " + lineInfo.getFileId()); } lineInfo.setFileInfo(fileInfo); } } - public FileInfo get(final List list, final int fileId) { + public static FileInfo get(final List list, String fileId) { for (FileInfo fileInfo : list) { - if (fileInfo.getFileId() == fileId) { + if (fileInfo.getFileId().equals(fileId)) { return fileInfo; } } return null; } - private Builder getBuilder(final String[] lines) throws SourceMapException { - if (lines.length == 0) { + private static Builder getBuilder(List lines) { + if (lines.isEmpty()) { return null; } - String sectionName = lines[0]; - String[] tokens = SPLITTER.split(lines[0], 2); + String sectionName = lines.get(0); + String[] tokens = SPACE_PATTERN.split(lines.get(0), 2); if (tokens.length > 1) { sectionName = tokens[0].trim(); } if (sectionName.startsWith("*")) { sectionName = sectionName.substring("*".length()); } - return builders.get(sectionName); + return Builder.get(sectionName); } - private void parseSection(final String[] lines) throws SourceMapException { + private static void parseSection(State state, List lines) { Builder builder = getBuilder(lines); if (builder != null) { builder.build(state, lines); } } - public SourceMap[] parse(final String source) throws SourceMapException, IOException { - return parse(new StringReader(source)); - } - - public SourceMap[] parse(final Reader reader) throws SourceMapException, IOException { - String line = ""; + public static List parse(String source) { + State state = new State(); + String line = null; try { - parseInit(); - ArrayList lines = new ArrayList(); - BufferedReader br = new BufferedReader(reader); - boolean sectionLine = true; - while ((line = br.readLine()) != null) { + String[] lines = END_OF_LINE_PATTERN.split(source); + boolean isSectionLine = true; + List sectionLines = new ArrayList<>(); + for (int i = 0; i < lines.length; i++) { + line = lines[i]; state.lineNumber += 1; - if (line.startsWith("*") || sectionLine && line.equals("SMAP")) { - parseSection(lines.toArray(new String[0])); - lines.clear(); + if (line.startsWith("*") || isSectionLine && line.equals("SMAP")) { + parseSection(state, sectionLines); + sectionLines.clear(); } - sectionLine = line.startsWith("*"); - lines.add(line); + isSectionLine = line.startsWith("*"); + sectionLines.add(line); } - parseSection(lines.toArray(new String[0])); - return parseDone(); - } catch (SourceMapException sme) { - ParserException pe = - new ParserException(sme.getMessage() + ":" + state.lineNumber + ":" + line); - pe.initCause(sme); - throw pe; + parseSection(state, sectionLines); + return parseDone(state); + } catch (Exception sme) { + throw new RuntimeException(sme.getMessage() + ":" + state.lineNumber + ":" + line, sme); } } - - public void add(final Builder builder) { - builders.put(builder.getSectionName(), builder); - } - - public void remove(final Builder builder) { - builders.remove(builder.getSectionName()); - } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/State.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/State.java index 4f6659a07bd..066e6fb695d 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/State.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/parser/State.java @@ -1,9 +1,7 @@ package datadog.trace.agent.tooling.iast.stratum.parser; import datadog.trace.agent.tooling.iast.stratum.EmbeddedStratum; -import datadog.trace.agent.tooling.iast.stratum.ParserException; import datadog.trace.agent.tooling.iast.stratum.SourceMap; -import datadog.trace.agent.tooling.iast.stratum.SourceMapException; import datadog.trace.agent.tooling.iast.stratum.StratumExt; import java.util.ArrayDeque; import java.util.Deque; @@ -13,23 +11,15 @@ class State { private StratumExt stratum; - private EmbeddedStratum parentStratum; + private EmbeddedStratum parentStratum = new EmbeddedStratum(); private final Deque stateStack = new ArrayDeque<>(); int lineNumber; - public void init() { - lineNumber = 0; - sourceMap = null; - stratum = null; - parentStratum = new EmbeddedStratum(); - stateStack.clear(); - } - - public EmbeddedStratum done() throws SourceMapException { + public EmbeddedStratum done() { if (!stateStack.isEmpty()) { - throw new ParserException("Unbalanced source map"); + throw new IllegalStateException("Unbalanced source map"); } return parentStratum; } @@ -38,45 +28,46 @@ public SourceMap getSourceMap() { return sourceMap; } - void setSourceMap(final SourceMap sourceMap) throws SourceMapException { + void setSourceMap(final SourceMap sourceMap) { if (this.sourceMap != null) { - throw new ParserException("End of source map expected"); + throw new IllegalStateException("End of source map expected"); } this.sourceMap = sourceMap; stratum = null; } - void endSourceMap() throws SourceMapException { + void endSourceMap() { if (sourceMap == null) { - throw new ParserException("Unexpected end of source map"); + throw new IllegalStateException("Unexpected end of source map"); } sourceMap = null; stratum = null; } - public StratumExt getStratum() throws SourceMapException { + public StratumExt getStratum() { if (stratum == null) { - throw new ParserException("Stratum expected"); + throw new IllegalStateException("Stratum expected"); } return stratum; } - void setStratum(final StratumExt stratum) throws SourceMapException { + void setStratum(final StratumExt stratum) { if (sourceMap == null) { - throw new ParserException("Source map expected"); + throw new IllegalStateException("Source map expected"); } this.stratum = stratum; } - void push(final EmbeddedStratum embeddedStratum) throws SourceMapException { + void push(final EmbeddedStratum embeddedStratum) { stateStack.push(new StackItem(sourceMap, parentStratum)); endSourceMap(); setParentStratum(embeddedStratum); } - void pop(final EmbeddedStratum embeddedStratum) throws SourceMapException { + void pop(final EmbeddedStratum embeddedStratum) { if (!parentStratum.getName().equals(embeddedStratum.getName())) { - throw new ParserException("Invalid closing embedded stratum: " + embeddedStratum.getName()); + throw new IllegalArgumentException( + "Invalid closing embedded stratum: " + embeddedStratum.getName()); } StackItem item = stateStack.pop(); setSourceMap(item.sourceMap); From 7c038681a840fef66be837f8c42f79427c5792d8 Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 11:57:50 +0100 Subject: [PATCH 2/8] move packages --- .../{iast => }/stratum/AbstractStratum.java | 2 +- .../{iast => }/stratum/EmbeddedStratum.java | 2 +- .../agent/tooling/{iast => }/stratum/FileInfo.java | 2 +- .../agent/tooling/{iast => }/stratum/LineInfo.java | 2 +- .../agent/tooling/{iast => }/stratum/Location.java | 2 +- .../agent/tooling/{iast => }/stratum/Resolver.java | 2 +- .../tooling/{iast => }/stratum/SourceMap.java | 2 +- .../agent/tooling/{iast => }/stratum/Stratum.java | 2 +- .../tooling/{iast => }/stratum/StratumExt.java | 2 +- .../tooling/{iast => }/stratum/StratumManager.java | 4 ++-- .../tooling/{iast => }/stratum/parser/Builder.java | 12 ++++++------ .../tooling/{iast => }/stratum/parser/Parser.java | 14 +++++++------- .../tooling/{iast => }/stratum/parser/State.java | 8 ++++---- .../{iast => }/stratum/StratumManagerTest.groovy | 3 ++- .../iastinstrumenter/SourceMapperImpl.java | 4 ++-- .../iastinstrumenter/StratumListener.java | 2 +- .../iastinstrumenter/SourceMapperImplTest.groovy | 4 ++-- 17 files changed, 35 insertions(+), 34 deletions(-) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/AbstractStratum.java (83%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/EmbeddedStratum.java (88%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/FileInfo.java (95%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/LineInfo.java (97%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/Location.java (86%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/Resolver.java (99%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/SourceMap.java (95%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/Stratum.java (88%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/StratumExt.java (98%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/StratumManager.java (97%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/parser/Builder.java (93%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/parser/Parser.java (86%) rename dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/{iast => }/stratum/parser/State.java (90%) rename dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/{iast => }/stratum/StratumManagerTest.groovy (94%) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/AbstractStratum.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/AbstractStratum.java similarity index 83% rename from dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/AbstractStratum.java rename to dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/AbstractStratum.java index ea15d4de9cd..9e7848143af 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/AbstractStratum.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/AbstractStratum.java @@ -1,4 +1,4 @@ -package datadog.trace.agent.tooling.iast.stratum; +package datadog.trace.agent.tooling.stratum; public abstract class AbstractStratum { private String name; diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/EmbeddedStratum.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/EmbeddedStratum.java similarity index 88% rename from dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/EmbeddedStratum.java rename to dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/EmbeddedStratum.java index 17801f0b109..23f2e5db950 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/EmbeddedStratum.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/EmbeddedStratum.java @@ -1,4 +1,4 @@ -package datadog.trace.agent.tooling.iast.stratum; +package datadog.trace.agent.tooling.stratum; import java.util.ArrayList; import java.util.List; diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/FileInfo.java similarity index 95% rename from dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java rename to dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/FileInfo.java index d0c69768fa2..3a9ab802397 100755 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/iast/stratum/FileInfo.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/FileInfo.java @@ -1,4 +1,4 @@ -package datadog.trace.agent.tooling.iast.stratum; +package datadog.trace.agent.tooling.stratum; /** * The fileInfo describes the translated-source file names Date: Thu, 15 Jan 2026 14:43:57 +0100 Subject: [PATCH 3/8] fix compilation --- .../instrumentation/iastinstrumenter/SourceMapperImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java index a926ce9362b..91fe3428e19 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java @@ -27,7 +27,7 @@ public Pair getFileAndLine(String className, int lineNumber) { if (stratum == null) { return null; } - Pair inputLine = stratum.getInputLine(lineNumber); + Pair inputLine = stratum.getInputLine(lineNumber); if (inputLine == null) { return null; } From 1ea13d5b5218c10d16993bf6e7e64342739e1f84 Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 17:23:30 +0100 Subject: [PATCH 4/8] Remove dependency to IAST with StratumManager Fix tests --- .../agent/tooling/stratum/StratumManager.java | 13 +------------ .../iastinstrumenter/IastInstrumentation.java | 8 ++++++-- .../iastinstrumenter/SourceMapperImpl.java | 2 +- .../iastinstrumenter/StratumListener.java | 17 ++++++++++++----- .../SourceMapperImplTest.groovy | 4 ++-- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java index e59a1552d2d..6f3c6a09376 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java @@ -1,7 +1,6 @@ package datadog.trace.agent.tooling.stratum; import datadog.trace.agent.tooling.stratum.parser.Parser; -import datadog.trace.api.Config; import datadog.trace.api.iast.telemetry.IastMetric; import datadog.trace.api.iast.telemetry.IastMetricCollector; import java.util.List; @@ -23,21 +22,11 @@ public class StratumManager { private final LimitedConcurrentHashMap map; - public static final StratumManager INSTANCE = - new StratumManager(Config.get().getIastSourceMappingMaxSize()); - - private StratumManager(int sourceMappingLimit) { + public StratumManager(int sourceMappingLimit) { // Prevent instantiation this.map = new LimitedConcurrentHashMap(sourceMappingLimit); } - public static boolean shouldBeAnalyzed(final String internalClassName) { - return internalClassName.contains("jsp") - && (internalClassName.contains("_jsp") - || internalClassName.contains("jsp_") - || internalClassName.contains("_tag")); - } - public void analyzeClass(final byte[] bytes) { if (map.isLimitReached()) { return; diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java index 12174161bec..e116c62ea9e 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java @@ -9,6 +9,7 @@ import datadog.trace.agent.tooling.bytebuddy.csi.CallSiteInstrumentation; import datadog.trace.agent.tooling.bytebuddy.csi.CallSiteSupplier; import datadog.trace.agent.tooling.csi.CallSites; +import datadog.trace.agent.tooling.stratum.StratumManager; import datadog.trace.api.Config; import datadog.trace.api.InstrumenterConfig; import datadog.trace.api.ProductActivation; @@ -17,6 +18,7 @@ import datadog.trace.api.iast.telemetry.Verbosity; import datadog.trace.instrumentation.iastinstrumenter.service.CallSitesLoader; import datadog.trace.instrumentation.iastinstrumenter.telemetry.TelemetryCallSiteSupplier; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -52,14 +54,16 @@ protected CallSiteSupplier callSites() { @Override protected Advices buildAdvices(final Iterable callSites) { - final List listeners = new LinkedList<>(); + final List listeners = new ArrayList<>(); final boolean iastActive = InstrumenterConfig.get().getIastActivation() == ProductActivation.FULLY_ENABLED; if (iastActive) { if (Config.get().isIastHardcodedSecretEnabled()) { listeners.add(IastHardcodedSecretListener.INSTANCE); } - listeners.add(StratumListener.INSTANCE); + StratumManager stratumManager = + new StratumManager(Config.get().getIastSourceMappingMaxSize()); + listeners.add(new StratumListener(stratumManager)); } return Advices.fromCallSites(callSites, listeners.toArray(new Listener[0])); } diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java index 91fe3428e19..21ca506f426 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java @@ -11,7 +11,7 @@ public class SourceMapperImpl implements SourceMapper { // This is only available if IAST source mapping is enabled public static final SourceMapperImpl INSTANCE = Config.get().isIastSourceMappingEnabled() - ? new SourceMapperImpl(StratumManager.INSTANCE) + ? new SourceMapperImpl(new StratumManager(Config.get().getIastSourceMappingMaxSize())) : null; private final StratumManager stratumManager; diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/StratumListener.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/StratumListener.java index cc1a3759a2d..4352faacf1f 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/StratumListener.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/StratumListener.java @@ -8,17 +8,24 @@ public class StratumListener implements Advices.Listener { - public static final StratumListener INSTANCE = new StratumListener(); + private final StratumManager stratumManager; - private StratumListener() { - // Prevent instantiation + public StratumListener(StratumManager stratumManager) { + this.stratumManager = stratumManager; } @Override public void onConstantPool( @Nonnull TypeDescription type, @Nonnull ConstantPool pool, byte[] classFile) { - if (StratumManager.shouldBeAnalyzed(type.getInternalName())) { - StratumManager.INSTANCE.analyzeClass(classFile); + if (shouldBeAnalyzed(type.getInternalName())) { + stratumManager.analyzeClass(classFile); } } + + private static boolean shouldBeAnalyzed(final String internalClassName) { + return internalClassName.contains("jsp") + && (internalClassName.contains("_jsp") + || internalClassName.contains("jsp_") + || internalClassName.contains("_tag")); + } } diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImplTest.groovy b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImplTest.groovy index 60032042575..f7bbc2d2d46 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImplTest.groovy +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImplTest.groovy @@ -41,8 +41,8 @@ class SourceMapperImplTest extends InstrumentationSpecification { then: "stratum exists and input line number is found" 1 * stratumManager.get("foo/bar/Baz") >> stratum - 1 * stratum.getInputLine(_) >> new Pair<>(1, 52) - 1 * stratum.getSourceFile(1) >> "foo/bar/Baz.jsp" + 1 * stratum.getInputLine(_) >> new Pair<>("1", 52) + 1 * stratum.getSourceFile("1") >> "foo/bar/Baz.jsp" result.getLeft() == "foo/bar/Baz.jsp" result.getRight() == 52 } From ee7469a93f28a6472118b3e09775e0de5b7b3417 Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 17:36:38 +0100 Subject: [PATCH 5/8] remove iast metric from StratumManager --- .../trace/agent/tooling/stratum/StratumManager.java | 13 +++++++------ .../iastinstrumenter/IastInstrumentation.java | 10 +++++++++- .../iastinstrumenter/SourceMapperImpl.java | 12 ++++++++++-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java index 6f3c6a09376..6e462f50031 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java @@ -1,11 +1,10 @@ package datadog.trace.agent.tooling.stratum; import datadog.trace.agent.tooling.stratum.parser.Parser; -import datadog.trace.api.iast.telemetry.IastMetric; -import datadog.trace.api.iast.telemetry.IastMetricCollector; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.IntConsumer; import net.bytebuddy.utility.OpenedClassReader; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -22,9 +21,9 @@ public class StratumManager { private final LimitedConcurrentHashMap map; - public StratumManager(int sourceMappingLimit) { + public StratumManager(int sourceMappingLimit, IntConsumer limitReachedCallback) { // Prevent instantiation - this.map = new LimitedConcurrentHashMap(sourceMappingLimit); + this.map = new LimitedConcurrentHashMap(sourceMappingLimit, limitReachedCallback); } public void analyzeClass(final byte[] bytes) { @@ -107,11 +106,13 @@ public void visitSource(final String source, final String debug) { static class LimitedConcurrentHashMap { private final int maxSize; + private final IntConsumer limitReachedCallback; private volatile boolean limitReached = false; private final Map map = new ConcurrentHashMap<>(); - public LimitedConcurrentHashMap(int maxSize) { + public LimitedConcurrentHashMap(int maxSize, IntConsumer limitReachedCallback) { this.maxSize = maxSize; + this.limitReachedCallback = limitReachedCallback; } public void put(String className, StratumExt value) { @@ -121,7 +122,7 @@ public void put(String className, StratumExt value) { } map.put(className, value); if (this.size() >= maxSize) { - IastMetricCollector.add(IastMetric.SOURCE_MAPPING_LIMIT_REACHED, 1); + limitReachedCallback.accept(maxSize); limitReached = true; } } diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java index e116c62ea9e..145d4ded3db 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java @@ -15,6 +15,8 @@ import datadog.trace.api.ProductActivation; import datadog.trace.api.appsec.RaspCallSites; import datadog.trace.api.iast.IastCallSites; +import datadog.trace.api.iast.telemetry.IastMetric; +import datadog.trace.api.iast.telemetry.IastMetricCollector; import datadog.trace.api.iast.telemetry.Verbosity; import datadog.trace.instrumentation.iastinstrumenter.service.CallSitesLoader; import datadog.trace.instrumentation.iastinstrumenter.telemetry.TelemetryCallSiteSupplier; @@ -62,12 +64,18 @@ protected Advices buildAdvices(final Iterable callSites) { listeners.add(IastHardcodedSecretListener.INSTANCE); } StratumManager stratumManager = - new StratumManager(Config.get().getIastSourceMappingMaxSize()); + new StratumManager( + Config.get().getIastSourceMappingMaxSize(), + IastInstrumentation::onSourceMappingLimitReached); listeners.add(new StratumListener(stratumManager)); } return Advices.fromCallSites(callSites, listeners.toArray(new Listener[0])); } + private static void onSourceMappingLimitReached(int maxSize) { + IastMetricCollector.add(IastMetric.SOURCE_MAPPING_LIMIT_REACHED, 1); + } + public static final class IastMatchers { public static final ElementMatcher INSTANCE; diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java index 21ca506f426..9ab4706d506 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java @@ -5,22 +5,30 @@ import datadog.trace.api.Config; import datadog.trace.api.Pair; import datadog.trace.api.iast.stratum.SourceMapper; +import datadog.trace.api.iast.telemetry.IastMetric; +import datadog.trace.api.iast.telemetry.IastMetricCollector; public class SourceMapperImpl implements SourceMapper { // This is only available if IAST source mapping is enabled public static final SourceMapperImpl INSTANCE = Config.get().isIastSourceMappingEnabled() - ? new SourceMapperImpl(new StratumManager(Config.get().getIastSourceMappingMaxSize())) + ? new SourceMapperImpl( + new StratumManager( + Config.get().getIastSourceMappingMaxSize(), + SourceMapperImpl::onSourceMappingLimitReached)) : null; private final StratumManager stratumManager; private SourceMapperImpl(StratumManager stratumManager) { - // Prevent instantiation this.stratumManager = stratumManager; } + private static void onSourceMappingLimitReached(int maxSize) { + IastMetricCollector.add(IastMetric.SOURCE_MAPPING_LIMIT_REACHED, 1); + } + @Override public Pair getFileAndLine(String className, int lineNumber) { Stratum stratum = stratumManager.get(className); From d624014b5f120ef3151e150cd3e66313c0eb6adb Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 18:16:41 +0100 Subject: [PATCH 6/8] fix tests --- .../tooling/stratum/StratumManagerTest.groovy | 26 ++++--------------- .../groovy/IastInstrumentationTest.groovy | 20 ++++++++++++++ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy index 024ab5924a6..d1fd9dea2e2 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy @@ -2,37 +2,21 @@ package datadog.trace.agent.tooling.stratum import datadog.trace.agent.tooling.stratum.StratumManager import datadog.trace.test.util.DDSpecification +import java.util.function.IntConsumer import org.apache.commons.io.FileUtils class StratumManagerTest extends DDSpecification { - void 'test shouldBeAnalyzed'(){ - - when: - def result = StratumManager.shouldBeAnalyzed(internalClassName) - - then: - result == expected - - where: - internalClassName | expected - 'foo/bar/Baz' | false - 'foo/jsp/Baz' | false - 'foo/bar/Baz_jsp' | true - 'foo/bar/jsp_Baz' | true - 'foo/bar/Baz_tag' | false - 'foo/bar/jsp/Baz_tag' | true - } - void 'test analyzeClass'(){ given: + StratumManager stratumManager = new StratumManager(1000, {}) byte[] data = FileUtils.readFileToByteArray(new File("src/test/resources/datadog.trace.agent.tooling.stratum/register_jsp.class")) when: - StratumManager.INSTANCE.analyzeClass(data) + stratumManager.analyzeClass(data) then: - final result = StratumManager.INSTANCE.get("org.apache.jsp.register_jsp") + final result = stratumManager.get("org.apache.jsp.register_jsp") result != null final inputLine = result.getInputLine(216) inputLine.right == 70 @@ -42,7 +26,7 @@ class StratumManagerTest extends DDSpecification { void 'test limit reached'(){ setup: - def newStratumManager = new StratumManager(1) + def newStratumManager = new StratumManager(1, {}) byte[] data = FileUtils.readFileToByteArray(new File("src/test/resources/datadog.trace.agent.tooling.stratum/register_jsp.class")) when: diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy index 6aac988c1af..842bb921cb4 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy @@ -1,7 +1,9 @@ import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.agent.tooling.stratum.StratumManager import datadog.trace.api.config.IastConfig import datadog.trace.instrumentation.iastinstrumenter.IastHardcodedSecretListener import datadog.trace.instrumentation.iastinstrumenter.IastInstrumentation +import datadog.trace.instrumentation.iastinstrumenter.StratumListener import net.bytebuddy.description.type.TypeDescription class IastInstrumentationTest extends InstrumentationSpecification { @@ -44,4 +46,22 @@ class IastInstrumentationTest extends InstrumentationSpecification { 'true' | true 'false' | false } + + void 'test shouldBeAnalyzed'(){ + + when: + def result = StratumListener.shouldBeAnalyzed(internalClassName) + + then: + result == expected + + where: + internalClassName | expected + 'foo/bar/Baz' | false + 'foo/jsp/Baz' | false + 'foo/bar/Baz_jsp' | true + 'foo/bar/jsp_Baz' | true + 'foo/bar/Baz_tag' | false + 'foo/bar/jsp/Baz_tag' | true + } } From 8e99e167e60fcf7c7dbb4774e4eeb2f9fc8f17e6 Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 21:00:07 +0100 Subject: [PATCH 7/8] fix tests --- .../agent/tooling/stratum/StratumManager.java | 14 ++++++++++++-- .../iastinstrumenter/IastInstrumentation.java | 2 +- .../iastinstrumenter/SourceMapperImpl.java | 11 +---------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java index 6e462f50031..a38813c3e8d 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/stratum/StratumManager.java @@ -19,10 +19,20 @@ public class StratumManager { private static final Logger LOG = LoggerFactory.getLogger(StratumManager.class); + private static volatile StratumManager INSTANCE; + private final LimitedConcurrentHashMap map; - public StratumManager(int sourceMappingLimit, IntConsumer limitReachedCallback) { - // Prevent instantiation + public static StratumManager init(int sourceMappingLimit, IntConsumer limitReachedCallback) { + INSTANCE = new StratumManager(sourceMappingLimit, limitReachedCallback); + return INSTANCE; + } + + public static StratumManager getInstance() { + return INSTANCE; + } + + private StratumManager(int sourceMappingLimit, IntConsumer limitReachedCallback) { this.map = new LimitedConcurrentHashMap(sourceMappingLimit, limitReachedCallback); } diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java index 145d4ded3db..640f899c67a 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java @@ -64,7 +64,7 @@ protected Advices buildAdvices(final Iterable callSites) { listeners.add(IastHardcodedSecretListener.INSTANCE); } StratumManager stratumManager = - new StratumManager( + StratumManager.init( Config.get().getIastSourceMappingMaxSize(), IastInstrumentation::onSourceMappingLimitReached); listeners.add(new StratumListener(stratumManager)); diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java index 9ab4706d506..349439662f7 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/SourceMapperImpl.java @@ -5,18 +5,13 @@ import datadog.trace.api.Config; import datadog.trace.api.Pair; import datadog.trace.api.iast.stratum.SourceMapper; -import datadog.trace.api.iast.telemetry.IastMetric; -import datadog.trace.api.iast.telemetry.IastMetricCollector; public class SourceMapperImpl implements SourceMapper { // This is only available if IAST source mapping is enabled public static final SourceMapperImpl INSTANCE = Config.get().isIastSourceMappingEnabled() - ? new SourceMapperImpl( - new StratumManager( - Config.get().getIastSourceMappingMaxSize(), - SourceMapperImpl::onSourceMappingLimitReached)) + ? new SourceMapperImpl(StratumManager.getInstance()) : null; private final StratumManager stratumManager; @@ -25,10 +20,6 @@ private SourceMapperImpl(StratumManager stratumManager) { this.stratumManager = stratumManager; } - private static void onSourceMappingLimitReached(int maxSize) { - IastMetricCollector.add(IastMetric.SOURCE_MAPPING_LIMIT_REACHED, 1); - } - @Override public Pair getFileAndLine(String className, int lineNumber) { Stratum stratum = stratumManager.get(className); From 7c3d62b2ad31b864cfe0d988903e26490a40359b Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Thu, 15 Jan 2026 22:31:45 +0100 Subject: [PATCH 8/8] fix codenarc --- .../trace/agent/tooling/stratum/StratumManagerTest.groovy | 2 -- .../src/test/groovy/IastInstrumentationTest.groovy | 1 - 2 files changed, 3 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy index d1fd9dea2e2..411798fa59b 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/stratum/StratumManagerTest.groovy @@ -1,8 +1,6 @@ package datadog.trace.agent.tooling.stratum -import datadog.trace.agent.tooling.stratum.StratumManager import datadog.trace.test.util.DDSpecification -import java.util.function.IntConsumer import org.apache.commons.io.FileUtils class StratumManagerTest extends DDSpecification { diff --git a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy index 842bb921cb4..7aa366c23c1 100644 --- a/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/datadog/asm/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy @@ -1,5 +1,4 @@ import datadog.trace.agent.test.InstrumentationSpecification -import datadog.trace.agent.tooling.stratum.StratumManager import datadog.trace.api.config.IastConfig import datadog.trace.instrumentation.iastinstrumenter.IastHardcodedSecretListener import datadog.trace.instrumentation.iastinstrumenter.IastInstrumentation