You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2021/06/20 21:41:08 UTC

svn commit: r1890934 - in /xmlbeans/trunk/src: main/java/org/apache/xmlbeans/ main/java/org/apache/xmlbeans/impl/schema/ main/java/org/apache/xmlbeans/impl/tool/ main/resources/maven/ test/java/compile/scomp/checkin/ test/resources/xbean/compile/scomp/...

Author: kiwiwings
Date: Sun Jun 20 21:41:08 2021
New Revision: 1890934

URL: http://svn.apache.org/viewvc?rev=1890934&view=rev
Log:
add code injection filter
doesn't protect against "Expression Language Injection", therefore I've added an schema compiler option to activate the copying of the annotation which is by default off

Added:
    xmlbeans/trunk/src/test/resources/xbean/compile/scomp/schemacompiler/javadoc.xsd
      - copied, changed from r1890294, xmlbeans/trunk/src/test/resources/xbean/compile/scomp/partials/partialMethods.xsd
Modified:
    xmlbeans/trunk/src/main/java/org/apache/xmlbeans/XmlOptions.java
    xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/SchemaTypeCodePrinter.java
    xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/MavenPlugin.java
    xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/Parameters.java
    xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java
    xmlbeans/trunk/src/main/resources/maven/plugin.xml
    xmlbeans/trunk/src/test/java/compile/scomp/checkin/CompilationTests.java

Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/XmlOptions.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/java/org/apache/xmlbeans/XmlOptions.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/XmlOptions.java (original)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/XmlOptions.java Sun Jun 20 21:41:08 2021
@@ -134,6 +134,7 @@ public class XmlOptions implements java.
         COMPILE_MDEF_NAMESPACES,
         COMPILE_PARTIAL_TYPESYSTEM,
         COMPILE_PARTIAL_METHODS,
+        COMPILE_ANNOTATION_JAVADOC,
         VALIDATE_ON_SET,
         VALIDATE_TREAT_LAX_AS_SKIP,
         VALIDATE_STRICT,
@@ -1369,6 +1370,7 @@ public class XmlOptions implements java.
         return flag != null && flag;
     }
 
+
     public XmlOptions setXPathUseXmlBeans() {
         return setXPathUseSaxon(true);
     }
@@ -1382,6 +1384,26 @@ public class XmlOptions implements java.
         return flag != null && flag;
     }
 
+    public XmlOptions setCompileAnnotationAsJavadoc() {
+        return setCompileAnnotationAsJavadoc(true);
+    }
+
+    /**
+     * When generating the schema sources, copy over the schema annotations to the javadoc.
+     * Be aware basic code injection is filtered, but annotation based RCE aren't filtered.
+     * So think twice before activating this on untrusted schemas!
+     *
+     * @param useAnnotationAsJavadoc {@code true} = copy the annotation - defaults to {@code false}
+     */
+    public XmlOptions setCompileAnnotationAsJavadoc(boolean useAnnotationAsJavadoc) {
+        return set(XmlOptionsKeys.COMPILE_ANNOTATION_JAVADOC, useAnnotationAsJavadoc);
+    }
+
+    public boolean isCompileAnnotationAsJavadoc() {
+        Boolean flag = (Boolean) get(XmlOptionsKeys.COMPILE_ANNOTATION_JAVADOC);
+        return flag != null && flag;
+    }
+
     public XmlOptions setAttributeValidationCompatMode(boolean attributeValidationCompatMode) {
         return set(XmlOptionsKeys.ATTTRIBUTE_VALIDATION_COMPAT_MODE, attributeValidationCompatMode);
     }

Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/SchemaTypeCodePrinter.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/SchemaTypeCodePrinter.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/SchemaTypeCodePrinter.java (original)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/SchemaTypeCodePrinter.java Sun Jun 20 21:41:08 2021
@@ -185,7 +185,7 @@ public final class SchemaTypeCodePrinter
         }
 
         emit("/**");
