8373448: jpackage: StackOverflowError when processing a very long argument

Reviewed-by: almatvee
Backport-of: 8737a8ca73952d60129e7fc2f7e17eea3b800af7
This commit is contained in:
Alexey Semenyuk 2026-01-14 22:44:40 +00:00
parent d011d7c7cc
commit 9f78c71f88
2 changed files with 37 additions and 6 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -727,8 +727,15 @@ public final class StandardOption {
//
// regexp for parsing args (for example, for additional launchers)
private static Pattern pattern = Pattern.compile(
"(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
private static Pattern PATTERN = Pattern.compile(String.format(
"(?:(?:%s|%s)|(?:\\\\[\"'\\s]|\\S))++",
createPatternComponent('\''),
createPatternComponent('\"')));
private static String createPatternComponent(char quoteChar) {
var str = Character.toString(quoteChar);
return String.format("(?:%s(?:\\\\%s|[^%s])*+(?:%s|$))", str, str, str, str);
}
static List<String> getArgumentList(String inputString) {
Objects.requireNonNull(inputString);
@ -741,7 +748,7 @@ public final class StandardOption {
// The "pattern" regexp attempts to abide to the rule that
// strings are delimited by whitespace unless surrounded by
// quotes, then it is anything (including spaces) in the quotes.
Matcher m = pattern.matcher(inputString);
Matcher m = PATTERN.matcher(inputString);
while (m.find()) {
String s = inputString.substring(m.start(), m.end()).trim();
// Ensure we do not have an empty string. trim() will take care of

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -341,9 +341,33 @@ public class StandardOptionTest extends JUnitAdapter.TestSrcInitializer {
Arguments.of("abc", List.of("abc")),
Arguments.of("a b c", List.of("a", "b", "c")),
Arguments.of("a=10 -Dorg.acme.name='John Smith' c=\\\"foo\\\"", List.of("a=10", "-Dorg.acme.name=John Smith", "c=\"foo\"")),
Arguments.of(" foo \"a b c\" v=' John Smith ' 'H e ll o' ", List.of("foo", "a b c", "v= John Smith ", "H e ll o")),
Arguments.of("\"\"", List.of("")),
Arguments.of(" ", List.of()),
Arguments.of("", List.of())
Arguments.of(" ", List.of()),
Arguments.of(" foo ", List.of("foo")),
Arguments.of("", List.of()),
Arguments.of("'fo\"o'\\ buzz \"b a r\"", List.of("fo\"o\\ buzz", "b a r")),
Arguments.of("a\\ 'b\"c'\\ d", List.of("a\\ b\"c\\ d")),
Arguments.of("\"a 'bc' d\"", List.of("a 'bc' d")),
Arguments.of("\'a 'bc' d\'", List.of("a bc d")),
Arguments.of("\"a \\'bc\\' d\"", List.of("a 'bc' d")),
Arguments.of("\'a \\'bc\\' d\'", List.of("a 'bc' d")),
Arguments.of("'a b c' 'd e f'", List.of("a b c", "d e f")),
Arguments.of("'a b c' \"'d e f' h", List.of("a b c", "'d e f' h")),
Arguments.of("'a b c' \"'d e f' \t ", List.of("a b c", "'d e f'")),
Arguments.of(" a='' '' \t '\\'\\'' \"\" \"\\\"\\\"\" ", List.of("a=", "", "\'\'", "", "\"\"")),
Arguments.of("' \'foo '", List.of(" foo", "")),
Arguments.of("' \'foo ' bar", List.of(" foo", " bar")),
Arguments.of("' \'foo\\ '", List.of(" foo\\ ")),
Arguments.of("'fo\"o buzz \"b a r\"", List.of("fo\"o buzz \"b a r\"")),
Arguments.of("'", List.of("")),
Arguments.of("' f g ", List.of(" f g")),
Arguments.of("' f g", List.of(" f g")),
Arguments.of("'\\'", List.of("'")),
Arguments.of("'\\' ", List.of("'")),
Arguments.of("'\\' a ", List.of("' a")),
Arguments.of("\"" + "\\\"".repeat(10000) + "A", List.of("\"".repeat(10000) + "A"))
);
}