This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git


The following commit(s) were added to refs/heads/develop by this push:
     new 255bb4d04 formatter: fix stack overflow on some platforms when MXML 
Script text is beyond a certain length
255bb4d04 is described below

commit 255bb4d040755184be0dfb176ac5608061bd1305
Author: Josh Tynjala <[email protected]>
AuthorDate: Fri Aug 11 10:45:13 2023 -0700

    formatter: fix stack overflow on some platforms when MXML Script text is 
beyond a certain length
    
    Java's regular expressions don't seem to like lazy quantifiers, on Windows 
especially
---
 .../royale/formatter/MXMLTokenFormatter.java       | 26 +++++++----
 .../apache/royale/formatter/TestMXMLMetadata.java  | 48 +++++++++++++++++++++
 .../apache/royale/formatter/TestMXMLScript.java    | 50 ++++++++++++++++++++++
 3 files changed, 115 insertions(+), 9 deletions(-)

diff --git 
a/formatter/src/main/java/org/apache/royale/formatter/MXMLTokenFormatter.java 
b/formatter/src/main/java/org/apache/royale/formatter/MXMLTokenFormatter.java
index a0b5dccd6..f514eaa99 100644
--- 
a/formatter/src/main/java/org/apache/royale/formatter/MXMLTokenFormatter.java
+++ 
b/formatter/src/main/java/org/apache/royale/formatter/MXMLTokenFormatter.java
@@ -38,6 +38,8 @@ import 
org.apache.royale.formatter.internal.BaseTokenFormatter;
 public class MXMLTokenFormatter extends BaseTokenFormatter {
        private static final int TOKEN_TYPE_EXTRA = 999999;
        private static final Pattern SCRIPT_START_PATTERN = 
Pattern.compile("<((?:mx|fx):(Script|Metadata))");
+       private static final Pattern TAG_START_WITH_OPTIONAL_CDATA_PATTERN = 
Pattern.compile("^<((?:mx|fx):(\\w+))>\\s*(<!\\[CDATA\\[)?");
+       private static final Pattern TAG_END_WITH_OPTIONAL_CDATA_PATTERN = 
Pattern.compile("(?:\\]\\]>)?\\s*<\\/(?:mx|fx):(?:\\w+)>$");
        private static final String FORMATTER_TAG_OFF = "@formatter:off";
        private static final String FORMATTER_TAG_ON = "@formatter:on";
 
@@ -338,22 +340,28 @@ public class MXMLTokenFormatter extends 
BaseTokenFormatter {
                        }
                }
                StringBuilder builder = new StringBuilder();
