镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

UTF Characters for relative path #27534

Description

@JSMonk

Version: 10.15.3
Platform: Windows 64bit
Subsystem: "path" module

const path = require("path");

const rootPath = "İ"; // Turkish character, char code 304
const absolute = "c:\\Users\\root\\Documents\\İ\\test.txt";

const relative = path.relative(rootPath, absolute); // est.txt

Expected result: test.txt
Actual result: est.txt

Activity

  1. changed the title [-]UTF Character for relative path[/-] [+]UTF Characters for relative path[/+] on May 2, 2019
  2. targos commented on May 3, 2019

    @targos
    Member

    The problem here is that path.relative computes everything using the lowercase versions of the paths but returns the result using the original case.
    "İ" has one char code while "İ".toLowerCase() has two.

    There's an easy fix for this case:

    console.log(path.win32.relative('c:\\a\\İ', 'c:\\a\\İ\\test.txt'));
    // est.txt
    diff --git a/lib/path.js b/lib/path.js
    index 2301a6ebb8..e76513f0f3 100644
    --- a/lib/path.js
    +++ b/lib/path.js
    @@ -499,7 +499,7 @@ const win32 = {
             if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {
               // We get here if `from` is the exact base path for `to`.
               // For example: from='C:\\foo\\bar'; to='C:\\foo\\bar\\baz'
    -          return toOrig.slice(toStart + i + 1);
    +          return toOrig.slice(toStart + i + 1 - from.length + fromOrig.length);
             }
             if (i === 2) {
               // We get here if `from` is the device root.
    console.log(path.win32.relative('c:\\a\\İ', 'c:\\a\\İ\\test.txt'));
    // test.txt

    However this case is trickier:

    console.log(path.win32.relative('c:\\İ\\a\\İ', 'c:\\İ\\b\\İ\\test.txt'));
    // ..\..b\İ\test.txt
  3. added
    confirmed-bugIssues and PRs for confirmed bugs.
    pathIssues and PRs related to the path subsystem.
    windowsIssues and PRs related to the Windows platform.
    on May 3, 2019
  4. targos commented on May 3, 2019

    @targos
    Member
  5. BridgeAR commented on May 3, 2019

    @BridgeAR
    Member

    This should be easy to fix: instead of using the lower cased variation it's possible to use the upper case one. These two ways do not work identical and the upper case variation does not show the negative sides as the lower case. I am compiling right now to see if that works as expected.

  6. BridgeAR commented on May 3, 2019

    @BridgeAR
    Member
    > console.log(path.win32.relative('c:\\a\\İ', 'c:\\a\\İ\\test.txt'));
    test.txt
    > console.log(path.win32.relative('c:\\İ\\a\\İ', 'c:\\İ\\b\\İ\\test.txt'));
    ..\..\b\İ\test.txt
    
  7. targos commented on May 3, 2019

    @targos
    Member

    @BridgeAR what about: console.log(path.win32.relative('c:\\İ\\a\\İ'.toLowerCase(), 'c:\\İ\\b\\İ\\test.txt'.toLowerCase())); ?

  8. targos commented on May 3, 2019

    @targos
    Member

    Sorry ^. That's not the example I meant. Isn't there the same risk with toUpperCase but with other characters?

  9. targos commented on May 3, 2019

    @targos
    Member

    @BridgeAR Make sure this case works as well: console.log(path.win32.relative('c:\\ß\\a\\ß', 'c:\\ß\\b\\ß\\test.txt'));

  10. BridgeAR commented on May 3, 2019

    @BridgeAR
    Member

    @targos ß is converted to SS when using toUpperCase, so it has a similar problem like the initial issue. Unicode is pretty ugly and we have problems with Turkish, German and likely more. There is the toLocaleLowerCase() function and it should work for all cases.

    @mathiasbynens PTAL.

  11. targos commented on May 3, 2019

    @targos
    Member

    I'm afraid the behavior of toLocaleLowerCase() depends on the user's locale.

  12. BridgeAR commented on May 3, 2019

    @BridgeAR
    Member

    @targos yes, that's correct. As far as I know a device name may also contain unicode characters and if that's the case also path.win32.resolve() would fail (and likely more).

    I have to think about this a bit closer when I find to do so. We probably also have issues even without changing the casing since we expect characters to always have a length of 1. This is mostly not an issue, since we almost always just check for slashes and take everything in-between but we expect the device root to always be of length 2.

  13. sr258 commented on Aug 18, 2021

    @sr258

    This is still an issue that can lead to bugs in August 2021. Any news?

  14. added a commit that references this issue on Aug 6, 2024
  15. added a commit that references this issue on Aug 14, 2024
  16. added a commit that references this issue on Sep 21, 2024
  17. added a commit that references this issue on Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.pathIssues and PRs related to the path subsystem.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions