8259637: java.io.File.getCanonicalPath() returns different values for same path

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2023-12-18 18:10:34 +00:00
parent 4f3de09672
commit b98d13fc3c
2 changed files with 36 additions and 7 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -157,7 +157,13 @@ collapse(char *path)
for (j = i - 1; j >= 0; j--) { for (j = i - 1; j >= 0; j--) {
if (ix[j]) break; if (ix[j]) break;
} }
if (j < 0) continue; if (j < 0) {
// If there is no preceding name and this path is absolute,
// then remove this instance of ".."
if (path[0] == '/')
ix[i] = 0;
continue;
}
ix[j] = 0; ix[j] = 0;
ix[i] = 0; ix[i] = 0;
} }

View file

@ -23,7 +23,6 @@
/* @test /* @test
* @bug 4899022 * @bug 4899022
* @requires (os.family == "windows")
* @summary Look for erroneous representation of drive letter * @summary Look for erroneous representation of drive letter
* @run junit GetCanonicalPath * @run junit GetCanonicalPath
*/ */
@ -35,6 +34,8 @@ import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
@ -43,7 +44,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
public class GetCanonicalPath { public class GetCanonicalPath {
private static Stream<Arguments> pathProvider() { private static Stream<Arguments> pathProviderWindows() {
List<Arguments> list = new ArrayList<Arguments>(); List<Arguments> list = new ArrayList<Arguments>();
File dir = new File(System.getProperty("user.dir", ".")); File dir = new File(System.getProperty("user.dir", "."));
@ -80,21 +81,43 @@ public class GetCanonicalPath {
return list.stream(); return list.stream();
} }
private static Stream<Arguments> pathProviderUnix() {
return Stream.of(
Arguments.of("/../../../../../a/b/c", "/a/b/c"),
Arguments.of("/../../../../../a/../b/c", "/b/c"),
Arguments.of("/../../../../../a/../../b/c", "/b/c"),
Arguments.of("/../../../../../a/../../../b/c", "/b/c"),
Arguments.of("/../../../../../a/../../../../b/c", "/b/c")
);
}
@ParameterizedTest @ParameterizedTest
@EnabledOnOs({OS.AIX, OS.LINUX, OS.MAC})
@MethodSource("pathProviderUnix")
void goodPathsUnix(String pathname, String expected) throws IOException {
File file = new File(pathname);
String canonicalPath = file.getCanonicalPath();
assertEquals(expected, canonicalPath);
}
@ParameterizedTest
@EnabledOnOs(OS.WINDOWS)
@ValueSource(strings = {"\\\\?", "\\\\?\\UNC", "\\\\?\\UNC\\"}) @ValueSource(strings = {"\\\\?", "\\\\?\\UNC", "\\\\?\\UNC\\"})
void badPaths(String pathname) { void badPathsWindows(String pathname) {
assertThrows(IOException.class, () -> new File(pathname).getCanonicalPath()); assertThrows(IOException.class, () -> new File(pathname).getCanonicalPath());
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("pathProvider") @EnabledOnOs(OS.WINDOWS)
void goodPaths(String pathname, String expected) throws IOException { @MethodSource("pathProviderWindows")
void goodPathsWindows(String pathname, String expected) throws IOException {
File file = new File(pathname); File file = new File(pathname);
String canonicalPath = file.getCanonicalPath(); String canonicalPath = file.getCanonicalPath();
assertEquals(expected, canonicalPath); assertEquals(expected, canonicalPath);
} }
@Test @Test
@EnabledOnOs(OS.WINDOWS)
void driveLetter() throws IOException { void driveLetter() throws IOException {
String path = new File("c:/").getCanonicalPath(); String path = new File("c:/").getCanonicalPath();
assertFalse(path.length() > 3, "Drive letter incorrectly represented"); assertFalse(path.length() > 3, "Drive letter incorrectly represented");