-               Pattern scriptPattern = Pattern.compile(
-                               
"^<((?:mx|fx):(\\w+))>\\s*(<!\\[CDATA\\[)?((?:.|(?:\\r?\\n))*?)(?:\\]\\]>)?\\s*<\\/(?:mx|fx):(?:\\w+)>$");
-               Matcher scriptMatcher = scriptPattern.matcher(text);
-               if (!scriptMatcher.matches()) {
+               Matcher scriptStartMatcher = 
TAG_START_WITH_OPTIONAL_CDATA_PATTERN.matcher(text);
+               if (!scriptStartMatcher.find() || scriptStartMatcher.end() > 
text.length()) {
                        return text;
                }
+
+               int startEndSearch = scriptStartMatcher.end();
+               Matcher scriptEndMatcher = 
TAG_END_WITH_OPTIONAL_CDATA_PATTERN.matcher(text.substring(startEndSearch));
+               if (!scriptEndMatcher.find()) {
+                       return text;
+               }
+
+               String scriptTagText = scriptStartMatcher.group(1);
+               String scriptTagName = scriptStartMatcher.group(2);
+               String cdataText = scriptStartMatcher.group(3);
+               String scriptText = text.substring(startEndSearch, 
startEndSearch + scriptEndMatcher.start());
+               boolean requireCdata = cdataText != null || 
"Script".equals(scriptTagName);
+
                if (problems == null) {
                        // we need to know if there were problems because it 
means that we
                        // need to return the original, unformatted text
                        problems = new ArrayList<ICompilerProblem>();
                }
-               String scriptTagText = scriptMatcher.group(1);
-               String scriptTagName = scriptMatcher.group(2);
-               String cdataText = scriptMatcher.group(3);
-               String scriptText = scriptMatcher.group(4);
-               boolean requireCdata = cdataText != null || 
"Script".equals(scriptTagName);
                ASTokenFormatter asFormatter = new ASTokenFormatter(settings);
                String formattedScriptText = asFormatter.format(filePath + 
"@Script[" + line + "]", scriptText, problems);
                if (!settings.ignoreProblems && hasErrors(problems)) {
diff --git 
a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLMetadata.java 
b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLMetadata.java
index c9264ca07..57c36cf62 100644
--- a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLMetadata.java
+++ b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLMetadata.java
@@ -48,6 +48,29 @@ public class TestMXMLMetadata extends BaseFormatterTests {
                                result);
        }
 
+       @Test
+       public void testEmptyMetadataNoCdataNoWhitespace() {
+               FormatterSettings settings = new FormatterSettings();
+               settings.insertSpaces = false;
+               MXMLTokenFormatter formatter = new MXMLTokenFormatter(settings);
+               String result = formatter.format("file.mxml",
+               // @formatter:off
+                       "<s:Application>\n" +
+                       "<fx:Metadata></fx:Metadata>\n" +
+                       "</s:Application>",
+                       // @formatter:on
+                       problems
+               );
+               assertEquals(
+               // @formatter:off
+                               "<s:Application>\n" +
+                               "\t<fx:Metadata>\n" +
+                               "\t</fx:Metadata>\n" +
+                               "</s:Application>",
+                               // @formatter:on
+                               result);
+       }
+
        @Test
        public void testEmptyMetadataWithCdata() {
                FormatterSettings settings = new FormatterSettings();
@@ -76,6 +99,31 @@ public class TestMXMLMetadata extends BaseFormatterTests {
                                result);
        }
 
+       @Test
+       public void testEmptyMetadataWithCdataNoWhitespace() {
+               FormatterSettings settings = new FormatterSettings();
+               settings.insertSpaces = false;
+               MXMLTokenFormatter formatter = new MXMLTokenFormatter(settings);
+               String result = formatter.format("file.mxml",
+               // @formatter:off
+                       "<s:Application>\n" +
+                       "<fx:Metadata><![CDATA[]]></fx:Metadata>\n" +
+                       "</s:Application>",
+                       // @formatter:on
+                       problems
+               );
+               assertEquals(
+               // @formatter:off
+                               "<s:Application>\n" +
+                               "\t<fx:Metadata>\n" +
+                               "\t\t<![CDATA[\n" +
+                               "\t\t]]>\n" +
+                               "\t</fx:Metadata>\n" +
+                               "</s:Application>",
+                               // @formatter:on
+                               result);
+       }
+
        @Test
        public void testSingleMetadata() {
                FormatterSettings settings = new FormatterSettings();
diff --git 
a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLScript.java 
b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLScript.java
index e40e2f62c..f5c6783e1 100644
--- a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLScript.java
+++ b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLScript.java
@@ -50,6 +50,31 @@ public class TestMXMLScript extends BaseFormatterTests {
                                result);
        }
 
+       @Test
+       public void testEmptyScriptNoCdataNoWhitespace() {
+               FormatterSettings settings = new FormatterSettings();
+               settings.insertSpaces = false;
+               MXMLTokenFormatter formatter = new MXMLTokenFormatter(settings);
+               String result = formatter.format("file.mxml",
+               // @formatter:off
+                       "<s:Application>\n" +
+                       "<fx:Script></fx:Script>\n" +
+                       "</s:Application>",
+                       // @formatter:on
+                       problems
+               );
+               assertEquals(
+               // @formatter:off
+                               "<s:Application>\n" +
+                               "\t<fx:Script>\n" +
+                               "\t\t<![CDATA[\n" +
+                               "\t\t]]>\n" +
+                               "\t</fx:Script>\n" +
+                               "</s:Application>",
+                               // @formatter:on
+                               result);
+       }
+
        @Test
        public void testEmptyScriptWithCdata() {
                FormatterSettings settings = new FormatterSettings();
@@ -78,6 +103,31 @@ public class TestMXMLScript extends BaseFormatterTests {
                                result);
        }
 
+       @Test
+       public void testEmptyScriptWithCdataNoWhitespace() {
+               FormatterSettings settings = new FormatterSettings();
+               settings.insertSpaces = false;
+               MXMLTokenFormatter formatter = new MXMLTokenFormatter(settings);
+               String result = formatter.format("file.mxml",
+               // @formatter:off
+                       "<s:Application>\n" +
+                       "<fx:Script><![CDATA[]]></fx:Script>\n" +
+                       "</s:Application>",
+                       // @formatter:on
+                       problems
+               );
+               assertEquals(
+               // @formatter:off
+                               "<s:Application>\n" +
+                               "\t<fx:Script>\n" +
+                               "\t\t<![CDATA[\n" +
+                               "\t\t]]>\n" +
+                               "\t</fx:Script>\n" +
+                               "</s:Application>",
+                               // @formatter:on
+                               result);
+       }
+
        @Test
        public void testScriptWithActionScript() {
                FormatterSettings settings = new FormatterSettings();

Reply via email to