[ 
https://issues.apache.org/jira/browse/FLINK-40917?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18129654#comment-18129654
 ] 

Mika Naylor commented on FLINK-40917:
-------------------------------------

Hey [~raminqaf], just wanted to follow up on this issue and ask whether this is 
still being worked on?

> Deeply nested VARIANT values overflow the stack in toJson(), CAST to STRING 
> and the variant builder
> ---------------------------------------------------------------------------------------------------
>
>                 Key: FLINK-40917
>                 URL: https://issues.apache.org/jira/browse/FLINK-40917
>             Project: Flink
>          Issue Type: Bug
>          Components: API / Core
>            Reporter: Ramin Gharib
>            Assignee: Ramin Gharib
>            Priority: Major
>
> h3. Problem
> Code that walks a \{{VARIANT}} recurses once per nesting level, so a deeply 
> nested value overflows the thread stack. A \{{StackOverflowError}} is an 
> \{{Error}}, so handlers that catch \{{Exception}} miss it. 
> \{{ExceptionUtils.isJvmFatalError}} does not treat it as fatal either. The 
> task fails over and restarts on the same record, without a message that says 
> what went wrong.
> The limit depends on the stack size and on the JIT state. On a 1 MiB stack, 
> the default for task threads, about 2,000 levels overflow. Such a value takes 
> only about 20 KB, far below the 16 MiB size limit of a \{{VARIANT}}.
> h3. Affected code
> ||Recursive walker||Used by||
> |\{{JsonVariantFormatter}}|\{{Variant#toJson()}}, \{{Variant#toString()}}, 
> \{{JSON_STRING}}, \{{JSON_OBJECT}}, the \{{json}} and \{{raw}} formats|
> |\{{VariantCastUtils.renderNode}}|\{{CAST(v AS STRING)}} and printing results|
> |\{{BinaryVariantInternalBuilder.appendVariantImpl}}|the object and array 
> builders of the public \{{VariantBuilder}}, and the cast of an \{{ARRAY}}, 
> \{{MAP}} or \{{ROW}} to \{{VARIANT}}|
> FLINK-40826 catches the overflow in the cast to \{{VARIANT}}, which fails 
> with \{{Cannot cast a value of type ARRAY<VARIANT> to VARIANT because it is 
> nested too deeply.}}, and \{{TRY_CAST}} returns \{{NULL}}. That covers one 
> call site only. The other walkers still throw a bare \{{StackOverflowError}}.
> h3. Reproduce
> {code:java}
> // [[[...[1]...]]] with 20,000 levels, built without recursion
> BinaryVariantInternalBuilder builder = new 
> BinaryVariantInternalBuilder(false);
> builder.appendInt(1);
> for (int i = 0; i < 20_000; i++) {
>     builder.finishWritingArray(0, new ArrayList<>(List.of(0)));
> }
> BinaryVariant deep = builder.build();
> deep.toJson();                                  // StackOverflowError
> Variant.newBuilder().array().add(deep).build(); // StackOverflowError
> {code}
> In SQL, \{{JSON_STRING(v)}} and \{{CAST(v AS STRING)}} fail the same way for 
> such a value.
> h3. Where deep values come from
> {\{PARSE_JSON}}, \{{TRY_PARSE_JSON}} and the JSON format parse with Jackson, 
> which rejects JSON nested deeper than 1,000 levels by default. That is close 
> to the overflow limit, so the margin is thin. Other sources have no limit, 
> such as binary variants that a format reads as they are, and values that a 
> user function builds with \{{VariantBuilder}}.
> h3. Options
> # Make the walkers iterative, with an explicit stack. This removes the limit 
> and changes nothing for valid input. It needs the most code.
> # Enforce a maximum nesting depth wherever a variant is built or read, well 
> below the stack limit, so that deeper values fail with a clear error. This is 
> simple, but a limit below 1,000 would reject JSON that \{{PARSE_JSON}} 
> accepts today.
> # Catch \{{StackOverflowError}} at every call site, as the cast to 
> \{{VARIANT}} does. This is the least code, but it is fragile, and every new 
> walker has to remember it.
> Option 1 fits best. The three walkers sit in core and in the table runtime, 
> and every query that uses \{{VARIANT}} reaches them. Once they are iterative, 
> the catch in \{{ToVariantConverter#convert}} can go.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to