[Git][java-team/libjettison-java][buster] 20 commits: Standards-Version updated to 4.5.1

Markus Koschany (@apo) gitlab at salsa.debian.org
Sat Dec 31 16:06:21 GMT 2022



Markus Koschany pushed to branch buster at Debian Java Maintainers / libjettison-java


Commits:
44603457 by Emmanuel Bourg at 2021-01-18T00:09:11+01:00
Standards-Version updated to 4.5.1

- - - - -
5e0c77b3 by Emmanuel Bourg at 2021-01-18T00:09:16+01:00
Switch to debhelper level 13

- - - - -
80ab88ac by Emmanuel Bourg at 2021-01-18T00:09:22+01:00
Use salsa.debian.org Vcs-* URLs

- - - - -
f41bb181 by Emmanuel Bourg at 2021-01-18T00:10:10+01:00
New upstream version 1.4.1
- - - - -
688a7497 by Emmanuel Bourg at 2021-01-18T00:10:11+01:00
Update upstream source from tag 'upstream/1.4.1'

Update to upstream version '1.4.1'
with Debian dir 50aa28fc29c3b87e8605a2c9792cc3a95f072aaf
- - - - -
8a2313f8 by Emmanuel Bourg at 2021-01-18T00:15:07+01:00
New upstream release (1.4.1)

- - - - -
8f6552e7 by Markus Koschany at 2022-11-10T01:08:29+01:00
Update debian/watch

- - - - -
3a3fe486 by Markus Koschany at 2022-11-10T01:08:48+01:00
Update upstream source from tag 'upstream/1.5.1'

Update to upstream version '1.5.1'
with Debian dir e8277480979a2fc148c12f99c36b8bee9c0a1452
- - - - -
bceadea9 by Markus Koschany at 2022-11-10T01:08:48+01:00
New upstream version 1.5.1
- - - - -
0040e8fc by Markus Koschany at 2022-11-10T01:18:11+01:00
Update changelog

- - - - -
5fb6ce90 by Markus Koschany at 2022-11-10T01:20:03+01:00
Drop 01-maven-bundle-plugin-compatibility.patch

- - - - -
16e50402 by Markus Koschany at 2022-11-10T01:21:45+01:00
Ignore org.apache.maven.plugins:maven-enforcer-plugin

- - - - -
b14a2249 by Markus Koschany at 2022-12-31T11:13:14+01:00
New upstream version 1.5.3
- - - - -
3202dbfb by Markus Koschany at 2022-12-31T11:13:14+01:00
Update upstream source from tag 'upstream/1.5.3'

Update to upstream version '1.5.3'
with Debian dir bd7aedd2c1a810acb3bc17e539e91dea15f4d833
- - - - -
cd052075 by Markus Koschany at 2022-12-31T11:18:41+01:00
Declare compliance with Debian Policy 4.6.2.

- - - - -
c9fa5e7f by Markus Koschany at 2022-12-31T11:20:31+01:00
Update changelog

- - - - -
7a07aa39 by Markus Koschany at 2022-12-31T11:36:04+01:00
Merge branch 'master' into buster

- - - - -
190f5310 by Markus Koschany at 2022-12-31T11:37:48+01:00
Update changelog

- - - - -
69d02a81 by Markus Koschany at 2022-12-31T11:38:18+01:00
Drop patches/CVE-2022-40149.patch

- - - - -
cfeca30f by Markus Koschany at 2022-12-31T11:38:48+01:00
Revert to debhelper-compat = 12.

- - - - -


25 changed files:

- + .github/workflows/codeql-analysis.yml
- README.md
- debian/changelog
- − debian/compat
- debian/control
- debian/maven.ignoreRules
- − debian/patches/01-maven-bundle-plugin-compatibility.patch
- − debian/patches/CVE-2022-40149.patch
- − debian/patches/series
- debian/watch
- pom.xml
- src/main/java/org/codehaus/jettison/json/JSONArray.java
- src/main/java/org/codehaus/jettison/json/JSONException.java
- src/main/java/org/codehaus/jettison/json/JSONObject.java
- src/main/java/org/codehaus/jettison/json/JSONTokener.java
- src/main/java/org/codehaus/jettison/json/JSONWriter.java
- src/main/java/org/codehaus/jettison/mapped/Configuration.java
- src/main/java/org/codehaus/jettison/mapped/DefaultConverter.java
- src/main/java/org/codehaus/jettison/mapped/MappedNamespaceConvention.java
- src/main/java/org/codehaus/jettison/mapped/MappedXMLStreamReader.java
- src/main/java/org/codehaus/jettison/mapped/MappedXMLStreamWriter.java
- src/main/java/org/codehaus/jettison/util/StringIndenter.java
- src/test/java/org/codehaus/jettison/json/JSONArrayTest.java
- src/test/java/org/codehaus/jettison/json/JSONObjectTest.java
- + src/test/java/org/codehaus/jettison/json/JSONTokenerTest.java


Changes:

=====================================
.github/workflows/codeql-analysis.yml
=====================================
@@ -0,0 +1,74 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+  push:
+    branches: [ "master" ]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [ "master" ]
+  schedule:
+    - cron: '38 10 * * 5'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+    permissions:
+      actions: read
+      contents: read
+      security-events: write
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'java' ]
+        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout at v3
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init at v2
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file.
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        
+        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+        # queries: security-extended,security-and-quality
+
+        
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    - name: Autobuild
+      uses: github/codeql-action/autobuild at v2
+
+    # ℹ️ Command-line programs to run using the OS shell..
+    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+    #   If the Autobuild fails above, remove it and uncomment the following three lines. 
+    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+
+    # - run: |
+    #   echo "Run, Build Application using script"
+    #   ./location_of_script_within_repo/buildscript.sh
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze at v2
+      with:
+        category: "/language:${{matrix.language}}"


