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

io.codemodder.remediation.xss.DefaultXSSRemediator Maven / Gradle / Ivy

package io.codemodder.remediation.xss;

import static java.util.stream.Collectors.groupingBy;

import com.github.javaparser.ast.CompilationUnit;
import io.codemodder.CodemodChange;
import io.codemodder.CodemodFileScanningResult;
import io.codemodder.DependencyGAV;
import io.codemodder.codetf.DetectorRule;
import io.codemodder.codetf.FixedFinding;
import io.codemodder.codetf.UnfixedFinding;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

final class DefaultXSSRemediator implements XSSRemediator {

  private final List javaFixers;

  DefaultXSSRemediator() {
    this.javaFixers = List.of(new PrintingMethodFixer(), new NakedVariableReturnFixer());
  }

  @Override
  public  CodemodFileScanningResult remediateJava(
      final CompilationUnit cu,
      final String path,
      final DetectorRule detectorRule,
      final List issuesForFile,
      final Function getKey,
      final Function getLine,
      final Function getColumn) {

    List> fixGroups = createFixGroups(issuesForFile, getLine, getColumn);

    List unfixedFindings = new ArrayList<>();
    List changes = new ArrayList<>();

    for (XSSFixGroup fixGroup : fixGroups) {
      boolean foundResponsibleFixer = false;
      for (XSSCodeShapeFixer javaFixer : javaFixers) {
        XSSCodeShapeFixResult fixResult =
            javaFixer.fixCodeShape(
                cu, path, detectorRule, fixGroup.issues(), getKey, getLine, getColumn);
        if (fixResult.isResponsibleFixer()) {
          foundResponsibleFixer = true;
          if (fixResult.isFixed()) {
            List fixes =
                fixGroup.issues().stream()
                    .map(fix -> new FixedFinding(getKey.apply(fix), detectorRule))
                    .toList();
            changes.add(
                CodemodChange.from(
                    fixResult.line(), List.of(DependencyGAV.OWASP_XSS_JAVA_ENCODER), fixes));
          } else {
            List unfixed =
                fixGroup.issues().stream()
                    .map(
                        fix ->
                            new UnfixedFinding(
                                getKey.apply(fix),
                                detectorRule,
                                path,
                                fixResult.line(),
                                fixResult.reasonNotFixed()))
                    .toList();
            unfixedFindings.addAll(unfixed);
          }
          // if this was the responsible fixer, no need to continue
          break;
        }
      }
      if (!foundResponsibleFixer) {
        unfixedFindings.addAll(
            fixGroup.issues().stream()
                .map(
                    fix ->
                        new UnfixedFinding(
                            getKey.apply(fix),
                            detectorRule,
                            path,
                            getLine.apply(fix),
                            "Couldn't fix that shape of code"))
                .toList());
      }
    }
    return CodemodFileScanningResult.from(changes, unfixedFindings);
  }

  /** Split the issues into fix groups that all have the same location. */
  private  List> createFixGroups(
      final List issuesForFile,
      final Function getLine,
      final Function getColumn) {
    List> fixGroups = new ArrayList<>();

    Map> fixesPerLine = issuesForFile.stream().collect(groupingBy(getLine));

    // now further separate the fixes by column if it's available
    for (Map.Entry> entry : fixesPerLine.entrySet()) {
      Map> fixesPerColumn =
          entry.getValue().stream().collect(groupingBy(getColumn));
      for (List columnFixes : fixesPerColumn.values()) {
        fixGroups.add(new XSSFixGroup<>(columnFixes));
      }
    }

    return List.copyOf(fixGroups);
  }

  @Override
  public  CodemodFileScanningResult remediateJSP(
      final Path filePath,
      final String path,
      final DetectorRule detectorRule,
      final List issuesForFile,
      final Function getKey,
      final Function getLine,
      final Function getColumn) {
    return CodemodFileScanningResult.none();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy