[ 
https://issues.apache.org/jira/browse/WW-5836?focusedWorklogId=1052232&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1052232
 ]

ASF GitHub Bot logged work on WW-5836:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 03/Nov/26 18:46
            Start Date: 03/Nov/26 18:46
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #2096:
URL: https://github.com/apache/struts/pull/2096

   Fixes [WW-5836](https://issues.apache.org/jira/browse/WW-5836)
   
   6.x backport of #2095. Differences from main: Java 8 (no pattern matching), 
`BoundedMessageFormat` sits in `org.apache.struts2.util` and is public because 
its callers are in `com.opensymphony.xwork2` and 
`com.opensymphony.xwork2.util`, and the tests use `Collections.singletonList`.
   
   WW-5828 bounded the integer digits `StringConverter` emits for a 
`BigDecimal`, falling back to `BigDecimal.toString()` past 340. Two other paths 
format a `BigDecimal` without going through `StringConverter`, and neither 
applied the bound:
   
   - the `number` tag (`Number.end()`), which formats the value from the stack 
with `NumberFormat` directly;
   - `MessageFormat` arguments: 
`AbstractLocalizedTextProvider.formatWithNullDetection` (reached from 
`getText(key, args)`, `<s:text>` with `<s:param>`, and validator 
`messageParams`) and `DefaultTextProvider.getText(key, defaultValue, List)`.
   
   The bound and its check (`precision - scale`, computed in `long`) move to 
`BigDecimalBounds`, shared by `StringConverter`, the number tag and message 
formatting.
   
   **Number tag.** Past the bound the value renders with `toString()`. The 
tag's `maximumIntegerDigits` attribute is not a substitute, because 
`DecimalFormat` applies it by dropping leading digits.
   
   **Message arguments.** The argument itself cannot be replaced with a 
`String`, because a typed element such as `{0,number}` throws 
`IllegalArgumentException` on a String. Instead, when an argument is past the 
bound, `BoundedMessageFormat` formats through a clone whose elements delegate 
to their original formats and render the over-bound value with `toString()`.
   
   `MessageFormat` re-parses a choice branch that contains `{n}` only when the 
element's format is an actual `ChoiceFormat`. Wrapping a choice element would 
therefore print the nested `{0}` literally, and leaving it unwrapped would 
format the nested pattern without the bound. The wrapper repeats that step 
itself, with the bound applied to the nested pattern at every level. A call 
with no argument past the bound goes to `MessageFormat` unchanged.
   
   Tests pin both sides of the bound for:
   - the number tag, including `type="currency"`;
   - plain `{0}`, `{0,number}` and `{0,number,currency}`;
   - mixed elements (number pattern, String, date, `null`) next to an 
over-bound argument;
   - choice elements: nested one and two levels deep, a small choice argument 
with an over-bound nested `{1}`, and a branch with no nested argument.
   
   Below the bound, the output is compared byte for byte with plain 
`MessageFormat`. Full core suite green (2749).
   
   Observable change: a value with more than 340 integer digits renders in 
`1E+340` form in these paths, as it already does through `StringConverter`. A 
`{0,date}` element given such a value prints that form too, instead of a date 
built from `longValue()`.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




Issue Time Tracking
-------------------

    Worklog Id:     (was: 1052232)
    Time Spent: 20m  (was: 10m)

> Number tag and localized text arguments do not bound integer digits when 
> formatting BigDecimal
> ----------------------------------------------------------------------------------------------
>
>                 Key: WW-5836
>                 URL: https://issues.apache.org/jira/browse/WW-5836
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 6.13.0, 7.5.0
>
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> WW-5828 bounded the number of integer digits {{StringConverter}} emits when 
> it formats a {{BigDecimal}}, falling back to {{BigDecimal.toString()}} past 
> the bound so that the length of the output follows the precision of the value 
> rather than its scale.
> Two other places in core format a {{BigDecimal}} without going through 
> {{StringConverter}}, and neither applies the same bound:
> * the {{number}} tag formats the value it finds on the stack with 
> {{NumberFormat}} directly;
> * message arguments passed to {{getText(key, args)}} (also reached from the 
> {{text}} tag with {{param}}, and from validator {{messageParams}}) are 
> formatted by {{MessageFormat}}, which delegates numeric arguments to the 
> locale {{NumberFormat}}.
> Apply the WW-5828 bound to both paths, sharing the bound rather than 
> duplicating the constant. For message arguments the bound has to be applied 
> through the formatter, not by substituting the argument, since a number-typed 
> message element rejects a {{String}} argument. Values within the bound must 
> render byte-identically to today, including {{currency}} and typed message 
> elements.
> Same fix on the 6.x line.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to