Try to reduce the risk of StackOverflow/OOM in report
Submitted by: Ryan Bennitt
Bugzilla: https://issues.apache.org/bugzilla/show_bug.cgi?id=57341
diff --git a/changes.xml b/changes.xml
index c665f93..4e43174 100644
--- a/changes.xml
+++ b/changes.xml
@@ -37,6 +37,14 @@
     <title>Apache AntUnit</title>
   </properties>
 
+  <release version="1.4" date="unreleased">
+    <action type="fix" issue="57341">
+      The br-replace template inside the XSLT stylesheets used by
+      for reports could cause stack overflows or out-of-memory errors
+      when applied to big outputs.
+    </action>
+  </release>
+
   <release version="1.3" date="2014-05-14">
     <action type="add" issue="53383">
       New assertion assertRefResourceExists,
diff --git a/contributors.xml b/contributors.xml
index b4a4966..00db496 100644
--- a/contributors.xml
+++ b/contributors.xml
@@ -63,6 +63,10 @@
     <last>Reilly</last>
   </name>
   <name>
+    <first>Ryan</first>
+    <last>Bennitt</last>
+  </name>
+  <name>
     <first>Stefan</first>
     <last>Bodewig</last>
   </name>
diff --git a/src/etc/junit-frames.xsl b/src/etc/junit-frames.xsl
index 7c5eb72..8a746e2 100644
--- a/src/etc/junit-frames.xsl
+++ b/src/etc/junit-frames.xsl
@@ -888,7 +888,24 @@
 -->
 <xsl:template name="br-replace">
     <xsl:param name="word"/>
+    <xsl:param name="splitlimit">32</xsl:param>
+    <xsl:variable name="secondhalflen" select="(string-length($word)+(string-length($word) mod 2)) div 2"/>
+    <xsl:variable name="secondhalfword" select="substring($word, $secondhalflen)"/>
+    <!-- When word is very big, a recursive replace is very heap/stack expensive, so subdivide on line break after middle of string -->
     <xsl:choose>
+      <xsl:when test="(string-length($word) > $splitlimit) and (contains($secondhalfword, '&#xa;'))">
+        <xsl:variable name="secondhalfend" select="substring-after($secondhalfword, '&#xa;')"/>
+        <xsl:variable name="firsthalflen" select="string-length($word) - $secondhalflen"/>
+        <xsl:variable name="firsthalfword" select="substring($word, 1, $firsthalflen)"/>
+        <xsl:variable name="firsthalfend" select="substring-before($secondhalfword, '&#xa;')"/>
+        <xsl:call-template name="br-replace">
+            <xsl:with-param name="word" select="concat($firsthalfword,$firsthalfend)"/>
+        </xsl:call-template>
+        <br/>
+        <xsl:call-template name="br-replace">
+            <xsl:with-param name="word" select="$secondhalfend"/>
+        </xsl:call-template>
+      </xsl:when>
       <xsl:when test="contains($word, '&#xa;')">
         <xsl:value-of select="substring-before($word, '&#xa;')"/>
         <br/>
diff --git a/src/etc/junit-noframes.xsl b/src/etc/junit-noframes.xsl
index d28cb2c..eb58896 100644
--- a/src/etc/junit-noframes.xsl
+++ b/src/etc/junit-noframes.xsl
@@ -468,7 +468,24 @@
 -->
 <xsl:template name="br-replace">
     <xsl:param name="word"/>
+    <xsl:param name="splitlimit">32</xsl:param>
+    <xsl:variable name="secondhalflen" select="(string-length($word)+(string-length($word) mod 2)) div 2"/>
+    <xsl:variable name="secondhalfword" select="substring($word, $secondhalflen)"/>
+    <!-- When word is very big, a recursive replace is very heap/stack expensive, so subdivide on line break after middle of string -->
     <xsl:choose>
+      <xsl:when test="(string-length($word) > $splitlimit) and (contains($secondhalfword, '&#xa;'))">
+        <xsl:variable name="secondhalfend" select="substring-after($secondhalfword, '&#xa;')"/>
+        <xsl:variable name="firsthalflen" select="string-length($word) - $secondhalflen"/>
+        <xsl:variable name="firsthalfword" select="substring($word, 1, $firsthalflen)"/>
+        <xsl:variable name="firsthalfend" select="substring-before($secondhalfword, '&#xa;')"/>
+        <xsl:call-template name="br-replace">
+            <xsl:with-param name="word" select="concat($firsthalfword,$firsthalfend)"/>
+        </xsl:call-template>
+        <br/>
+        <xsl:call-template name="br-replace">
+            <xsl:with-param name="word" select="$secondhalfend"/>
+        </xsl:call-template>
+      </xsl:when>
       <xsl:when test="contains($word, '&#xa;')">
         <xsl:value-of select="substring-before($word, '&#xa;')"/>
         <br/>