Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import com.fortify.cli.aviator._common.exception.AviatorSimpleException;
import com.fortify.cli.aviator._common.exception.AviatorTechnicalException;
import com.fortify.cli.aviator.config.IAviatorLogger;
import com.fortify.cli.aviator.fpr.processor.RemediationProcessor;
import com.fortify.cli.aviator.fpr.processor.RemediationProcessor.RemediationMetric;
import com.fortify.cli.aviator.fpr.remediation.RemediationProcessor;
import com.fortify.cli.aviator.fpr.remediation.model.RemediationMetric;
import com.fortify.cli.aviator.fpr.utils.ISourceDecoder;
import com.fortify.cli.aviator.fpr.utils.SourceDecoders;
import com.fortify.cli.aviator.util.FprHandle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,13 @@
import com.fortify.cli.aviator.fpr.utils.ISourceDecoder;
import com.fortify.cli.aviator.fpr.utils.SourceDecoders;
import com.fortify.cli.aviator.util.Constants;
import com.fortify.cli.aviator.util.FileUtil;
import com.fortify.cli.aviator.util.FprHandle;

import lombok.Setter;



public class AuditProcessor {

Logger logger = LoggerFactory.getLogger(AuditProcessor.class);
Expand Down Expand Up @@ -938,7 +940,9 @@ private Document generateRemediationsXml(Map<String, AuditResponse> auditRespons
changeElement.appendChild(originalCodeElement);

Element newCodeElement = finalDoc.createElementNS(REMEDIATIONS_NAMESPACE_URI, "NewCode");
newCodeElement.appendChild(finalDoc.createCDATASection(change.getReplaceWith() != null ? change.getReplaceWith() : ""));
String sanitizedNewCode = FileUtil.stripSyntheticLineMarkers(
change.getReplaceWith() != null ? change.getReplaceWith() : "", filename);
newCodeElement.appendChild(finalDoc.createCDATASection(sanitizedNewCode));
changeElement.appendChild(newCodeElement);

final int CONTEXT_LINES = 3;
Expand Down Expand Up @@ -1007,10 +1011,13 @@ private void recordSkipped(Map<String, Integer> skippedByReason, RemediationSkip
}

private String calculateHashBase64(String content, String algorithm) {
if (content == null) return "";
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] digest = md.digest(content.getBytes(StandardCharsets.UTF_8));
// hash the canonical form (LF-normalised, no trailing newline) so the apply
// side can reproduce the digest regardless of the OS that ran the audit or the
// file's trailing-newline state.
String canonical = FileUtil.canonicalizeForHash(content);
byte[] digest = md.digest(canonical.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(digest);
} catch (NoSuchAlgorithmException e) {
throw new AviatorTechnicalException("Hashing algorithm not available: " + algorithm, e);
Expand Down

This file was deleted.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2021-2026 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*/
package com.fortify.cli.aviator.fpr.remediation;

public enum SkipReason {
SOURCE_FILE_MISSING("Source file missing"),
SOURCE_FILE_OUTSIDE_SOURCE_DIR("Source file outside source directory"),
SOURCE_READ_FAILED("Source file read failed"),
SOURCE_DECODE_FAILED("Source file decode failed"),
REMEDIATION_DATA_INVALID("Remediation data invalid"),
REMEDIATION_LINE_RANGE_INVALID("Remediation line range invalid"),
SOURCE_CONTEXT_NOT_FOUND("Source context not found"),
SOURCE_CONTEXT_AMBIGUOUS("Source context matched multiple locations"),
ORIGINAL_CODE_NOT_FOUND("Original code not found"),
ORIGINAL_CODE_AMBIGUOUS("Original code matched multiple locations"),
SUPERSEDED_BY_BROADER_FIX("Superseded by broader fix"),
CONFLICTS_WITH_ANOTHER_FIX("Conflicts with another fix"),
ANCHOR_DOES_NOT_MATCH("Anchor does not match"),
REMEDIATION_ENCODE_FAILED("Remediation encode failed"),
SOURCE_WRITE_FAILED("Source file write failed"),
NO_CHANGES("No file changes found"),
UNEXPECTED_ERROR("Unexpected remediation processing error");

final String displayName;

SkipReason(String displayName) {
this.displayName = displayName;
}

final String displayName() {
return displayName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2021-2026 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*/
package com.fortify.cli.aviator.fpr.remediation.applier;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import com.fortify.cli.aviator.fpr.remediation.SkipReason;
import com.fortify.cli.aviator.fpr.remediation.exception.SkipRemediationException;
import com.fortify.cli.aviator.util.FuzzyContextSearcher;

/** Wraps the {@link FuzzyContextSearcher} utility's context/original-code matching, unmodified from the original. */
public final class FuzzyAnchorLocator {

public int searchContext(String instanceId, String filename, List<String> originalLines, List<String> contextLine,
int projectedDeclaredFrom, int contextBefore) {
try {
List<Integer> matches = FuzzyContextSearcher.fuzzySearchContextMatches(originalLines, contextLine, 0);
if (matches.size() > 1) {
int expectedContextLineFrom = projectedDeclaredFrom - 1 - contextBefore;
List<Integer> exact = matches.stream().filter(m -> m == expectedContextLineFrom).toList();
if (exact.size() == 1) {
return exact.get(0);
}
String candidateLines = matches.stream()
.map(line -> String.valueOf(line + 1))
.collect(Collectors.joining(", "));
throw new SkipRemediationException(SkipReason.SOURCE_CONTEXT_AMBIGUOUS,
"Source context matched multiple locations in file '" + filename + "'; candidate lines: " + candidateLines);
}
return matches.isEmpty() ? -1 : matches.get(0);
} catch (IOException e) {
throw new SkipRemediationException(SkipReason.SOURCE_CONTEXT_NOT_FOUND,
"Error searching source context for remediation '" + instanceId + "' in file '" + filename + "'", e);
}
}

public int[] searchOriginalCode(String instanceId, String filename, List<String> originalLines, List<String> originalCodeLine,
int contextLineFrom, int contextLineCount, int contextBefore, int contextAfter,
int projectedDeclaredFrom, int projectedDeclaredTo) {
int contextStart = contextLineFrom + contextBefore;
int contextEnd = contextLineFrom + contextLineCount - contextAfter;
if (contextStart < 0 || contextStart >= contextEnd || contextEnd > originalLines.size()) {
return new int[] {-1, -1};
}

List<int[]> matches = FuzzyContextSearcher.fuzzySearchOriginalCodeMatches(
originalLines.subList(contextStart, contextEnd), originalCodeLine, 0, 0);
if (matches.size() > 1) {
int expectedFrom = projectedDeclaredFrom - 1 - contextStart;
int expectedTo = projectedDeclaredTo - 1 - contextStart;
List<int[]> exact = matches.stream().filter(m -> m[0] == expectedFrom && m[1] == expectedTo).toList();
if (exact.size() == 1) {
int[] m = exact.get(0);
return new int[] {m[0] + contextStart, m[1] + contextStart};
}
String candidateLines = matches.stream()
.map(m -> String.valueOf(m[0] + contextStart + 1))
.collect(Collectors.joining(", "));
throw new SkipRemediationException(SkipReason.ORIGINAL_CODE_AMBIGUOUS,
"Original code matched multiple locations in file '" + filename + "'; candidate lines: " + candidateLines);
}
if (matches.isEmpty()) {
return new int[] {-1, -1};
}
int[] lineFromTo = matches.get(0);
return new int[] {lineFromTo[0] + contextStart, lineFromTo[1] + contextStart};
}
}
Loading
Loading