=====================================
README.md
=====================================
@@ -1,5 +1,5 @@
 Jettison is a Java library for converting XML to JSON and vice-versa with the help of StAX (https://en.wikipedia.org/wiki/StAX).
-It implements XMLStreamWriter and XMLStreamReader and supports Mapped and BadgerFish conventions. Latest release is 1.3.7.
+It implements XMLStreamWriter and XMLStreamReader and supports Mapped and BadgerFish conventions. Latest release is 1.4.0.
 
 For example, with a Mapped convention, JAXB processes JAXB beans and emits XMLStreamWriter events which are processed by Jettison
 with the XML data being converted to JSON. Likewise, when it reads JSON, it reports XMLStreamReader events for JAXB to populate JAXB


=====================================
debian/changelog
=====================================
@@ -1,12 +1,42 @@
-libjettison-java (1.4.0-1+deb10u1) buster-security; urgency=high
+libjettison-java (1.5.3-1~deb10u1) buster-security; urgency=high
 
-  * Non-maintainer upload by the LTS team.
+  * Team upload.
+  * Fix CVE-2022-40150, CVE-2022-45685, CVE-2022-45693:
+    denial of service via stack overflow / out of memory
+
+ -- Markus Koschany <apo at debian.org>  Sat, 31 Dec 2022 11:36:13 +0100
+
+libjettison-java (1.5.3-1) unstable; urgency=high
+
+  * Team upload.
+  * New upstream version 1.5.3.
+    - Fix CVE-2022-40150, CVE-2022-45685, CVE-2022-45693:
+      denial of service via stack overflow / out of memory
+      (Closes: #1022553)
+  * Declare compliance with Debian Policy 4.6.2.
+
+ -- Markus Koschany <apo at debian.org>  Sat, 31 Dec 2022 11:18:53 +0100
+
+libjettison-java (1.5.1-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream version 1.5.1.
   * Fix CVE-2022-40149:
     It was discovered that libjettison-java, a collection of StAX parsers and
     writers for JSON, was vulnerable to a denial-of-service attack, if the
-    attacker provided untrusted XML or JSON data.
+    attacker provided untrusted XML or JSON data. (Closes: #1022554)
+
+ -- Markus Koschany <apo at debian.org>  Thu, 10 Nov 2022 01:09:07 +0100
+
+libjettison-java (1.4.1-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release
+  * Standards-Version updated to 4.5.1
+  * Switch to debhelper level 13
+  * Use salsa.debian.org Vcs-* URLs
 
- -- Markus Koschany <apo at debian.org>  Thu, 10 Nov 2022 00:28:44 +0100
+ -- Emmanuel Bourg <ebourg at apache.org>  Mon, 18 Jan 2021 00:14:42 +0100
 
 libjettison-java (1.4.0-1) unstable; urgency=medium
 


=====================================
debian/compat deleted
=====================================
@@ -1 +0,0 @@
-11


=====================================
debian/control
=====================================
@@ -4,15 +4,15 @@ Priority: optional
 Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
 Uploaders: Torsten Werner <twerner at debian.org>
 Build-Depends:
- debhelper (>= 11),
+ debhelper-compat (= 12),
  default-jdk,
  junit4,
  libmaven-bundle-plugin-java,
  libwoodstox-java,
  maven-debian-helper
-Standards-Version: 4.1.4
-Vcs-Git: https://anonscm.debian.org/git/pkg-java/libjettison-java.git
-Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/libjettison-java.git
+Standards-Version: 4.6.2
+Vcs-Git: https://salsa.debian.org/java-team/libjettison-java.git
+Vcs-Browser: https://salsa.debian.org/java-team/libjettison-java
 Homepage: https://github.com/jettison-json/jettison
 
 Package: libjettison-java


=====================================
debian/maven.ignoreRules
=====================================
@@ -1 +1,2 @@
 org.sonatype.plugins nexus-staging-maven-plugin
+org.apache.maven.plugins maven-enforcer-plugin * * * *


=====================================
debian/patches/01-maven-bundle-plugin-compatibility.patch deleted
=====================================
@@ -1,13 +0,0 @@
-Description: Adjusts the bundle plugin configuration to avoid generating an empty jar
-Author: Emmanuel Bourg <ebourg at apache.org>
-Forwarded: no
---- a/pom.xml
-+++ b/pom.xml
-@@ -70,7 +70,6 @@
-            <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-            <Export-Package>org.codehaus.jettison*;version=${project.version}</Export-Package>
-            <Import-Package>*</Import-Package>
--           <Private-Package>!*</Private-Package>
-            <Implementation-Title>${project.name}</Implementation-Title>
-            <Implementation-Version>${project.version}</Implementation-Version>
-          </instructions>


=====================================
debian/patches/CVE-2022-40149.patch deleted
=====================================
@@ -1,89 +0,0 @@
-From: Markus Koschany <apo at debian.org>
-Date: Thu, 10 Nov 2022 00:28:12 +0100
-Subject: CVE-2022-40149
-
----
- .../org/codehaus/jettison/json/JSONTokener.java    |  3 ++
- .../org/codehaus/jettison/json/JSONObjectTest.java | 57 +++++++++++++++++++++-
- 2 files changed, 59 insertions(+), 1 deletion(-)
-
-diff --git a/src/main/java/org/codehaus/jettison/json/JSONTokener.java b/src/main/java/org/codehaus/jettison/json/JSONTokener.java
-index 7beb791..80391f1 100644
---- a/src/main/java/org/codehaus/jettison/json/JSONTokener.java
-+++ b/src/main/java/org/codehaus/jettison/json/JSONTokener.java
-@@ -190,6 +190,9 @@ public class JSONTokener {
-                     }
-                     break;
-                 default:
-+                    if (!more()) {
-+                        throw syntaxError("The JSON text is malformed");
-+                    }
-                     back();
-                     return '/';
-                 }
-diff --git a/src/test/java/org/codehaus/jettison/json/JSONObjectTest.java b/src/test/java/org/codehaus/jettison/json/JSONObjectTest.java
-index 6fbd919..acd8246 100644
---- a/src/test/java/org/codehaus/jettison/json/JSONObjectTest.java
-+++ b/src/test/java/org/codehaus/jettison/json/JSONObjectTest.java
-@@ -92,5 +92,60 @@ public class JSONObjectTest extends TestCase {
-       assertEquals(obj.toString(), "{\"key\":\"http://example.com/foo\"}");
-       obj.setEscapeForwardSlashAlways(true);
-       assertEquals(obj.toString(), "{\"key\":\"http:\\/\\/example.com\\/foo\"}");
--   }
-+    }
-+
-+    public void testMalformedObject() throws Exception {
-+       try {
-+           new JSONObject("{/");
-+           fail("Failure expected on malformed JSON");
-+       } catch (JSONException ex) {
-+           // expected
-+       }
-+    }
-+
-+    public void testMalformedObject2() throws Exception {
-+        try {
-+            new JSONObject("{x");
-+            fail("Failure expected on malformed JSON");
-+        } catch (JSONException ex) {
-+            // expected
-+        }
-+    }
-+
-+    public void testMalformedObject3() throws Exception {
-+        try {
-+            new JSONObject("{/x");
-+            fail("Failure expected on malformed JSON");
-+        } catch (JSONException ex) {
-+            // expected
-+        }
-+    }
-+
-+    public void testMalformedObject4() throws Exception {
-+        try {
-+            new JSONObject("{/*");
-+            fail("Failure expected on malformed JSON");
-+        } catch (JSONException ex) {
-+            // expected
-+        }
-+    }
-+
-+    public void testMalformedObject5() throws Exception {
-+        try {
-+            new JSONObject("{//");
-+            fail("Failure expected on malformed JSON");
-+        } catch (JSONException ex) {
-+            // expected
-+        }
-+    }
-+
-+    public void testMalformedArray() throws Exception {
-+        try {
-+            new JSONObject("{[/");
-+            fail("Failure expected on malformed JSON");
-+        } catch (JSONException ex) {
-+            // expected
-+        }
-+    }
-+
- }


=====================================
debian/patches/series deleted
=====================================
@@ -1,2 +0,0 @@
-01-maven-bundle-plugin-compatibility.patch
-CVE-2022-40149.patch


=====================================
debian/watch
=====================================
@@ -1,3 +1,3 @@
-version=3
-opts="repack,compression=xz" \
-https://github.com/jettison-json/jettison/tags .*/archive/jettison-([\d\.]+).tar.gz
+version=4
+opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/jettison-json-$1\.tar\.gz/ \
+ https://github.com/jettison-json/jettison/tags .*/jettison-?(\d\S+)\.tar\.gz


=====================================
pom.xml
=====================================
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.codehaus.jettison</groupId>
   <artifactId>jettison</artifactId>
-  <version>1.4.0</version>
+  <version>1.5.3</version>
   <packaging>bundle</packaging>
   <name>Jettison</name>
   <description>A StAX implementation for JSON.</description>
@@ -17,13 +17,13 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>4.12</version>
+      <version>4.13.2</version>
       <scope>test</scope>
     </dependency>
 	<dependency> 
 		<groupId>com.fasterxml.woodstox</groupId>
 		<artifactId>woodstox-core</artifactId>
-		<version>5.0.3</version>
+		<version>6.4.0</version>
 		<scope>test</scope>
 	</dependency>    
   </dependencies>
@@ -31,7 +31,7 @@
     <connection>scm:git:http://github.com/jettison-json/jettison.git</connection>
     <developerConnection>scm:git:https://github.com/jettison-json/jettison.git</developerConnection>
     <url>https://github.com/jettison-json/jettison</url>
-    <tag>jettison-1.4.0</tag>
+    <tag>jettison-1.5.3</tag>
   </scm>
   <distributionManagement>
       <snapshotRepository>
@@ -46,10 +46,30 @@
   <build>
     
     <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0</version>
+        <executions>
+          <execution>
+            <id>enforce-maven</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <requireMavenVersion>
+                  <version>3.2.5</version>
+                </requireMavenVersion>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.7.0</version>
+        <version>3.10.1</version>
         <configuration>
           <source>1.8</source>
           <target>1.8</target>
@@ -59,41 +79,42 @@
           <showWarnings>true</showWarnings>
         </configuration>
       </plugin>
+      <plugin>
+          <groupId>org.sonatype.plugins</groupId>
+          <artifactId>nexus-staging-maven-plugin</artifactId>
+          <version>1.6.13</version>
+          <extensions>true</extensions>
+          <configuration>
+              <serverId>ossrh</serverId>
+              <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+              <autoReleaseAfterClose>true</autoReleaseAfterClose>
+          </configuration>
+      </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
         <extensions>true</extensions>
-        <version>1.0.0</version>
+        <version>5.1.6</version>
         <configuration>
          <instructions>
            <Bundle-Name>${project.artifactId}</Bundle-Name>
            <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
            <Export-Package>org.codehaus.jettison*;version=${project.version}</Export-Package>
-           <Import-Package>*</Import-Package>
-           <Private-Package>!*</Private-Package>
+           <Import-Package>javax.xml,*</Import-Package>
            <Implementation-Title>${project.name}</Implementation-Title>
            <Implementation-Version>${project.version}</Implementation-Version>
+           <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@)))</_versionpolicy>
+           <_nouses>true</_nouses>
          </instructions>
         </configuration>
       </plugin>
