{"record":{"id":"4ff7c6d30c1b8f2a","repo":"google/gson","slug":"failed-parsing-json-source-reader-to-json","errorCode":null,"errorMessage":"Failed parsing JSON source: ${reader} to Json","messagePattern":"Failed parsing JSON source: (.+?) to Json","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"critical","filePath":"gson/src/main/java/com/google/gson/JsonParser.java","lineNumber":146,"sourceCode":"   * Strictness#STRICT}, that strictness will be used for parsing. Otherwise the strictness will be\n   * temporarily changed to {@link Strictness#LENIENT} and will be restored once this method\n   * returns.\n   *\n   * @throws JsonParseException if there is an IOException or if the specified text is not valid\n   *     JSON\n   * @since 2.8.6\n   */\n  public static JsonElement parseReader(JsonReader reader)\n      throws JsonIOException, JsonSyntaxException {\n    Strictness strictness = reader.getStrictness();\n    if (strictness == Strictness.LEGACY_STRICT) {\n      // For backward compatibility change to LENIENT if reader has default strictness LEGACY_STRICT\n      reader.setStrictness(Strictness.LENIENT);\n    }\n    try {\n      return Streams.parse(reader);\n    } catch (StackOverflowError | OutOfMemoryError e) {\n      throw new JsonParseException(\"Failed parsing JSON source: \" + reader + \" to Json\", e);\n    } finally {\n      reader.setStrictness(strictness);\n    }\n  }\n\n  /**\n   * @deprecated Use {@link JsonParser#parseString}\n   */\n  @Deprecated\n  @InlineMe(replacement = \"JsonParser.parseString(json)\", imports = \"com.google.gson.JsonParser\")\n  public JsonElement parse(String json) throws JsonSyntaxException {\n    return parseString(json);\n  }\n\n  /**\n   * @deprecated Use {@link JsonParser#parseReader(Reader)}\n   */\n  @Deprecated","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/JsonParser.java#L128-L164","documentation":"Thrown as JsonParseException by JsonParser.parseReader(JsonReader) (JsonParser.java:146) when Streams.parse(reader) raises StackOverflowError or OutOfMemoryError; the VM error is caught and wrapped. It signals the input is pathologically deep (stack overflow) or too large for available heap (out of memory). This is a resource/DoS condition, not a JSON syntax error.","triggerScenarios":"Deeply nested arrays/objects causing StackOverflowError (e.g. tens of thousands of nested '['), or a payload so large that building the full JsonElement tree exhausts the heap (OutOfMemoryError).","commonSituations":"Untrusted/malicious input (a JSON nesting bomb such as '[[[[...]]]]'); very large log or metadata files parsed in one shot; recursive data structures serialized to deeply nested JSON; JVM launched with insufficient -Xss/-Xmx for the workload.","solutions":["Stream with JsonReader (event-based, constant-ish memory) instead of building a full JsonElement tree","Increase JVM stack (-Xss) and/or heap (-Xmx) if the payload is legitimately large","Reject oversized payloads and/or cap nesting depth before parsing (size + depth pre-check)","For untrusted input, pair streaming with an explicit depth counter and abort past a threshold"],"exampleFix":"// before: builds whole tree, can SOF/OOM\nJsonElement e = JsonParser.parseString(massiveOrDeepJson);\n\n// after: streaming parse with a depth guard\ntry (JsonReader r = new JsonReader(new StringReader(massiveOrDeepJson))) {\n    int depth = 0, maxDepth = 512;\n    while (r.peek() != JsonToken.END_DOCUMENT) {\n        JsonToken t = r.peek();\n        if (t == JsonToken.BEGIN_ARRAY || t == JsonToken.BEGIN_OBJECT) {\n            if (++depth > maxDepth) throw new IllegalStateException(\"nesting too deep\");\n            // begin as needed\n        } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {\n            depth--;\n        }\n        r.skipValue(); // or handle the token\n    }\n}","handlingStrategy":"validation","validationCode":"// reject oversized / over-deep input before parsing\nif (raw.length() > MAX_BYTES) throw new IllegalArgumentException(\"payload too large\");\n// enforce depth with a streaming reader (see exampleFix) instead of building a full tree","typeGuard":null,"tryCatchPattern":"try {\n    JsonElement e = JsonParser.parseString(raw);\n} catch (JsonParseException ex) {\n    if (ex.getMessage().startsWith(\"Failed parsing JSON source\")) {\n        // underlying cause was StackOverflowError or OutOfMemoryError\n    }\n}","preventionTips":["Stream with JsonReader for large or untrusted input rather than building a full tree","Cap input size and nesting depth at the trust boundary","Size the JVM (-Xss/-Xmx) to the workload","Treat deep nesting as a potential DoS vector"],"tags":["gson","json","memory","parsing","dos"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}