-        if(sType.getDocumentation() != null && sType.getDocumentation().length() > 0){
+        if (opt.isCompileAnnotationAsJavadoc() && sType.getDocumentation() != null && sType.getDocumentation().length() > 0){
             emit(" *");
             printJavaDocBody(sType.getDocumentation());
             emit(" *");
@@ -500,29 +500,15 @@ public final class SchemaTypeCodePrinter
         emit(" */");
     }
 
-    //  removes newline, tabs and white spaces.
-    String cleanUpString(String s){
-        s = s.replace("\n", "");
-        s = s.replace("\t", "");
-        return s.trim();
-    }
-
-    void printJavaDocBody(String s) throws IOException{
+    void printJavaDocBody(String doc) throws IOException{
+        // add some poor mans code injection protection
+        // this is not protecting against annotation based RCEs like CVE-2018-16621
+        String docClean = doc.trim()
+            .replace("\t", "")
+            .replace("*/", "* /");
 
-        int start = 0;
-        int newLineIndex = s.indexOf("\n");
-
-        if(newLineIndex == -1){
+        for (String s : docClean.split("[\\n\\r]+")) {
             emit(" * " + s);
-        }else{
-            if(newLineIndex == 0){
-                newLineIndex = s.indexOf("\n", newLineIndex + 1);
-            }
-            while(newLineIndex > 0){
-                emit(" * " + cleanUpString(s.substring(start, newLineIndex)));
-                start = newLineIndex;
-                newLineIndex = s.indexOf("\n", start + 1);
-            }
         }
     }
 
@@ -810,7 +796,7 @@ public final class SchemaTypeCodePrinter
         boolean xmltype = (javaType == SchemaProperty.XML_OBJECT);
 
         if (prop.extendsJavaSingleton()) {
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                 printJavaDocParagraph(propertyDocumentation);
             }else {
                 printJavaDoc((several ? "Gets first " : "Gets the ") + propdesc, BeanMethod.GET);
@@ -829,7 +815,7 @@ public final class SchemaTypeCodePrinter
         }
 
         if (prop.extendsJavaOption()) {
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                 printJavaDocParagraph(propertyDocumentation);
             }else {
                 printJavaDoc((several ? "True if has at least one " : "True if has ") + propdesc, BeanMethod.IS_SET);
@@ -838,7 +824,7 @@ public final class SchemaTypeCodePrinter
         }
 
         if (several) {
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                 printJavaDocParagraph(propertyDocumentation);
             }
 
@@ -849,14 +835,14 @@ public final class SchemaTypeCodePrinter
                 wrappedType = javaWrappedType(javaType);
             }
 
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                 printJavaDocParagraph(propertyDocumentation);
             }else{
                 printJavaDoc("Gets a List of " + propdesc + "s", BeanMethod.GET_LIST);
             }
             emit("java.util.List<" + wrappedType + "> get" + propertyName + "List();", BeanMethod.GET_LIST);
 
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                 printJavaDocParagraph(propertyDocumentation);
             }else{
                 printJavaDoc("Gets array of all " + propdesc + "s", BeanMethod.GET_ARRAY);
@@ -909,7 +895,7 @@ public final class SchemaTypeCodePrinter
         String propdesc = "\"" + qName.getLocalPart() + "\"" + (isAttr ? " attribute" : " element");
 
         if (singleton) {
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0) {
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0) {
                 printJavaDocParagraph(propertyDocumentation);
             } else {
                 printJavaDoc((several ? "Sets first " : "Sets the ") + propdesc, BeanMethod.SET);
@@ -933,7 +919,7 @@ public final class SchemaTypeCodePrinter
         }
 
         if (optional) {
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0) {
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0) {
                 printJavaDocParagraph(propertyDocumentation);
             } else {
                 printJavaDoc((several ? "Removes first " : "Unsets the ") + propdesc, BeanMethod.UNSET);
@@ -944,14 +930,14 @@ public final class SchemaTypeCodePrinter
         if (several) {
             String arrayName = propertyName + "Array";
 
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0) {
+            if(opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0) {
                 printJavaDocParagraph(propertyDocumentation);
             } else {
                 printJavaDoc("Sets array of all " + propdesc, BeanMethod.SET_ARRAY);
             }
             emit("void set" + arrayName + "(" + type + "[] " + safeVarName + "Array);", BeanMethod.SET_ARRAY);
 
-            if(propertyDocumentation != null && propertyDocumentation.length() > 0) {
+            if (opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0) {
                 printJavaDocParagraph(propertyDocumentation);
             } else {
                 printJavaDoc("Sets ith " + propdesc, BeanMethod.SET_IDX);
@@ -1675,7 +1661,7 @@ public final class SchemaTypeCodePrinter
         if (prop.extendsJavaSingleton()) {
             if (bmList == null || bmList.contains(BeanMethod.GET)) {
                 // Value getProp()
-                if(propertyDocumentation != null && propertyDocumentation.length() > 0){
+                if(opt.isCompileAnnotationAsJavadoc() && propertyDocumentation != null && propertyDocumentation.length() > 0){
                     printJavaDocParagraph(propertyDocumentation);
                 } else {
                     printJavaDoc((several ? "Gets first " : "Gets the ") + propdesc);

Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/MavenPlugin.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/MavenPlugin.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/MavenPlugin.java (original)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/MavenPlugin.java Sun Jun 20 21:41:08 2021
@@ -172,6 +172,10 @@ public class MavenPlugin extends Abstrac
     @Parameter( defaultValue = "false" )
     private boolean debug;
 
+    /** copy annotations to javadoc of generated sources - default: false */
+    @Parameter( defaultValue = "false" )
+    private boolean copyAnn;
+
     @Parameter
     private List<Extension> extensions;
 
@@ -269,6 +273,7 @@ public class MavenPlugin extends Abstrac
             params.setNoUpa(noUpa);
             params.setNoPvr(noPvr);
             params.setNoAnn(noAnn);
+            params.setCopyAnn(copyAnn);
             params.setNoVDoc(noVDoc);
             if (repackage != null && !repackage.isEmpty()) {
                 params.setRepackage("org.apache.xmlbeans.metadata:"+repackage);

Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/Parameters.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/Parameters.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/Parameters.java (original)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/Parameters.java Sun Jun 20 21:41:08 2021
@@ -53,6 +53,7 @@ public class Parameters {
     private boolean noVDoc;
     private boolean noExt;
     private boolean debug;
+    private boolean copyAnn;
     private boolean incrementalSrcGen;
     private String repackage;
     private List<Extension> extensions = Collections.emptyList();
@@ -278,6 +279,14 @@ public class Parameters {
         repackage = newRepackage;
     }
 
+    public boolean isCopyAnn() {
+        return copyAnn;
+    }
+
+    public void setCopyAnn(boolean newCopyAnn) {
+        copyAnn = newCopyAnn;
+    }
+
     public List<Extension> getExtensions() {
         return extensions;
     }

Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java (original)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/tool/SchemaCompiler.java Sun Jun 20 21:41:08 2021
@@ -66,6 +66,7 @@ public class SchemaCompiler {
         System.out.println("    -partialMethods [list] -  comma separated list of bean methods to be generated. Use \"-\" to negate and \"ALL\" for all." );
         System.out.println("                              processed left-to-right, e.g. \"ALL,-GET_LIST\" exclude java.util.List getters - see XmlOptions.BeanMethod" );
         System.out.println("    -repackage - repackage specification, e.g. \"org.apache.xmlbeans.metadata:mypackage.metadata\" to change the metadata directory");
+        System.out.println("    -copyann - copy schema annotations to javadoc (default false) - don't activate on untrusted schema sources!");
         /* Undocumented feature - pass in one schema compiler extension and related parameters
         System.out.println("    -extension - registers a schema compiler extension");
         System.out.println("    -extensionParms - specify parameters for the compiler extension");
@@ -115,6 +116,7 @@ public class SchemaCompiler {
         opts.add("allowmdef");
         opts.add("catalog");
         opts.add("partialMethods");
+        opts.add("copyann");
 
         CommandLine cl = new CommandLine(args, flags, opts);
 
@@ -183,6 +185,7 @@ public class SchemaCompiler {
         boolean noExt = (cl.getOpt("noext") != null);
         boolean nojavac = (cl.getOpt("srconly") != null);
         boolean debug = (cl.getOpt("debug") != null);
+        boolean copyAnn = (cl.getOpt("copyann") != null);
 
         String allowmdef = cl.getOpt("allowmdef");
         Set<String> mdefNamespaces = (allowmdef == null ? Collections.emptySet() :
@@ -337,6 +340,7 @@ public class SchemaCompiler {
         params.setCatalogFile(catString);
         params.setSchemaCodePrinter(codePrinter);
         params.setPartialMethods(parsePartialMethods(partialMethods));
+        params.setCopyAnn(copyAnn);
         boolean result = compile(params);
 
         if (tempdir != null) {
@@ -609,6 +613,7 @@ public class SchemaCompiler {
         boolean noVDoc = params.isNoVDoc();
         boolean noExt = params.isNoExt();
         boolean incrSrcGen = params.isIncrementalSrcGen();
+        boolean copyAnn = params.isCopyAnn();
         Collection<XmlError> outerErrorListener = params.getErrorListener();
         Set<BeanMethod> partialMethods = params.getPartialMethods();
 
@@ -687,6 +692,7 @@ public class SchemaCompiler {
             }
             options.setCompilePartialMethod(partialMethods);
             options.setCompileNoAnnotations(noAnn);
+            options.setCompileAnnotationAsJavadoc(copyAnn);
 
             // save .xsb files
             system.save(filer);

Modified: xmlbeans/trunk/src/main/resources/maven/plugin.xml
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/main/resources/maven/plugin.xml?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/main/resources/maven/plugin.xml (original)
+++ xmlbeans/trunk/src/main/resources/maven/plugin.xml Sun Jun 20 21:41:08 2021
@@ -343,6 +343,13 @@
 					</extensions>
                 ]]></description>
                 </parameter>
+                <parameter>
+                    <name>copyAnn</name>
+                    <type>boolean</type>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>copy annotation to javadoc of generated source - don't use on untrusted schemas/sources!</description>
+                </parameter>
             </parameters>
             <configuration>
                 <project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
@@ -360,6 +367,7 @@
                 <noUpa implementation="boolean" default-value="false"/>
                 <noPvr implementation="boolean" default-value="false"/>
                 <noAnn implementation="boolean" default-value="false"/>
+                <copyAnn implementation="boolean" default-value="false"/>
                 <noVDoc implementation="boolean" default-value="false"/>
                 <download implementation="boolean" default-value="false"/>
                 <debug implementation="boolean" default-value="false"/>

Modified: xmlbeans/trunk/src/test/java/compile/scomp/checkin/CompilationTests.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/test/java/compile/scomp/checkin/CompilationTests.java?rev=1890934&r1=1890933&r2=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/test/java/compile/scomp/checkin/CompilationTests.java (original)
+++ xmlbeans/trunk/src/test/java/compile/scomp/checkin/CompilationTests.java Sun Jun 20 21:41:08 2021
@@ -432,6 +432,30 @@ public class CompilationTests {
         }
     }
 
+    @Test
+    public void annotation2javadoc() throws Exception {
+        deltree(xbeanOutput("compile/scomp/javadoc"));
+        File srcdir = xbeanOutput("compile/scomp/javadoc/src");
+        File classesdir = xbeanOutput("compile/scomp/javadoc/classes");
+        File outputjar = xbeanOutput("compile/scomp/javadoc/javadoc.jar");
+        Parameters params = new Parameters();
+        params.setXsdFiles(xbeanCase("schemacompiler/javadoc.xsd"));
+        params.setSrcDir(srcdir);
+        params.setClassesDir(classesdir);
+        params.setOutputJar(outputjar);
+        params.setName("javadoc");
+        SchemaCompiler.compile(params);
+
+        Path p = new File(srcdir, "javadoc/RootDocument.java").toPath();
+        String act = new String(Files.readAllBytes(p), StandardCharsets.UTF_8);
+        assertFalse(act.contains("* / heck, I'm smart"));
+
+        params.setCopyAnn(true);
+        SchemaCompiler.compile(params);
+
+        act = new String(Files.readAllBytes(p), StandardCharsets.UTF_8);
+        assertTrue(act.contains("* / heck, I'm smart"));
+    }
 
     //TESTENV:
 

Copied: xmlbeans/trunk/src/test/resources/xbean/compile/scomp/schemacompiler/javadoc.xsd (from r1890294, xmlbeans/trunk/src/test/resources/xbean/compile/scomp/partials/partialMethods.xsd)
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/test/resources/xbean/compile/scomp/schemacompiler/javadoc.xsd?p2=xmlbeans/trunk/src/test/resources/xbean/compile/scomp/schemacompiler/javadoc.xsd&p1=xmlbeans/trunk/src/test/resources/xbean/compile/scomp/partials/partialMethods.xsd&r1=1890294&r2=1890934&rev=1890934&view=diff
==============================================================================
--- xmlbeans/trunk/src/test/resources/xbean/compile/scomp/partials/partialMethods.xsd (original)
+++ xmlbeans/trunk/src/test/resources/xbean/compile/scomp/schemacompiler/javadoc.xsd Sun Jun 20 21:41:08 2021
@@ -13,24 +13,27 @@
      See the License for the specific language governing permissions and
      limitations under the License. -->
 
-
+<!DOCTYPE xs:schema [
+    <!ENTITY endcom "*/" >
+    <!ENTITY cve "*/ heck, I'm smart &#10;&#13;*&#47;   &endcom;" >
+]>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-        xmlns="partials"
-        targetNamespace="partials"
+        xmlns="javadoc"
+        targetNamespace="javadoc"
         elementFormDefault="qualified">
 
     <xs:element name="root">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="single" minOccurs="0" type="xs:decimal" nillable="true"/>
-                <xs:element name="complex" minOccurs="0" type="xmlBeanchen"/>
-                <xs:element name="primitiveList" minOccurs="0" maxOccurs="unbounded" type="xs:decimal" nillable="true"/>
-                <xs:element name="complexList" minOccurs="0" maxOccurs="unbounded" type="xmlBeanchen"/>
+                <xs:element name="single" minOccurs="0" type="xs:decimal" nillable="true">
+                    <xs:annotation>
+                        <xs:documentation>@deprecated use something else
+                        */ just try to inject code
+                        &cve;
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:element>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
-
-    <xs:complexType name="xmlBeanchen">
-        <xs:attribute name="name" type="xs:string"/>
-    </xs:complexType>
 </xs:schema>



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org