Skip to content

Commit 862df1e

Browse files
authored
Merge pull request #2747 from guwirth/fix-2741
Improve handling of relative file paths in report files
2 parents 48e17ab + 7bd54f1 commit 862df1e

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

cxx-squid/src/main/java/org/sonar/cxx/utils/CxxReportLocation.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.util.Objects;
2323
import javax.annotation.Nullable;
24+
import org.apache.commons.io.FilenameUtils;
2425
import org.sonar.api.utils.PathUtils;
2526

2627
/**
@@ -35,8 +36,22 @@ public class CxxReportLocation {
3536

3637
public CxxReportLocation(@Nullable String file, @Nullable String line, @Nullable String column, String info) {
3738
super();
38-
// normalize file, removing double and single dot path steps => avoids duplicates
39-
this.file = PathUtils.sanitize(file);
39+
40+
// Normalize file using separators in UNIX format, removing double and single dot path steps. This is to avoid
41+
// duplicates in the issue containers because they are using the file as key. PathUtils.sanitize uses
42+
// FilenameUtils.normalize internally, relative paths starting with a double dot will cause that path segment
43+
// and the one before to be removed. If the double dot has no parent path segment to work with, null is returned.
44+
// null would mean 'project issue' which is wrong in this context. To avoid this we extract the filename to
45+
// generate at least a meningful error message (#2747).
46+
var normalized = PathUtils.sanitize(file);
47+
if (normalized == null && (file != null && !file.isBlank())) {
48+
49+
// use FilenameUtils.getName because this works on Windows and Linux also if
50+
// report is generated on the one and consumed on the other
51+
normalized = FilenameUtils.getName(file);
52+
}
53+
54+
this.file = normalized;
4055
this.line = line;
4156
this.column = column;
4257
this.info = info;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* C++ Community Plugin (cxx plugin)
3+
* Copyright (C) 2010-2023 SonarOpenCommunity
4+
* http://github.com/SonarOpenCommunity/sonar-cxx
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.cxx.utils;
21+
22+
import static org.assertj.core.api.Assertions.*;
23+
import org.junit.jupiter.api.Test;
24+
25+
public class CxxReportLocationTest {
26+
27+
@Test
28+
void testConstructor() {
29+
var loc0 = new CxxReportLocation(null, null, null, "info");
30+
assertThat(loc0.getFile()).isNull();
31+
assertThat(loc0.getLine()).isNull();
32+
assertThat(loc0.getColumn()).isNull();
33+
assertThat(loc0.getInfo()).isEqualTo("info");
34+
assertThat(loc0.toString()).isEqualTo("CxxReportLocation [file=null, line=null, column=null, info=info]");
35+
36+
var loc1 = new CxxReportLocation("file", "line", "column", "info");
37+
assertThat(loc1.getFile()).isEqualTo("file");
38+
assertThat(loc1.getLine()).isEqualTo("line");
39+
assertThat(loc1.getColumn()).isEqualTo("column");
40+
assertThat(loc1.getInfo()).isEqualTo("info");
41+
assertThat(loc1.toString()).isEqualTo("CxxReportLocation [file=file, line=line, column=column, info=info]");
42+
}
43+
44+
@Test
45+
void testPathSanitize() {
46+
var loc = new CxxReportLocation("file", null, null, "");
47+
48+
loc = new CxxReportLocation("/dir/File", null, null, "");
49+
assertThat(loc.getFile()).isEqualTo("/dir/File");
50+
loc = new CxxReportLocation("/dir/./File", null, null, "");
51+
assertThat(loc.getFile()).isEqualTo("/dir/File");
52+
loc = new CxxReportLocation("/dir/../File", null, null, "");
53+
assertThat(loc.getFile()).isEqualTo("/File");
54+
loc = new CxxReportLocation("dir/File", null, null, "");
55+
assertThat(loc.getFile()).isEqualTo("dir/File");
56+
loc = new CxxReportLocation("./dir/File", null, null, "");
57+
assertThat(loc.getFile()).isEqualTo("dir/File");
58+
loc = new CxxReportLocation("../dir/File", null, null, "");
59+
assertThat(loc.getFile()).isEqualTo("File");
60+
loc = new CxxReportLocation("../../File", null, null, "");
61+
assertThat(loc.getFile()).isEqualTo("File");
62+
63+
loc = new CxxReportLocation("c:\\dir\\file.ext", null, null, "");
64+
assertThat(loc.getFile()).isEqualTo("c:/dir/file.ext");
65+
loc = new CxxReportLocation("C:\\dir\\.\\file.ext", null, null, "");
66+
assertThat(loc.getFile()).isEqualTo("C:/dir/file.ext");
67+
loc = new CxxReportLocation("c:\\dir\\..\\file.ext", null, null, "");
68+
assertThat(loc.getFile()).isEqualTo("c:/file.ext");
69+
loc = new CxxReportLocation("dir\\file.ext", null, null, "");
70+
assertThat(loc.getFile()).isEqualTo("dir/file.ext");
71+
loc = new CxxReportLocation(".\\dir\\file.ext", null, null, "");
72+
assertThat(loc.getFile()).isEqualTo("dir/file.ext");
73+
loc = new CxxReportLocation("..\\dir\\file.ext", null, null, "");
74+
assertThat(loc.getFile()).isEqualTo("file.ext");
75+
loc = new CxxReportLocation("..\\..\\file.ext", null, null, "");
76+
assertThat(loc.getFile()).isEqualTo("file.ext");
77+
}
78+
}

0 commit comments

Comments
 (0)