-      <plugin>
-          <groupId>org.sonatype.plugins</groupId>
-          <artifactId>nexus-staging-maven-plugin</artifactId>
-          <version>1.6.8</version>
-          <extensions>true</extensions>
-          <configuration>
-              <serverId>ossrh</serverId>
-              <nexusUrl>https://oss.sonatype.org/</nexusUrl>
-              <autoReleaseAfterClose>true</autoReleaseAfterClose>
-          </configuration>
-      </plugin>
     </plugins>
     <pluginManagement>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-release-plugin</artifactId>
-                <version>2.5.2</version>
+                <version>2.5.3</version>
                 <configuration>
                     <useReleaseProfile>false</useReleaseProfile>
                     <preparationGoals>clean install</preparationGoals>
@@ -114,7 +135,7 @@
                   <plugin>
                       <inherited>true</inherited>
                       <artifactId>maven-deploy-plugin</artifactId>
-                      <version>2.8.1</version>
+                      <version>2.8.2</version>
                       <configuration>
                           <altDeploymentRepository>${deploy.altRepository}</altDeploymentRepository>
                           <updateReleaseInfo>true</updateReleaseInfo>
@@ -123,7 +144,7 @@
                   <!-- We want to sign the artifact, the POM, and all attached artifacts -->
                   <plugin>
                       <artifactId>maven-gpg-plugin</artifactId>
-                      <version>1.6</version>
+                      <version>3.0.1</version>
                       <executions>
                           <execution>
                               <goals>


