Skip to content

8339460: CDS error when module is located in a directory with space in the name #20987

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

mkartashev
Copy link
Member

@mkartashev mkartashev commented Sep 13, 2024

The crux of the problem is that path names in CDS are saved as URIs and subsequently "converted" back to path names simply by stripping off the prefix without appropriate conversion of the rest of the name. This commit adds such a conversion.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8339460: CDS error when module is located in a directory with space in the name (Bug - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/20987/head:pull/20987
$ git checkout pull/20987

Update a local copy of the PR:
$ git checkout pull/20987
$ git pull https://git.openjdk.org/jdk.git pull/20987/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 20987

View PR using the GUI difftool:
$ git pr show -t 20987

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/20987.diff

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Sep 13, 2024

👋 Welcome back mkartashev! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Sep 13, 2024

@mkartashev This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8339460: CDS error when module is located in a directory with space in the name

Reviewed-by: ccheung, iklam

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 265 new commits pushed to the master branch:

  • 8c8f0d8: 8339260: Move rarely used constants out of ClassFile
  • 47c1069: 8340812: LambdaForm customization via MethodHandle::updateForm is not thread safe
  • 66f1639: 8339271: giflib attribution correction
  • 8f75619: 8340864: Remove unused lines related to vmClasses
  • 84751cb: 8340831: Simplify simple validation for class definition in MethodHandles.Lookup
  • df1959f: 8340838: Clean up MutableCallSite to use explicit release fence instead of AtomicInteger
  • 1b2d40a: 8340956: ProblemList 4 java/nio/channels/DatagramChannel tests on macosx-all
  • f7bc9ba: 8340228: Open source couple more miscellaneous AWT tests
  • 0e0b0b0: 8340684: Reading from an input stream backed by a closed ZipFile has no test coverage
  • 81b5f09: 8340946: Add vmTestbase/gc/memory/Nio/Nio.java and java/nio/Buffer/LimitDirectMemory.java to problem list
  • ... and 255 more: https://git.openjdk.org/jdk/compare/a35fd3861044bdb8ddae378cb666b3d2e549a8c8...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@calvinccheung, @iklam) but any other Committer may sponsor as well.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk openjdk bot added the rfr Pull request is ready for review label Sep 13, 2024
@openjdk
Copy link

openjdk bot commented Sep 13, 2024

@mkartashev The following label will be automatically applied to this pull request:

  • hotspot-runtime

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the hotspot-runtime hotspot-runtime-dev@openjdk.org label Sep 13, 2024
@mlbridge
Copy link

mlbridge bot commented Sep 13, 2024

Webrevs

@dfuch
Copy link
Member

dfuch commented Sep 13, 2024

Hi, could you point at the place where the URI is written? Do we know what code produced the URI?

@mkartashev
Copy link
Member Author

The URI is coming from the Java side. When a module is defined, its location is kept as a URI. See Modules.java:

Module defineModule(ClassLoader loader, ModuleDescriptor descriptor, URI uri);

Later on, the URI is converted into a path name, see ClassLoaderExt::process_module_table():

        path = ClassLoader::skip_uri_protocol(path);
        char* path_copy = NEW_RESOURCE_ARRAY(char, strlen(path) + 1);
        strcpy(path_copy, path);
        _module_paths->append(path_copy);

That path name, untouched, is passed to os::stat() to verify the file; see ClassLoader::setup_module_search_path():

  if (os::stat(path, &st) != 0) {
    tty->print_cr("os::stat error %d (%s). CDS dump aborted (path was \"%s\").",
      errno, os::errno_name(errno), path);
    vm_exit_during_initialization();
  }

At this point, if the original URI had any escaped characters, os::stat() would fail terminating the entire JVM.
There are other code paths that also had to be fixed.

Copy link
Member

@calvinccheung calvinccheung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this bug. I've re-assigned the bug to you. Couple of comments below.

Comment on lines 1234 to 1236
if (str[index] == '%'
&& isxdigit(str[index + 1])
&& isxdigit(str[index + 2])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to bound check the index because the uri from ClassLoaderExt::process_module_table could just be a directory name, e.g. dir%, without the jar file name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

str is still zero-terminated, so if str[index] == '%' is true, then str[index + 1] at least exists and might be 0. If isxdigit(str[index + 1]) is true then str[index + 2] at least exists and might be 0, in which case isxdigit() is going to be false for it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if isxdigit(str[index + 1]) is false, it won't proceed to check isxdigit(str[index + 2])?
The bound check I'm thinking about is like the following:

if (index >= strlen(str) - 2) {
  return str[index];
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if isxdigit(str[index + 1]) is false, it won't proceed to check isxdigit(str[index + 2])? The bound check I'm thinking about is like the following:

That is exactly correct.

The bound check I'm thinking about is like the following:

if (index >= strlen(str) - 2) {
  return str[index];
}

This seems unnecessary as we already assume that the string is null-terminated in the caller, and, as I have demonstrated out earlier, null-terminated strings are quite safe to check character-by-character.


public class ComplexURITest {
final static String listFileName = "test-classlist.txt";
final static String archiveName = "test-dynamic.jsa";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using the same archiveName for both static and dynamic test cases. I'd suggest declare a different archive name for the static case. E.g.

final static String staticArchiveName = "test-static.jsa";
final static String dynamicArchiveName = "test-dynamic.jsa";

Also, I think this test should be excluded from the hotspot_appcds_dynamic test group in the open/test/hotspot/jtreg/TEST.groups file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I also added the code to safeguard against IOException on Windows in the case of deleting the read-only archive created previously.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test changes look good. I will run some testing on your patch.

Copy link
Member

@iklam iklam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Some small nits.

Comment on lines 1268 to 1272
#ifdef _WINDOWS
if (decoded == '/') {
decoded = '\\';
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary for this patch? If not, I think we should not include it, since it changes behavior (i.e., strcmp() on the path may start failing).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary for this patch?

I suppose, not. Let me check that the test still passes on Windows, though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me check that the test still passes on Windows, though.

The test does pass on Windows with all the recent changes.


#ifdef _WINDOWS
if (uri[0] == '/') {
// Absolute path name on Windows does not begin with a slash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use 2-space indents.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly. Done.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Sep 25, 2024
@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Sep 25, 2024
Copy link
Member

@calvinccheung calvinccheung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran tiers 1 - 4 testing prior to this latest change and saw no new failures.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Sep 25, 2024
@mkartashev
Copy link
Member Author

/integrate

@openjdk openjdk bot added the sponsor Pull request is ready to be sponsored label Sep 26, 2024
@openjdk
Copy link

openjdk bot commented Sep 26, 2024

@mkartashev
Your change (at version 5fcaf02) is now ready to be sponsored by a Committer.

@calvinccheung
Copy link
Member

/sponsor

@openjdk
Copy link

openjdk bot commented Sep 26, 2024

Going to push as commit aceae76.
Since your change was applied there have been 274 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Sep 26, 2024
@openjdk openjdk bot closed this Sep 26, 2024
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review sponsor Pull request is ready to be sponsored labels Sep 26, 2024
@openjdk
Copy link

openjdk bot commented Sep 26, 2024

@calvinccheung @mkartashev Pushed as commit aceae76.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot-runtime hotspot-runtime-dev@openjdk.org integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

4 participants