All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.codemodder.remediation.xxe.XMLReaderAtParseFixer Maven / Gradle / Ivy

package io.codemodder.remediation.xxe;

import static io.codemodder.remediation.RemediationMessages.multipleNodesFound;
import static io.codemodder.remediation.RemediationMessages.noNodesAtThatLocation;

import com.github.javaparser.Position;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithType;
import com.github.javaparser.ast.stmt.Statement;
import io.codemodder.ast.ASTs;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/** Fixes XXEs that are reported at the XMLReader#parse() call. */
final class XMLReaderAtParseFixer implements XXEFixer {

  @Override
  public XXEFixAttempt tryFix(final int line, final Integer column, final CompilationUnit cu) {
    List candidateMethods =
        cu.findAll(MethodCallExpr.class).stream()
            .filter(m -> "parse".equals(m.getNameAsString()))
            .filter(m -> m.getScope().isPresent())
            .filter(m -> m.getScope().get().isNameExpr())
            .filter(
                m -> {
                  Optional sourceRef =
                      ASTs.findNonCallableSimpleNameSource(
                          m.getScope().get().asNameExpr().getName());
                  if (sourceRef.isEmpty()) {
                    return false;
                  }
                  Node source = sourceRef.get();
                  if (source instanceof NodeWithType) {
                    return Set.of("XMLReader", "org.xml.sax.XMLReader")
                        .contains(((NodeWithType) source).getTypeAsString());
                  }
                  return false;
                })
            .filter(m -> m.getRange().isPresent())
            .filter(m -> m.getRange().get().begin.line == line)
            .toList();

    if (column != null) {
      Position reportedPosition = new Position(line, column);
      candidateMethods =
          candidateMethods.stream()
              .filter(m -> m.getRange().get().contains(reportedPosition))
              .toList();
    }

    if (candidateMethods.isEmpty()) {
      return new XXEFixAttempt(false, false, noNodesAtThatLocation);
    } else if (candidateMethods.size() > 1) {
      return new XXEFixAttempt(false, false, multipleNodesFound);
    }

    MethodCallExpr parseCall = candidateMethods.get(0);
    Optional parserRef = parseCall.getScope();
    if (parserRef.isEmpty()) {
      return new XXEFixAttempt(false, false, "No scope found for parse() call");
    } else if (!parserRef.get().isNameExpr()) {
      return new XXEFixAttempt(false, false, "Scope is not a name expression");
    }
    NameExpr parser = parserRef.get().asNameExpr();
    Optional parseStatement = parseCall.findAncestor(Statement.class);
    if (parseStatement.isEmpty()) {
      return new XXEFixAttempt(true, false, "No statement found for parse() call");
    }
    return XMLFeatures.addFeatureDisablingStatements(
        parser.asNameExpr(), parseStatement.get(), true);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy