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

lukaszlenart pushed a commit to branch merge-master-to-7xx-2024-02-01
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 11d84a26c3c08078a1e28fa96359a7693edd79bc
Merge: 84d350dac eb469779f
Author: Lukasz Lenart <lukaszlen...@apache.org>
AuthorDate: Thu Feb 1 09:55:34 2024 +0100

    Merge remote-tracking branch 'origin/master' into 
merge-master-to-7xx-2024-02-01
    
    # Conflicts:
    #       Jenkinsfile
    #       
core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java
    #       core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java
    #       pom.xml

 .github/workflows/scorecards-analysis.yaml         |   2 +-
 .github/workflows/sonar.yml                        |   1 +
 Jenkinsfile                                        |  10 +-
 SECURITY.md                                        |  12 +-
 .../org/apache/struts2/showcase/UITagExample.java  |  24 +-
 .../showcase/action/ParamsAnnotationAction.java    | 133 ++++++++
 .../struts2/showcase/action/SkillAction.java       |   2 +
 .../struts2/showcase/async/ChatRoomAction.java     |   3 +
 .../struts2/showcase/conversion/AddressAction.java |   4 +-
 .../showcase/conversion/OperationsEnumAction.java  |   2 +
 .../struts2/showcase/conversion/PersonAction.java  |   2 +
 .../showcase/filedownload/FileDownloadAction.java  |   2 +
 .../showcase/fileupload/FileUploadAction.java      |   2 +
 .../PersonAction.java => model/MyDto.java}         |  35 +--
 .../validation/FieldValidatorsExampleAction.java   |  11 +
 .../struts2/showcase/wait/LongProcessAction.java   |   2 +
 .../struts-params-annotation.xml}                  |  43 +--
 apps/showcase/src/main/resources/struts.xml        |  14 +-
 .../src/main/webapp/WEB-INF/paramsannotation.vm    |  19 ++
 .../struts2/showcase/StrutsParametersTest.java     | 239 ++++++++++++++
 .../xwork2/config/impl/DefaultConfiguration.java   |   2 +
 .../xwork2/ognl/SecurityMemberAccess.java          |  10 +-
 .../security/DefaultAcceptedPatternsChecker.java   |  18 +-
 .../java/org/apache/struts2/StrutsConstants.java   |   3 +
 .../struts2/components/IteratorComponent.java      |  13 +-
 .../org/apache/struts2/dispatcher/Dispatcher.java  |   8 +
 .../parameter/ParametersInterceptor.java           | 204 +++++++++++-
 .../interceptor/parameter/StrutsParameter.java     |  44 +++
 .../org/apache/struts2/ognl/ThreadAllowlist.java   |  51 +++
 .../struts2/views/jsp/ComponentTagSupport.java     |  10 +-
 .../apache/struts2/views/jsp/IteratorStatus.java   |  20 +-
 core/src/main/resources/struts-beans.xml           |   1 +
 .../xwork2/ognl/SecurityMemberAccessTest.java      |   6 +-
 .../java/com/opensymphony/xwork2/test/User.java    |   6 +
 .../test/java/org/apache/struts2/TestAction.java   |   9 +
 .../struts2/components/IteratorComponentTest.java  | 208 +++++++++++-
 .../parameter/StrutsParameterAnnotationTest.java   | 348 +++++++++++++++++++++
 .../apache/struts2/views/jsp/IteratorTagTest.java  | 211 ++++++-------
 src/etc/project-suppression.xml                    |  21 +-
 39 files changed, 1522 insertions(+), 233 deletions(-)

diff --cc Jenkinsfile
index ca830acf2,1d8aa072a..45cd77441
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@@ -117,13 -191,10 +117,13 @@@ pipeline 
          }
          stage('Upload nightlies') {
            when {
 -            branch 'master'
 +            anyOf {
 +              branch 'master'
 +              branch 'release/struts-7-0-x'
 +            }
            }
            steps {
-             sh './mvnw -B package -DskipTests'
+             sh './mvnw -B package -DskipTests --no-transfer-progress'
              sshPublisher(publishers: [
                  sshPublisherDesc(
                      configName: 'Nightlies',
diff --cc 
apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java
index be6f38669,279c1e928..a1381c08c
--- 
a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java
+++ 
b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java
@@@ -23,8 -23,8 +23,9 @@@ package org.apache.struts2.showcase.fil
  import com.opensymphony.xwork2.ActionSupport;
  import org.apache.struts2.action.UploadedFilesAware;
  import org.apache.struts2.dispatcher.multipart.UploadedFile;
+ import org.apache.struts2.interceptor.parameter.StrutsParameter;
  
 +import java.io.File;
  import java.util.List;
  
  /**
diff --cc 
apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java
index 000000000,417909544..927f0d101
mode 000000,100644..100644
--- 
a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java
+++ 
b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java
@@@ -1,0 -1,239 +1,239 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements.  See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership.  The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License.  You may obtain a copy of the License at
+  *
+  *  http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing,
+  * software distributed under the License is distributed on an
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  * KIND, either express or implied.  See the License for the
+  * specific language governing permissions and limitations
+  * under the License.
+  */
+ package it.org.apache.struts2.showcase;
+ 
 -import com.gargoylesoftware.htmlunit.WebClient;
 -import com.gargoylesoftware.htmlunit.html.HtmlPage;
++import org.htmlunit.WebClient;
++import org.htmlunit.html.HtmlPage;
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+ import org.springframework.web.util.UriComponentsBuilder;
+ 
+ import java.io.IOException;
+ import java.util.HashMap;
+ import java.util.Map;
+ 
+ import static org.junit.Assert.assertEquals;
+ 
+ public class StrutsParametersTest {
+ 
+     private WebClient webClient;
+ 
+     @Before
+     public void setUp() throws Exception {
+         webClient = new WebClient();
+     }
+ 
+     @After
+     public void tearDown() throws Exception {
+         webClient.close();
+     }
+ 
+     @Test
+     public void public_StringField_WithoutGetterSetter_FieldNotAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicField", "yes");
+         params.put("varToPrint", "publicField");
+         assertText(params, "publicField{no}");
+     }
+ 
+     @Test
+     public void public_StringField_WithoutGetterSetter_FieldAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicFieldAnnotated", "yes");
+         params.put("varToPrint", "publicFieldAnnotated");
+         assertText(params, "publicFieldAnnotated{yes}");
+     }
+ 
+     @Test
+     public void private_StringField_WithSetter_MethodNotAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("privateFieldMethod", "yes");
+         params.put("varToPrint", "privateField");
+         assertText(params, "privateField{no}");
+     }
+ 
+     @Test
+     public void private_StringField_WithSetter_MethodAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("privateFieldMethodAnnotated", "yes");
+         params.put("varToPrint", "privateField");
+         assertText(params, "privateField{yes}");
+     }
+ 
+     @Test
+     public void public_ArrayField_WithoutGetterSetter_FieldNotAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicArray[0]", "1");
+         params.put("varToPrint", "publicArray");
+         assertText(params, "publicArray{[0]}");
+     }
+ 
+     @Test
+     public void public_ArrayField_WithoutGetterSetter_FieldAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicArrayAnnotated[0]", "1");
+         params.put("varToPrint", "publicArrayAnnotated");
+         assertText(params, "publicArrayAnnotated{[1]}");
+     }
+ 
+     @Test
+     public void public_ListField_WithoutGetterSetter_FieldNotAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicList[0]", "yes");
+         params.put("varToPrint", "publicList");
+         assertText(params, "publicList{[no]}");
+     }
+ 
+     @Test
+     public void public_ListField_WithoutGetterSetter_FieldAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicListAnnotated[0]", "yes");
+         params.put("varToPrint", "publicListAnnotated");
+         assertText(params, "publicListAnnotated{[yes]}");
+     }
+ 
+     @Test
+     public void private_ListField_WithGetterNoSetter_MethodNotAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("privateListMethod[0]", "yes");
+         params.put("varToPrint", "privateList");
+         assertText(params, "privateList{[no]}");
+     }
+ 
+     @Test
+     public void private_ListField_WithGetterNoSetter_MethodAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("privateListMethodAnnotated[0]", "yes");
+         params.put("varToPrint", "privateList");
+         assertText(params, "privateList{[yes]}");
+     }
+ 
+     @Test
+     public void public_MapField_WithoutGetterSetter_FieldNotAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMap['key']", "yes");
+         params.put("varToPrint", "publicMap");
+         assertText(params, "publicMap{{key=no}}");
+     }
+ 
+     @Test
+     public void public_MapField_WithoutGetterSetter_FieldAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMapAnnotated['key']", "yes");
+         params.put("varToPrint", "publicMapAnnotated");
+         assertText(params, "publicMapAnnotated{{key=yes}}");
+     }
+ 
+     @Test
+     public void 
public_MapField_Insert_WithoutGetterSetter_FieldNotAnnotated() throws Exception 
{
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMap[999]", "yes");
+         params.put("varToPrint", "publicMap");
+         assertText(params, "publicMap{{key=no}}");
+     }
+ 
+     @Test
+     public void public_MapField_Insert_WithoutGetterSetter_FieldAnnotated() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMapAnnotated[999]", "yes");
+         params.put("varToPrint", "publicMapAnnotated");
+         assertText(params, "publicMapAnnotated{{999=yes, key=no}}");
+     }
+ 
+     @Test
+     public void public_MyDtoField_WithoutGetter_FieldNotAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMyDto.str", "yes");
+         params.put("publicMyDto.map['key']", "yes");
+         params.put("publicMyDto.array[0]", "1");
+         params.put("varToPrint", "publicMyDto");
+         assertText(params, "publicMyDto{str=no, map={key=no}, array=[0]}");
+     }
+ 
+     @Test
+     public void public_MyDtoField_WithoutGetter_FieldAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMyDtoAnnotated.str", "yes");
+         params.put("publicMyDtoAnnotated.map['key']", "yes");
+         params.put("publicMyDtoAnnotated.array[0]", "1");
+         params.put("varToPrint", "publicMyDtoAnnotated");
+         assertText(params, "publicMyDtoAnnotated{str=yes, map={key=yes}, 
array=[1]}");
+     }
+ 
+     @Test
+     public void public_MyDtoField_WithoutGetter_FieldAnnotatedDepthOne() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("publicMyDtoAnnotatedDepthOne.str", "yes");
+         params.put("publicMyDtoAnnotatedDepthOne.map['key']", "yes");
+         params.put("publicMyDtoAnnotatedDepthOne.array[0]", "1");
+         params.put("varToPrint", "publicMyDtoAnnotatedDepthOne");
+         assertText(params, "publicMyDtoAnnotatedDepthOne{str=yes, 
map={key=no}, array=[0]}");
+     }
+ 
+     @Test
+     public void private_MyDtoField_WithGetter_MethodNotAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("unsafeMethodMyDto.str", "yes");
+         params.put("unsafeMethodMyDto.map['key']", "yes");
+         params.put("unsafeMethodMyDto.array[0]", "1");
+         params.put("varToPrint", "privateMyDto");
+         assertText(params, "privateMyDto{str=no, map={key=no}, array=[0]}");
+     }
+ 
+     @Test
+     public void private_MyDtoField_WithGetter_MethodNotAnnotated_Alternate() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("unsafeMethodMyDto['str']", "yes");
+         params.put("unsafeMethodMyDto['map']['key']", "yes");
+         params.put("unsafeMethodMyDto['map'][999]", "yes");
+         params.put("unsafeMethodMyDto['array'][0]", "1");
+         params.put("varToPrint", "privateMyDto");
+         assertText(params, "privateMyDto{str=no, map={key=no}, array=[0]}");
+     }
+ 
+     @Test
+     public void private_MyDtoField_WithGetter_MethodAnnotated() throws 
Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("safeMethodMyDto.str", "yes");
+         params.put("safeMethodMyDto.map['key']", "yes");
+         params.put("safeMethodMyDto.array[0]", "1");
+         params.put("varToPrint", "privateMyDto");
+         assertText(params, "privateMyDto{str=yes, map={key=yes}, array=[1]}");
+     }
+ 
+     @Test
+     public void private_MyDtoField_WithGetter_MethodAnnotatedDepthOne() 
throws Exception {
+         Map<String, String> params = new HashMap<>();
+         params.put("safeMethodMyDtoDepthOne.str", "yes");
+         params.put("safeMethodMyDtoDepthOne.map['key']", "yes");
+         params.put("safeMethodMyDtoDepthOne.array[0]", "1");
+         params.put("varToPrint", "privateMyDto");
+         assertText(params, "privateMyDto{str=yes, map={key=no}, array=[0]}");
+     }
+ 
+     private void assertText(Map<String, String> params, String text) throws 
IOException {
+         UriComponentsBuilder builder = 
UriComponentsBuilder.fromHttpUrl(ParameterUtils.getBaseUrl()).path("/paramsannotation/test.action");
+         params.forEach(builder::queryParam);
+         String url = builder.toUriString();
+         HtmlPage page = webClient.getPage(url);
+         String output = page.getElementById("output").asNormalizedText();
+         assertEquals(text, output);
+     }
+ }
diff --cc 
core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java
index 7ef4eed1e,c2208982c..e090daf77
--- a/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java
+++ b/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java
@@@ -18,15 -18,13 +18,14 @@@
   */
  package org.apache.struts2.views.jsp;
  
 -import com.opensymphony.xwork2.inject.Container;
 -import com.opensymphony.xwork2.util.ValueStack;
 +import jakarta.servlet.http.HttpServletRequest;
 +import jakarta.servlet.http.HttpServletResponse;
 +import jakarta.servlet.jsp.JspException;
 +
- import com.opensymphony.xwork2.ActionContext;
  import org.apache.struts2.components.Component;
  
 -import javax.servlet.http.HttpServletRequest;
 -import javax.servlet.http.HttpServletResponse;
 -import javax.servlet.jsp.JspException;
 +import com.opensymphony.xwork2.inject.Container;
 +import com.opensymphony.xwork2.util.ValueStack;
  
  /**
   */
@@@ -62,7 -59,7 +60,7 @@@ public abstract class ComponentTagSuppo
  
      /**
       * Define method to populate component state based on the Tag parameters.
-      * 
 -     * <p>
++     *
       * Descendants should override this method for custom behaviour, but 
should <em>always</em> call the ancestor method when doing so.
       */
      protected void populateParams() {
@@@ -71,7 -68,7 +69,7 @@@
  
      /**
       * Specialized method to populate the 
performClearTagStateForTagPoolingServers state of the Component to match the 
value set in the Tag.
-      * 
 -     * <p>
++     *
       * Generally only unit tests would call this method directly, to avoid 
calling the whole populateParams() chain again after doStartTag()
       * has been called.  Doing that can break tag / component state 
behaviour, but unit tests still need a way to set the
       * performClearTagStateForTagPoolingServers state for the component 
(which only comes into being after doStartTag() is called).
diff --cc core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java
index ad3f68745,fd3fc9587..3c355bf1d
--- a/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java
@@@ -18,34 -18,27 +18,32 @@@
   */
  package org.apache.struts2.views.jsp;
  
 -import com.mockobjects.servlet.MockBodyContent;
 -import com.mockobjects.servlet.MockJspWriter;
 -import com.opensymphony.xwork2.ActionContext;
++import jakarta.servlet.jsp.JspException;
++import jakarta.servlet.jsp.tagext.TagSupport;
+ import org.apache.commons.collections.ListUtils;
++import org.springframework.mock.web.MockBodyContent;
++import org.springframework.mock.web.MockJspWriter;
+ 
 -import javax.servlet.jsp.JspException;
 -import javax.servlet.jsp.tagext.TagSupport;
 +import java.io.StringWriter;
 +import java.io.Writer;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
+ import java.util.Locale;
  import java.util.Map;
  
- import org.apache.commons.collections.ListUtils;
- import org.springframework.mock.web.MockBodyContent;
- import org.springframework.mock.web.MockJspWriter;
- 
- import jakarta.servlet.jsp.JspException;
- import jakarta.servlet.jsp.tagext.TagSupport;
- 
 +
 +/**
 + * Test Case for Iterator Tag
-  *
 + */
  public class IteratorTagTest extends AbstractUITagTest {
  
-     IteratorTag tag;
- 
+     private IteratorTag tag;
  
      public void testIteratingWithIdSpecified() throws Exception {
-         List list = new ArrayList();
+         List<String> list = new ArrayList<>();
          list.add("one");
          list.add("two");
          list.add("three");
diff --cc src/etc/project-suppression.xml
index 38324163d,7b2a1c5fb..b0d5ebc95
--- a/src/etc/project-suppression.xml
+++ b/src/etc/project-suppression.xml
@@@ -132,22 -132,47 +132,17 @@@
          <notes><![CDATA[ file name: plexus-utils-1.2.jar]]></notes>
          <packageUrl 
regex="true">^pkg:maven/org\.codehaus\.plexus/plexus\-utils@.*$</packageUrl>
          <cpe>cpe:/a:plexus-utils_project:plexus-utils</cpe>
+         <cve>CVE-2022-4244</cve>
+         <cve>CVE-2022-4245</cve>
+         <cve>CVE-2017-1000487</cve>
      </suppress>
      <suppress>
-         <notes><![CDATA[file name: plexus-utils-1.2.jar]]></notes>
-         <packageUrl 
regex="true">^pkg:maven/org\.codehaus\.plexus/plexus\-utils@.*$</packageUrl>
-         <vulnerabilityName>CVE-2017-1000487</vulnerabilityName>
-     </suppress>
-     <suppress>
-         <notes><![CDATA[file name: plexus-utils-1.2.jar]]></notes>
-         <packageUrl 
regex="true">^pkg:maven/org\.codehaus\.plexus/plexus\-utils@.*$</packageUrl>
-         <vulnerabilityName>Directory traversal in 
org.codehaus.plexus.util.Expand</vulnerabilityName>
-     </suppress>
-     <suppress>
-         <notes><![CDATA[file name: plexus-utils-1.2.jar]]></notes>
-         <packageUrl 
regex="true">^pkg:maven/org\.codehaus\.plexus/plexus\-utils@.*$</packageUrl>
-         <vulnerabilityName>Possible XML Injection</vulnerabilityName>
+         <notes><![CDATA[ file name: 
plexus-container-default-1.0-alpha-10.jar]]></notes>
+         <packageUrl 
regex="true">^pkg:maven/org\.codehaus\.plexus\/plexus\-container\-default@.*$</packageUrl>
+         <cpe>cpe:/a:plexus-utils_project:plexus-utils</cpe>
+         <cve>CVE-2022-4244</cve>
+         <cve>CVE-2022-4245</cve>
      </suppress>
 -    <suppress>
 -        <notes><![CDATA[file name: oval-1.90.jar]]></notes>
 -        <packageUrl 
regex="true">^pkg:maven/net\.sf\.oval/oval@.*$</packageUrl>
 -        <cpe>cpe:/a:apache:groovy</cpe>
 -    </suppress>
 -    <suppress>
 -        <notes><![CDATA[file name: oval-1.90.jar]]></notes>
 -        <packageUrl 
regex="true">^pkg:maven/net\.sf\.oval/oval@.*$</packageUrl>
 -        <cpe>cpe:/a:apache:log4j</cpe>
 -    </suppress>
 -    <suppress>
 -        <notes><![CDATA[file name: oval-1.90.jar]]></notes>
 -        <packageUrl 
regex="true">^pkg:maven/net\.sf\.oval/oval@.*$</packageUrl>
 -        <cpe>cpe:/a:jruby:jruby</cpe>
 -    </suppress>
 -    <suppress>
 -        <notes><![CDATA[file name: oval-1.90.jar]]></notes>
 -        <packageUrl 
regex="true">^pkg:maven/net\.sf\.oval/oval@.*$</packageUrl>
 -        <cpe>cpe:/a:xstream_project:xstream</cpe>
 -    </suppress>
 -    <suppress>
 -        <notes><![CDATA[file name: oval-1.90.jar: 
xstream-1.4.19.jar]]></notes>
 -        <packageUrl 
regex="true">^pkg:maven/com\.thoughtworks\.xstream/xstream@.*$</packageUrl>
 -        <cve>CVE-2022-40151</cve>
 -        <cve>CVE-2022-40152</cve>
 -        <cve>CVE-2022-40153</cve>
 -        <cve>CVE-2022-40154</cve>
 -        <cve>CVE-2022-40155</cve>
 -        <cve>CVE-2022-40156</cve>
 -    </suppress>
      <!-- TestNG -->
      <suppress>
          <notes><![CDATA[file name: guava-19.0.jar]]></notes>

Reply via email to