Merge branch '2.7'
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 7db8ee3..a964afa 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -54,6 +54,8 @@
 #307: JsonGenerationException: Split surrogate on writeRaw() input thrown for
   input of a certain size
  (reported by Mike N)
+#315: `OutOfMemoryError` when writing BigDecimal
+ (reported by gmethwin@github)
 
 2.7.6 (23-Jul-2016)
 
diff --git a/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java b/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
index 19bcfd6..d2d05f2 100644
--- a/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
+++ b/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.core.base;
 
 import java.io.*;
+import java.math.BigDecimal;
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.json.DupDetector;
@@ -41,6 +42,16 @@
     protected final static String WRITE_RAW = "write a raw (unencoded) value";
     protected final static String WRITE_STRING = "write a string";
 
+    /**
+     * This value is the limit of scale allowed for serializing {@link BigDecimal}
+     * in "plain" (non-engineering) notation; intent is to prevent asymmetric
+     * attack whereupon simple eng-notation with big scale is used to generate
+     * huge "plain" serialization. See [core#315] for details.
+     * 
+     * @since 2.7.7
+     */
+    protected final static int MAX_BIG_DECIMAL_SCALE = 9999;
+    
     /*
     /**********************************************************
     /* Configuration
@@ -426,6 +437,26 @@
         return new DefaultPrettyPrinter();
     }
 
+    /**
+     * Helper method used to serialize a {@link java.math.BigDecimal} as a String,
+     * for serialization, taking into account configuration settings
+     *
+     * @since 2.7.7
+     */
+    protected String _asString(BigDecimal value) throws IOException {
+        if (Feature.WRITE_BIGDECIMAL_AS_PLAIN.enabledIn(_features)) {
+            // 24-Aug-2016, tatu: [core#315] prevent possible DoS vector
+            int scale = value.scale();
+            if ((scale < -MAX_BIG_DECIMAL_SCALE) || (scale > MAX_BIG_DECIMAL_SCALE)) {
+                _reportError(String.format(
+"Attempt to write plain `java.math.BigDecimal` (see JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN) with illegal scale (%d): needs to be between [-%d, %d]",
+scale, MAX_BIG_DECIMAL_SCALE, MAX_BIG_DECIMAL_SCALE));
+            }
+            return value.toPlainString();
+        }
+        return value.toString();
+    }
+
     /*
     /**********************************************************
     /* UTF-8 related helper method(s)
diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
index 15ea15f..80559d4 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
@@ -938,14 +938,10 @@
         _verifyValueWrite(WRITE_NUMBER);
         if (value == null) {
             _writeNull();
-        } else if (_cfgNumbersAsStrings) {
-            String raw = Feature.WRITE_BIGDECIMAL_AS_PLAIN.enabledIn(_features)
-                    ? value.toPlainString() : value.toString();
-            _writeQuotedRaw(raw);
-        } else if (Feature.WRITE_BIGDECIMAL_AS_PLAIN.enabledIn(_features)) {
-            writeRaw(value.toPlainString());
+        } else  if (_cfgNumbersAsStrings) {
+            _writeQuotedRaw(_asString(value));
         } else {
-            writeRaw(value.toString());
+            writeRaw(_asString(value));
         }
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
index 74b47c5..180497a 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
@@ -719,13 +719,10 @@
         _verifyValueWrite(WRITE_NUMBER);
         if (value == null) {
             _writeNull();
-        } else if (_cfgNumbersAsStrings) {
-            String raw = isEnabled(Feature.WRITE_BIGDECIMAL_AS_PLAIN) ? value.toPlainString() : value.toString();
-            _writeQuotedRaw(raw);
-        } else if (isEnabled(Feature.WRITE_BIGDECIMAL_AS_PLAIN)) {
-            writeRaw(value.toPlainString());
+        } else  if (_cfgNumbersAsStrings) {
+            _writeQuotedRaw(_asString(value));
         } else {
-            writeRaw(value.toString());
+            writeRaw(_asString(value));
         }
     }
 
@@ -734,7 +731,7 @@
     {
         _verifyValueWrite(WRITE_NUMBER);
         if (_cfgNumbersAsStrings) {
-            _writeQuotedRaw(encodedValue);            
+            _writeQuotedRaw(encodedValue);
         } else {
             writeRaw(encodedValue);
         }
diff --git a/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java b/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java
index a04e5e6..20bdff4 100644
--- a/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java
+++ b/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java
@@ -131,7 +131,62 @@
         g.close();
         assertEquals(quote("100"), bos.toString("UTF-8"));
     }
-    
+
+    // [core#315]
+    public void testTooBigBigDecimal() throws Exception
+    {
+        JsonFactory f = new JsonFactory();
+        f.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
+
+        // 24-Aug-2016, tatu: Initial check limits scale to [-9999,+9999]
+        BigDecimal BIG = new BigDecimal("1E+9999");
+        BigDecimal TOO_BIG = new BigDecimal("1E+10000");
+        BigDecimal SMALL = new BigDecimal("1E-9999");
+        BigDecimal TOO_SMALL = new BigDecimal("1E-10000");
+
+        for (boolean useBytes : new boolean[] { false, true } ) {
+            for (boolean asString : new boolean[] { false, true } ) {
+                JsonGenerator g;
+                
+                if (useBytes) {
+                    g = f.createGenerator(new ByteArrayOutputStream());
+                } else {
+                    g = f.createGenerator(new StringWriter());
+                }
+                if (asString) {
+                    g.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
+                }
+
+                // first, ok cases:
+                g.writeStartArray();
+                g.writeNumber(BIG);
+                g.writeNumber(SMALL);
+                g.writeEndArray();
+                g.close();
+
+                // then invalid
+                for (BigDecimal input : new BigDecimal[] { TOO_BIG, TOO_SMALL }) {
+                    if (useBytes) {
+                        g = f.createGenerator(new ByteArrayOutputStream());
+                    } else {
+                        g = f.createGenerator(new StringWriter());
+                    }
+                    if (asString) {
+                        g.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
+                    }
+                    try {
+                        g.writeNumber(input);
+                        fail("Should not have written without exception: "+input);
+                    } catch (JsonGenerationException e) {
+                        verifyException(e, "Attempt to write plain `java.math.BigDecimal`");
+                        verifyException(e, "illegal scale");
+                    }
+                    g.close();
+                }
+            }
+        }
+    }
+
     private String _writeNumbers(JsonFactory f) throws IOException
     {
         StringWriter sw = new StringWriter();