=====================================
src/main/java/org/codehaus/jettison/json/JSONArray.java
=====================================
@@ -179,8 +179,9 @@ public class JSONArray implements Serializable {
     /**
      * Construct a JSONArray from a Collection.
      * @param collection     A Collection.
+     * @throws JSONException If there is a syntax error.
      */
-    public JSONArray(Collection collection) {
+    public JSONArray(Collection collection) throws JSONException {
         this.myArrayList = (collection == null) ?
                 new ArrayList() :
                 new ArrayList(collection);
@@ -580,8 +581,9 @@ public class JSONArray implements Serializable {
      * JSONArray which is produced from a Collection.
      * @param value     A Collection value.
      * @return          this.
+     * @throws JSONException If there is a syntax error.
      */
-    public JSONArray put(Collection value) {
+    public JSONArray put(Collection value) throws JSONException {
         put(new JSONArray(value));
         return this;
     }
@@ -621,7 +623,7 @@ public class JSONArray implements Serializable {
      * @return this.
      */
     public JSONArray put(long value) {
-        put(new Long(value));
+        put(Long.valueOf(value));
         return this;
     }
 
@@ -631,8 +633,9 @@ public class JSONArray implements Serializable {
      * JSONObject which is produced from a Map.
      * @param value     A Map value.
      * @return          this.
+     * @throws JSONException If there is a syntax error.
      */
-    public JSONArray put(Map value) {
+    public JSONArray put(Map value) throws JSONException {
         put(new JSONObject(value));
         return this;
     }
@@ -727,7 +730,7 @@ public class JSONArray implements Serializable {
      * @throws JSONException If the index is negative.
      */
     public JSONArray put(int index, long value) throws JSONException {
-        put(index, new Long(value));
+        put(index, Long.valueOf(value));
         return this;
     }
 


=====================================
src/main/java/org/codehaus/jettison/json/JSONException.java
=====================================
@@ -21,7 +21,6 @@ package org.codehaus.jettison.json;
  * @version 2
  */
 public class JSONException extends Exception {
-    private Throwable cause;
     private int line = -1;
     private int column = -1;
     /**
@@ -40,11 +39,6 @@ public class JSONException extends Exception {
 
     public JSONException(Throwable t) {
         super(t.getMessage(), t);
-        this.cause = t;
-    }
-
-    public Throwable getCause() {
-        return this.cause;
     }
 
 	public int getColumn() {


=====================================
src/main/java/org/codehaus/jettison/json/JSONObject.java
=====================================
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.codehaus.jettison.JSONSequenceTooLargeException;
 
@@ -83,6 +84,13 @@ import org.codehaus.jettison.JSONSequenceTooLargeException;
  */
 public class JSONObject implements Serializable {
 
+    /**
+     * The default recursion depth limit to prevent stack overflow issues on deeply nested structures.
+     */
+    final static int DEFAULT_RECURSION_DEPTH_LIMIT = 500;
+    
+    static int RECURSION_DEPTH_LIMIT = DEFAULT_RECURSION_DEPTH_LIMIT;
+
     /**
      * JSONObject.NULL is equivalent to the value that JavaScript calls null,
      * whilst Java's null is equivalent to the value that JavaScript calls
@@ -91,15 +99,15 @@ public class JSONObject implements Serializable {
      private static final class Null {
 
     	 boolean explicitNull;
-    	 
-    	 public Null() { 
-    		 
+
+    	 public Null() {
+
     	 }
 
-         public Null(boolean explicitNull) { 
+         public Null(boolean explicitNull) {
     		 this.explicitNull = explicitNull;
     	 }
-    	 
+
         /**
          * There is only intended to be a single instance of the NULL object,
          * so the clone method returns itself.
@@ -128,7 +136,7 @@ public class JSONObject implements Serializable {
         public String toString() {
             return isExplicitNull() ? null : "null";
         }
-        
+
         public boolean isExplicitNull() {
             return explicitNull;
         }
@@ -138,7 +146,7 @@ public class JSONObject implements Serializable {
     /**
      * The hash map where the JSONObject's properties are kept.
      */
-    private LinkedHashMap myHashMap;
+    private LinkedHashMap<Object,Object> myHashMap;
     private boolean dropRootElement;
     private List ignoredElements;
     private boolean writeNullAsString = true;
@@ -165,10 +173,10 @@ public class JSONObject implements Serializable {
     public JSONObject(List ignoredElements) {
     	this(false, ignoredElements, true, true);
     }
-    
-    public JSONObject(boolean dropRootElement, List ignoredElements, boolean writeNullAsString, 
+
+    public JSONObject(boolean dropRootElement, List ignoredElements, boolean writeNullAsString,
     		          boolean escapeForwardSlash) {
-        this.myHashMap = new LinkedHashMap();
+        this.myHashMap = new LinkedHashMap<Object,Object>();
         this.dropRootElement = dropRootElement;
         this.ignoredElements = ignoredElements;
         this.writeNullAsString = writeNullAsString;
@@ -212,6 +220,8 @@ public class JSONObject implements Serializable {
                 throw x.syntaxError("A JSONObject text must end with '}'");
             case '}':
                 return;
+            case '{':
+                throw x.syntaxError("Expected a key");                
             default:
                 x.back();
                 key = x.nextValue().toString();
@@ -256,24 +266,33 @@ public class JSONObject implements Serializable {
      * Construct a JSONObject from a Map.
      * @param map A map object that can be used to initialize the contents of
      *  the JSONObject.
+     * @throws JSONException If there is a syntax error.
      */
-    public JSONObject(Map map) {
+    public JSONObject(Map map) throws JSONException {
+        this(map, 0);
+    }
+
+    private JSONObject(Map map, int recursionDepth) throws JSONException {
+
+        if (recursionDepth > RECURSION_DEPTH_LIMIT) {
+            throw new JSONException("JSONObject has reached recursion depth limit of " + RECURSION_DEPTH_LIMIT);
+        }
         this.myHashMap = (map == null) ?
-                new LinkedHashMap() :
-                new LinkedHashMap(map);
+                new LinkedHashMap<Object,Object>() :
+                new LinkedHashMap<Object,Object>(map);
         // ensure a pure hierarchy of JSONObjects and JSONArrays
-        for (Object k : myHashMap.keySet()) {
-            Object v = myHashMap.get(k);
+        for (Entry entry : myHashMap.entrySet()) {
+            Object v = entry.getValue();
             if (v instanceof Collection) {
-                myHashMap.put(k, new JSONArray((Collection) v));
+                myHashMap.put(entry.getKey(), new JSONArray((Collection) v));
             }
-            if (v instanceof Map) {
-                myHashMap.put(k, new JSONObject((Map) v));
+            if (v instanceof Map && v != map) {
+                myHashMap.put(entry.getKey(), new JSONObject((Map) v, recursionDepth + 1));
             }
-        }                
+        }
     }
 
-    
+
     /**
      * Construct a JSONObject from an Object, using reflection to find the
      * public members. The resulting JSONObject's keys will be the strings
@@ -349,7 +368,7 @@ public class JSONObject implements Serializable {
      * @param key   A key string.
      * @param value An object to be accumulated under the key.
      * @return this.
-     * @throws JSONException If the key is null or if the current value 
+     * @throws JSONException If the key is null or if the current value
      *  associated with the key is not a JSONArray.
      */
     public JSONObject append(String key, Object value)
@@ -359,7 +378,7 @@ public class JSONObject implements Serializable {
         if (o == null) {
             put(key, new JSONArray().put(value));
         } else if (!(o instanceof JSONArray)){
-            throw new JSONException("JSONObject[" + key + 
+            throw new JSONException("JSONObject[" + key +
                         "] is not a JSONArray.");
         } else {
         	((JSONArray)o).put(value);
@@ -450,7 +469,7 @@ public class JSONObject implements Serializable {
     private double doGetDouble(String key, Object o) throws JSONException {
         try {
             return o instanceof Number ?
-                ((Number)o).doubleValue() : 
+                ((Number)o).doubleValue() :
                 Double.valueOf((String)o).doubleValue();
         } catch (Exception e) {
             throw new JSONException("JSONObject[" + quote(key) +
@@ -470,7 +489,7 @@ public class JSONObject implements Serializable {
      */
     public int getInt(String key) throws JSONException {
         return doGetInt(key, get(key));
-        
+
     }
     private int doGetInt(String key, Object o) throws JSONException {
         return o instanceof Number ? ((Number)o).intValue() : (int)getDouble(key);
@@ -674,7 +693,7 @@ public class JSONObject implements Serializable {
         }
     }
 
-    
+
     /**
      * Put a key/value pair in the JSONObject, where the value will be a
      * JSONArray which is produced from a Collection.
@@ -688,7 +707,7 @@ public class JSONObject implements Serializable {
         return this;
     }
 
-    
+
     /**
      * Get an optional double associated with a key,
      * or NaN if there is no such key or if its value is not a number.
@@ -909,11 +928,11 @@ public class JSONObject implements Serializable {
      * @throws JSONException If the key is null.
      */
     public JSONObject put(String key, long value) throws JSONException {
-        put(key, new Long(value));
+        put(key, Long.valueOf(value));
         return this;
     }
 
-     
+
     /**
      * Put a key/value pair in the JSONObject, where the value will be a
      * JSONObject which is produced from a Map.
@@ -926,8 +945,8 @@ public class JSONObject implements Serializable {
         put(key, new JSONObject(value));
         return this;
     }
-    
-    
+
+
     /**
      * Put a key/value pair in the JSONObject. If the value is null,
      * then the key will be removed from the JSONObject if it is present..
@@ -942,11 +961,11 @@ public class JSONObject implements Serializable {
     public JSONObject put(String key, Object value) throws JSONException {
         return doPut(key, value, -1, false);
     }
-    
-    protected JSONObject doPut(String key, 
+
+    protected JSONObject doPut(String key,
     		                   Object value,
     		                   int threshold,
-    		                   boolean checkExistingValue) 
+    		                   boolean checkExistingValue)
     		throws JSONException {
         if (key == null) {
             throw new JSONException("Null key.");
@@ -995,7 +1014,7 @@ public class JSONObject implements Serializable {
         return this;
     }
 
-    
+
 
     /**
      * Produce a string in double quotes with backslash sequences in all the
@@ -1024,9 +1043,10 @@ public class JSONObject implements Serializable {
             c = string.charAt(i);
             switch (c) {
             case '\\':
+                sb.append("\\\\");
+                break;
             case '"':
-                sb.append('\\');
-                sb.append(c);
+                sb.append("\\\"");
                 break;
             case '/':
             	if (escapeForwardSlashAlways || i > 0 && string.charAt(i - 1) == '<') {
@@ -1049,6 +1069,12 @@ public class JSONObject implements Serializable {
             case '\r':
                 sb.append("\\r");
                 break;
+            case '\u2028':
+                sb.append("\\u2028");
+                break;
+            case '\u2029':
+                sb.append("\\u2029");
+                break;
             default:
                 if (c < ' ') {
                     t = "000" + Integer.toHexString(c);
@@ -1118,7 +1144,7 @@ public class JSONObject implements Serializable {
     public int hashCode() {
     	return myHashMap.hashCode();
     }
-    
+
     @Override
     public boolean equals(Object obj) {
     	if (obj instanceof JSONObject) {
@@ -1127,7 +1153,7 @@ public class JSONObject implements Serializable {
     		return false;
     	}
     }
-    
+
     /**
      * Make a JSON text of this JSONObject. For compactness, no whitespace
      * is added. If this would not result in a syntactically correct JSON text,
@@ -1201,34 +1227,25 @@ public class JSONObject implements Serializable {
         Iterator     keys = keys();
         StringBuilder sb = new StringBuilder("{");
         int          newindent = indent + indentFactor;
-        Object       o;
-        if (n == 1) {
-            o = keys.next();
-            sb.append(quote(o.toString(), escapeForwardSlashAlways));
-            sb.append(": ");
-            sb.append(valueToString(this.myHashMap.get(o), indentFactor,
-                    indent, escapeForwardSlashAlways));
-        } else {
-            while (keys.hasNext()) {
-                o = keys.next();
-                if (sb.length() > 1) {
-                    sb.append(",\n");
-                } else {
-                    sb.append('\n');
-                }
-                for (i = 0; i < newindent; i += 1) {
-                    sb.append(' ');
-                }
-                sb.append(quote(o.toString()));
-                sb.append(": ");
-                sb.append(valueToString(this.myHashMap.get(o), indentFactor,
-                        newindent, escapeForwardSlashAlways));
-            }
+        while (keys.hasNext()) {
+            Object o = keys.next();
             if (sb.length() > 1) {
+                sb.append(",\n");
+            } else {
                 sb.append('\n');
-                for (i = 0; i < indent; i += 1) {
-                    sb.append(' ');
-                }
+            }
+            for (i = 0; i < newindent; i += 1) {
+                sb.append(' ');
+            }
+            sb.append(quote(o.toString()));
+            sb.append(": ");
+            sb.append(valueToString(this.myHashMap.get(o), indentFactor,
+                    newindent, escapeForwardSlashAlways));
+        }
+        if (sb.length() > 1) {
+            sb.append('\n');
+            for (i = 0; i < indent; i += 1) {
+                sb.append(' ');
             }
         }
         sb.append('}');
@@ -1252,21 +1269,21 @@ public class JSONObject implements Serializable {
      *  with <code>}</code> <small>(right brace)</small>.
      * @throws JSONException If the value is or contains an invalid number.
      */
-    static String valueToString(Object value, boolean escapeForwardSlash) throws JSONException {	
-    	
+    static String valueToString(Object value, boolean escapeForwardSlash) throws JSONException {
+
         if (value == null || value.equals(null)) {
             return "null";
         }
         if (value instanceof JSONString) {
-                Object o;
-                try {
+            String o;
+            try {
                 o = ((JSONString)value).toJSONString();
             } catch (Exception e) {
                 throw new JSONException(e);
             }
-            if (o instanceof String) {
-                        return (String) o;
-                }
+            if (o != null) {
+                return o;
+            }
             throw new JSONException("Bad value from toJSONString: " + o);
         }
         if (value instanceof Number) {
@@ -1300,12 +1317,9 @@ public class JSONObject implements Serializable {
             return "null";
         }
         try {
-                if (value instanceof JSONString) {
-                        Object o = ((JSONString)value).toJSONString();
-                        if (o instanceof String) {
-                                return (String)o;
-                        }
-                }
+            if (value instanceof JSONString) {
+                return ((JSONString)value).toJSONString();
+            }
         } catch (Exception e) {
                 /* forget about it */
         }
@@ -1324,6 +1338,43 @@ public class JSONObject implements Serializable {
         return quote(value.toString(), escapeForwardSlash);
     }
 
+    /**
+     * Set the new recursion depth limit to prevent stack overflow issues on deeply nested structures. The default
+     * value is 500
+     * @param newRecursionDepthLimit the new recursion depth limit to set
+     */
+    public static void setGlobalRecursionDepthLimit(int newRecursionDepthLimit) {
+        RECURSION_DEPTH_LIMIT = newRecursionDepthLimit;
+    }
+
+    /**
+     * Set the new recursion depth limit to prevent stack overflow issues on deeply nested structures. The default
+     * value is 500
+     * @param newRecursionDepthLimit the new recursion depth limit to set
+     */
+    @Deprecated
+    public void setRecursionDepthLimit(int newRecursionDepthLimit) {
+        RECURSION_DEPTH_LIMIT = newRecursionDepthLimit;
+    }
+
+    /**
+     * Get the new recursion depth limit to prevent stack overflow issues on deeply nested structures. The default
+     * value is 500
+     * @return the recursion depth limit
+     */
+    public static int getGlobalRecursionDepthLimit() {
+        return RECURSION_DEPTH_LIMIT;
+    }
+
+    /**
+     * Get the new recursion depth limit to prevent stack overflow issues on deeply nested structures. The default
+     * value is 500
+     * @return the recursion depth limit
+     */
+    @Deprecated
+    public int getRecursionDepthLimit() {
+        return RECURSION_DEPTH_LIMIT;
+    }
 
      /**
       * Write the contents of the JSONObject as JSON text to a writer.
@@ -1338,37 +1389,38 @@ public class JSONObject implements Serializable {
      public Writer write(Writer writer) throws JSONException {
         try {
         	int hashMapSize = this.myHashMap.size();
-        	
+
         	boolean dropObjectKeyName = false;
         	if (hashMapSize == 1) {
-        		dropObjectKeyName = dropRootElement 
+        		dropObjectKeyName = dropRootElement
         			|| ignoredElements != null && ignoredElements.contains(keys().next());
         	}
-        	
+
             if (!dropObjectKeyName) {
                 writer.write('{');
             }
 
             boolean  b = false;
-            
+
             Iterator keys = keys();
             while (keys.hasNext()) {
                 if (b) {
                     writer.write(',');
+                    b = false;
                 }
                 String k = keys.next().toString();
                 Object v = this.myHashMap.get(k);
-                
+
                 boolean mayBeDropSimpleElement = false;
                 if (!dropObjectKeyName) {
-                	mayBeDropSimpleElement = hashMapSize > 1 
+                	mayBeDropSimpleElement = hashMapSize > 1
                 		&& ignoredElements != null && ignoredElements.contains(k);
                 	if (!mayBeDropSimpleElement) {
                         writer.write(quote(k, escapeForwardSlashAlways));
                         writer.write(':');
                 	}
                 }
-                
+
                 if (v instanceof JSONObject) {
                     ((JSONObject)v).write(writer);
                 } else if (v instanceof JSONArray) {
@@ -1388,7 +1440,7 @@ public class JSONObject implements Serializable {
             throw new JSONException(e);
         }
      }
-     
+
      public boolean isEscapeForwardSlashAlways() {
        return escapeForwardSlashAlways;
      }
@@ -1396,4 +1448,9 @@ public class JSONObject implements Serializable {
      public void setEscapeForwardSlashAlways(boolean escapeForwardSlashAlways) {
        this.escapeForwardSlashAlways = escapeForwardSlashAlways;
      }
-}
\ No newline at end of file
+    
+     public Map toMap() {
+       return Collections.unmodifiableMap(myHashMap);
+     }
+
+}


=====================================
src/main/java/org/codehaus/jettison/json/JSONTokener.java
=====================================
@@ -15,6 +15,8 @@ limitations under the License.
 */
 package org.codehaus.jettison.json;
 
+import java.math.BigDecimal;
+
 /**
  * A JSONTokener takes a source string and extracts characters and tokens from
  * it. It is used by the JSONObject and JSONArray constructors to parse
@@ -24,6 +26,11 @@ package org.codehaus.jettison.json;
  */
 public class JSONTokener {
 
+    private static final String USE_BIGDECIMAL_JSONTOKENER_KEY = "jettison.json.jsontokener.use_bigdecimal";
+    public static final boolean USE_BIGDECIMAL_JSONTOKENER = Boolean.getBoolean( USE_BIGDECIMAL_JSONTOKENER_KEY );
+    protected boolean useBigDecimal = USE_BIGDECIMAL_JSONTOKENER; 
+
+
     /**
      * The index of the next character.
      */
@@ -37,7 +44,9 @@ public class JSONTokener {
 
 
     private int threshold = -1;
-    
+
+    private int recursionDepth;
+
     /**
      * Construct a JSONTokener from a string.
      *
@@ -47,7 +56,7 @@ public class JSONTokener {
         this.myIndex = 0;
         this.mySource = s.trim();
     }
-    
+
     /**
      * Construct a JSONTokener from a string.
      *
@@ -185,11 +194,13 @@ public class JSONTokener {
                             if (next() == '/') {
                                 break;
                             }
-                            back();
                         }
                     }
                     break;
                 default:
+                    if (!more()) {
+                        throw syntaxError("The JSON text is malformed");
+                    }
                     back();
                     return '/';
                 }
@@ -308,7 +319,8 @@ public class JSONTokener {
 
 
     /**
-     * Get the next value. The value can be a Boolean, Double, Integer,
+     * Get the next value. The value can be a Boolean, Double/BigDecimal
+     * (depending on -Djettison.json.jsontokener.use_bigdecimal), Integer,
      * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
      * @throws JSONException If syntax error.
      *
@@ -392,13 +404,17 @@ public class JSONTokener {
                 }
             }
             try {
-                return new Integer(s);
+                return Integer.valueOf(s);
             } catch (Exception e) {
                 try {
-                    return new Long(s);
+                    return Long.valueOf(s);
                 } catch (Exception f) {
                     try {
-                        return new Double(s);
+                        if (useBigDecimal) {
+                            return new BigDecimal(s);
+                        } else {
+                            return new Double(s);
+                        }
                     }  catch (Exception g) {
                         return s;
                     }
@@ -409,11 +425,24 @@ public class JSONTokener {
     }
 
     protected JSONObject newJSONObject() throws JSONException {
-    	return new JSONObject(this);
+        checkRecursionDepth();
+        JSONObject object = new JSONObject(this);
+        recursionDepth--;
+        return object;
     }
-    
+
     protected JSONArray newJSONArray() throws JSONException {
-    	return new JSONArray(this);
+        checkRecursionDepth();
+        JSONArray array = new JSONArray(this);
+        recursionDepth--;
+        return array;
+    }
+
+    private void checkRecursionDepth() throws JSONException {
+        recursionDepth++;
+        if (recursionDepth > JSONObject.RECURSION_DEPTH_LIMIT) {
+            throw new JSONException("JSONTokener has reached recursion depth limit of " + JSONObject.RECURSION_DEPTH_LIMIT);
+        }
     }
     
     /**


=====================================
src/main/java/org/codehaus/jettison/json/JSONWriter.java
=====================================
@@ -92,7 +92,7 @@ public class JSONWriter {
      */
     private int top;
 
-    /**kue
+    /**
      * The writer that will receive the output.
      */
     protected Writer writer;
@@ -140,7 +140,7 @@ public class JSONWriter {
     /**
      * Begin appending a new array. All values until the balancing
      * <code>endArray</code> will be appended to this array. The
-     * <code>endArray</code> method must be called to mark the array's end.kue
+     * <code>endArray</code> method must be called to mark the array's end.
      * @return this
      * @throws JSONException If the nesting is too deep, or if the object is
      * started in the wrong place (for example as a key or after the end of the


=====================================
src/main/java/org/codehaus/jettison/mapped/Configuration.java
=====================================
@@ -75,6 +75,7 @@ public class Configuration {
     private String attributeKey = "@";
     private boolean ignoreNamespaces;
     private boolean dropRootElement;
+    private boolean rootElementArrayWrapper = true;
     private Set primitiveArrayKeys = Collections.EMPTY_SET;
     private boolean writeNullAsString = true;
     private boolean readNullAsString;
@@ -169,7 +170,14 @@ public class Configuration {
 	public void setDropRootElement(boolean dropRootElement) {
 		this.dropRootElement = dropRootElement;
 	}
+	public boolean isRootElementArrayWrapper() {
+            return rootElementArrayWrapper;
+        }
 
+        public void setRootElementArrayWrapper(boolean rootElementArrayWrapper) {
+            this.rootElementArrayWrapper = rootElementArrayWrapper;
+        }
+	
 	public boolean isWriteNullAsString() {
 		return writeNullAsString;
 	}


=====================================
src/main/java/org/codehaus/jettison/mapped/DefaultConverter.java
=====================================
@@ -33,35 +33,194 @@ public class DefaultConverter implements TypeConverter {
 
 	public Object convertToJSONPrimitive(String text) {
         if(text == null) return text;
-		Object primitive = null;
-		// Attempt to convert to Integer
-		try {
-			primitive = enforce32BitInt ? Integer.valueOf(text) : Long.valueOf(text);
-		} catch (Exception e) {/**/}
-		// Attempt to convert to double
-		if (primitive == null) {
-			try {
-				Double v = Double.valueOf(text);
-                if( !v.isInfinite() && !v.isNaN() ) {
-                    primitive = v;
+
+        // If there's at least one character
+        if (text.length() >= 1) {
+            // find the first character
+            char first = text.charAt(0);
+
+            // Is it incompatible with a number?
+            if ((first < '0' || first > '9') && first != '-') {
+                // Yes it is, so special case check for Boolean values
+                if (first == 't') {
+                    if (text.equals("true")) {
+                       return Boolean.TRUE;
+                    }
+                } else if (first == 'f') {
+                    if (text.equals("false")) {
+                        return Boolean.FALSE;
+                    }
                 }
-                else {
+
+                // Definitely not a Boolean or a number, so return the original value
+                return text;
+            }
+        }
+
+        Object primitive = null;
+
+        if (enforce32BitInt) {
+            primitive = getInteger(text);
+        } else {
+            primitive = getLong(text);
+        }
+
+        if (primitive == null) {
+            Double dbl = getDouble(text);
+
+            if (dbl != null) {
+                if (dbl.isInfinite() || dbl.isNaN()) {
                     primitive = text;
                 }
-			} catch (Exception e) {/**/}
-		}
-		// Attempt to convert to boolean
-		if (primitive == null) {
-			if(text.trim().equalsIgnoreCase("true") || text.trim().equalsIgnoreCase("false")) {
-				primitive = Boolean.valueOf(text);
-			}
-		}
-
-		if (primitive == null || !primitive.toString().equals(text)) {
-			// Default String
-			primitive = text;
-		}
-
-		return primitive;
+                else {
+                    primitive = dbl;
+                }
+            }
+        }
+
+        if (primitive == null || !primitive.toString().equals(text)) {
+            // Default String
+            primitive = text;
+        }
+
+        return primitive;
+    }
+
+	private static final int MAX_LENGTH_LONG = String.valueOf(Long.MAX_VALUE).length();
+	private static final int MAX_LENGTH_LONG_NEGATIVE = String.valueOf(Long.MAX_VALUE).length() + 1;
+
+	/**
+     *  Try to get a Long value efficiently, avoiding Exceptions
+     */
+    private static Long getLong(String text)
+    {
+        // handle an empty string
+        if (text.isEmpty()) return null;
+
+        // if the text is too long it can't be a Long
+        if (text.charAt(0) == '-') {
+            if (text.length() > MAX_LENGTH_LONG_NEGATIVE) {
+                return null;
+	        }
+        } else if (text.length() > MAX_LENGTH_LONG) {
+            return null;
+        }
+
+        // Handle a leading minus sign
+        int i = 0;
+        if (text.charAt(0) == '-') {
+            if (text.length() > 1) {
+                i++;
+            } else {
+                return null;
+            }
+        }
+
+        // Check each character is a digit
+        for (; i < text.length(); i++) {
+            if (!Character.isDigit(text.charAt(i))) {
+                return null;
+            }
+        }
+
+        // It looks like it might be a Long, so give it a go
+        try {
+            return Long.parseLong(text);
+        } catch (Exception e) {
+            // It isn't a Long
+            return null;
+        }
+    }
+
+    private static final int MAX_LENGTH_INTEGER = String.valueOf(Integer.MAX_VALUE).length();
+    private static final int MAX_LENGTH_INTEGER_NEGATIVE = String.valueOf(Integer.MAX_VALUE).length() + 1;
+
+    /**
+     *  Try to get an Integer value efficiently, avoiding Exceptions
+     */
+    private static Integer getInteger(String text) {
+        // handle an empty string
+        if (text.isEmpty()) return null;
+
+        // if the text is too long it can't be an Integer
+        if (text.charAt(0) == '-') {
+            if (text.length() > MAX_LENGTH_INTEGER_NEGATIVE) {
+                return null;
+	        }
+        }
+        else if (text.length() > MAX_LENGTH_INTEGER) {
+            return null;
+        }
+
+        // Handle a leading minus sign
+        int i = 0;
+        if (text.charAt(0) == '-') {
+            if (text.length() > 1) {
+                i++;
+            } else {
+                return null;
+            }
+        }
+
+        // Check each character is a digit
+        for (; i < text.length(); i++) {
+            if (!Character.isDigit(text.charAt(i))) {
+                return null;
+            }
+        }
+
+        // It looks like it might be an Integer, so give it a go
+        try {
+            return Integer.parseInt(text);
+        } catch (Exception e) {
+            // It isn't an Integer
+            return null;
+        }
+    }
+
+    /**
+     * Try to get a Double value efficiently, avoiding Exceptions
+     */
+    private static Double getDouble(String text) {
+        boolean foundDP = false;
+        boolean foundExp = false;
+
+        // handle an empty string
+        if (text.isEmpty())
+            return null;
+
+        // Handle a leading minus sign
+        int i = 0;
+        if (text.charAt(0) == '-') {
+            if (text.length() > 1)
+                i++;
+            else
+                return null;
+        }
+
+        // Check each character is a digit
+        for (; i < text.length(); i++) {
+            char next = text.charAt(i);
+            if (!Character.isDigit(next)) {
+                if (next == '.') {
+                    if (foundDP)
+                        return null;
+                    foundDP = true;
+                } else if (next == 'E' || next == 'e') {
+                    if (foundExp)
+                        return null;
+                    foundExp = true;
+                } else
+                    return null;
+            }
+        }
+
+        // It looks like it might be a Double, so give it a go
+        try {
+            return Double.parseDouble(text);
+        } catch (Exception e) {
+            // It isn't a Double
+            return null;
+        }
     }
 }


=====================================
src/main/java/org/codehaus/jettison/mapped/MappedNamespaceConvention.java
=====================================
@@ -51,6 +51,7 @@ public class MappedNamespaceConvention implements Convention, NamespaceContext {
     private Set<?> primitiveArrayKeys;
     private boolean dropRootElement;
     private boolean writeNullAsString = true;
+    private boolean rootElementArrayWrapper = true;
     private boolean ignoreEmptyArrayValues;
     private boolean readNullAsString;
     private boolean escapeForwardSlashAlways;
@@ -66,6 +67,7 @@ public class MappedNamespaceConvention implements Convention, NamespaceContext {
         this.supressAtAttributes = config.isSupressAtAttributes();
         this.ignoreNamespaces = config.isIgnoreNamespaces();
         this.dropRootElement = config.isDropRootElement();
+        this.rootElementArrayWrapper = config.isRootElementArrayWrapper();
         this.attributeKey = config.getAttributeKey();
         this.primitiveArrayKeys = config.getPrimitiveArrayKeys();
         this.ignoredElements = config.getIgnoredElements();
@@ -135,6 +137,25 @@ public class MappedNamespaceConvention implements Convention, NamespaceContext {
                             n.setNamespace( prefix, uri );
                         }
                     }
+                    // With the 1.0 release, the default behavior was to treat an @xmlns
+                    // JSON field name (without a namespace prefix), as the attribute for
+                    // the default namespace URI. During JSON->XML serialization, this
+                    // default behavior resulted in an xmlns (without a namespace prefix)
+                    // attribute appearing on the applicable element, with the default
+                    // namespace uri as it's value.
+                    //
+                    // The code refactoring in this processAttributesAndNamespaces
+                    // method back in the 2.0 release, no longer assigns the default
+                    // namespace URI to the xmlns (without a namespace prefix) during JSON->XML
+                    // serialization, which in some cases is causing unmarshaling issues.
+                    // Putting in the following conditional check, restores the previous
+                    // default behavior, without breaking anything added during the earlier
+                    // refactoring exercise.
+                    if (o instanceof String) {
+                        String uri = o.toString();
+                        QName name = new QName( XMLConstants.DEFAULT_NS_PREFIX, k);
+                        n.setAttribute(name, uri);
+                    }
                 }
                 else {
                     String strValue = o == null ? null : o.toString();
@@ -313,10 +334,13 @@ public class MappedNamespaceConvention implements Convention, NamespaceContext {
 	public boolean isDropRootElement() {
 		return dropRootElement;
 	}
+	public boolean isRootElementArrayWrapper() {
+	    return rootElementArrayWrapper;
+	}
 	public List<?> getIgnoredElements() {
-        return ignoredElements;
-    }
-    public boolean isWriteNullAsString() {
+            return ignoredElements;
+        }
+        public boolean isWriteNullAsString() {
 		return writeNullAsString;
 	}
 	public boolean isReadNullAsString() {


=====================================
src/main/java/org/codehaus/jettison/mapped/MappedXMLStreamReader.java
=====================================
@@ -50,7 +50,11 @@ public class MappedXMLStreamReader extends AbstractXMLStreamReader {
         if (top instanceof JSONObject) {
             this.node = new Node(null, rootName, (JSONObject)top, convention);
         } else if (top instanceof JSONArray && !(((JSONArray)top).length() == 1 && ((JSONArray)top).get(0).equals(""))) {
-            this.node = new Node(null, rootName, obj, convention);
+            if (con.isRootElementArrayWrapper()) {
+                this.node = new Node(null, rootName, obj, convention);
+            } else {
+                this.node = new Node(null, rootName, ((JSONArray)top).getJSONObject(0), convention);
+            }
         } else {
             node = new Node(rootName, convention);
             convention.processAttributesAndNamespaces(node, obj);


=====================================
src/main/java/org/codehaus/jettison/mapped/MappedXMLStreamWriter.java
=====================================
@@ -243,6 +243,10 @@ public class MappedXMLStreamWriter extends AbstractXMLStreamWriter {
 	}
 	
 	public void writeStartElement(String prefix, String local, String ns) throws XMLStreamException {
+		if (current == null) {
+			this.writeStartDocument();
+		}
+
 		String parentKey = current.getTreeKey();
 		stack.push(current);
 		String key = convention.createKey(prefix, ns, local);


=====================================
src/main/java/org/codehaus/jettison/util/StringIndenter.java
=====================================
@@ -78,7 +78,7 @@ public class StringIndenter {
       return null;
     }
     String resultString = this.result.toString();
-    return resultString == null ? null : resultString.trim();
+    return resultString.trim();
   }
 
   /**


=====================================
src/test/java/org/codehaus/jettison/json/JSONArrayTest.java
=====================================
@@ -43,6 +43,30 @@ public class JSONArrayTest extends TestCase {
       String expectedValue = "[\"a string with / character\",{\"key\":\"http://example.com/foo\"}]";
       assertEquals(expectedValue, array.toString());
     }
-    
-    
+
+    public void testInfiniteLoop() {
+        String str = "[*/*A25] **";
+        try {
+            new JSONArray(str);
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testInfiniteLoop2() {
+        String str = "[/";
+        try {
+            new JSONArray(str);
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testIssue52() throws JSONException {
+        JSONObject.setGlobalRecursionDepthLimit(10);
+        new JSONArray("[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {a:10}]");
+    }
+
 }


=====================================
src/test/java/org/codehaus/jettison/json/JSONObjectTest.java
=====================================
@@ -2,7 +2,13 @@ package org.codehaus.jettison.json;
 
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 public class JSONObjectTest extends TestCase {
+
     public void testEquals() throws Exception {
     	JSONObject aJsonObj = new JSONObject("{\"x\":\"y\"}");
     	JSONObject bJsonObj = new JSONObject("{\"x\":\"y\"}");
@@ -81,7 +87,11 @@ public class JSONObjectTest extends TestCase {
     public void testSlashEscapingTurnedOnByDefault() throws Exception {
        JSONObject obj = new JSONObject();
        obj.put("key", "http://example.com/foo");
-       assertEquals(obj.toString(), "{\"key\":\"http:\\/\\/example.com\\/foo\"}");
+       assertEquals("{\"key\":\"http:\\/\\/example.com\\/foo\"}", obj.toString());
+        
+        obj = new JSONObject();
+        obj.put("key", "\\\\");
+        assertEquals("{\"key\":\"\\\\\\\\\"}", obj.toString());
     }
     
     public void testForwardSlashEscapingModifiedfBySetter() throws Exception {
@@ -92,5 +102,113 @@ public class JSONObjectTest extends TestCase {
       assertEquals(obj.toString(), "{\"key\":\"http://example.com/foo\"}");
       obj.setEscapeForwardSlashAlways(true);
       assertEquals(obj.toString(), "{\"key\":\"http:\\/\\/example.com\\/foo\"}");
-   }
+    }
+
+    public void testMalformedObject() throws Exception {
+       try {
+           new JSONObject("{/");
+           fail("Failure expected on malformed JSON");
+       } catch (JSONException ex) {
+           // expected
+       }
+    }
+
+    public void testMalformedObject2() throws Exception {
+        try {
+            new JSONObject("{x");
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testMalformedObject3() throws Exception {
+        try {
+            new JSONObject("{/x");
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testMalformedObject4() throws Exception {
+        try {
+            new JSONObject("{/*");
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testMalformedObject5() throws Exception {
+        try {
+            new JSONObject("{//");
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    public void testMalformedArray() throws Exception {
+        try {
+            new JSONObject("{[/");
+            fail("Failure expected on malformed JSON");
+        } catch (JSONException ex) {
+            // expected
+        }
+    }
+
+    // https://github.com/jettison-json/jettison/issues/52
+    public void testIssue52() throws Exception {
+        Map<String,Object> map = new HashMap<>();
+        map.put("t",map);
+        new JSONObject(map);
+    }
+
+    // https://github.com/jettison-json/jettison/issues/52
+    public void testIssue52Recursive() throws Exception {
+        try {
+            Map<String, Object> map = new HashMap<>();
+            Map<String, Object> map2 = new HashMap<>();
+            map.put("t", map2);
+            map2.put("t", map);
+            new JSONObject(map);
+            fail("Failure expected");
+        } catch (JSONException e) {
+            assertTrue(e.getMessage().contains("JSONObject has reached recursion depth limit"));
+            // expected
+        }
+    }
+
+    // https://github.com/jettison-json/jettison/issues/45
+    public void testFuzzerTestCase() throws Exception, JSONException {
+        try {
+            new JSONObject("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{\"G\":[30018084,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,38,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,0]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,340282366920938463463374607431768211458,6,1,1]}:[32768,1,1,6,1,0]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,340282366920938463463374607431768211458,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,9 68,1,127,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,6,32768,1,1,6,1,9223372036854775807]}:[3,1,6,32768,1,1,6,1,1]}:[3,1,10,32768,1,1,6,1,1]}");
+            fail("Failure expected");
+        } catch (JSONException ex) {
+            // expected
+            assertTrue(ex.getMessage().contains("Expected a key"));
+        }
+    }
+
+    public void testFuzzerTestCase2() throws Exception {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < 100000; i++) {
+            sb.append("{\"key\":");
+        }
+        try {
+            new JSONObject(sb.toString());
+            fail("Failure expected");
+        } catch (JSONException e) {
+            assertTrue(e.getMessage().contains("JSONTokener has reached recursion depth limit"));
+            // expected
+        }
+    }
+
+    public void testIssue58() throws JSONException {
+        Map<String, Object> map = new HashMap<>();
+        map.put("request", "{\"exclude\":[\".\",\"?\",\"+\",\"*\",\"|\",\"{\",\"}\",\"[\",\"]\",\"(\",\")\",\"\\\"\",\"\\\\\",\"#\",\"@\",\"&\",\"<\",\">\",\"~\"]}");
+        JSONObject jsonObject = new JSONObject(map);
+        JSONObject jsonObject1 = new JSONObject(jsonObject.toString());
+    }
 }


=====================================
src/test/java/org/codehaus/jettison/json/JSONTokenerTest.java
=====================================
@@ -0,0 +1,27 @@
+package org.codehaus.jettison.json;
+
+import java.math.BigDecimal;
+
+import junit.framework.TestCase;
+
+public class JSONTokenerTest extends TestCase {
+    
+    public void testDoublePrecision() throws Exception {
+        JSONTokener doubleTokener = new JSONTokener("9999999999999.9999");
+        Object nextValue = doubleTokener.nextValue();
+        assertEquals(Double.class, nextValue.getClass());
+        assertEquals(Double.valueOf("1.0E13"), nextValue);
+    }
+
+    public void testBigDecimalPrecision() throws Exception {
+        JSONTokener bigDecimalTokener = new JSONTokener("9999999999999.9999") {
+            {
+                this.useBigDecimal = true;
+            }
+        };
+        Object nextValue = bigDecimalTokener.nextValue();
+        assertEquals(BigDecimal.class, nextValue.getClass());
+        assertEquals(new BigDecimal("9999999999999.9999"), nextValue);
+    }
+
+}



View it on GitLab: https://salsa.debian.org/java-team/libjettison-java/-/compare/08a09461050f0277c2ea712db3cc0573bb673de9...cfeca30fadd009f9ff992eb61eaaa5f41e72483c

-- 
View it on GitLab: https://salsa.debian.org/java-team/libjettison-java/-/compare/08a09461050f0277c2ea712db3cc0573bb673de9...cfeca30fadd009f9ff992eb61eaaa5f41e72483c
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20221231/d618b991/attachment.htm>


More information about the pkg-java-commits mailing list