[ 
https://issues.apache.org/jira/browse/THRIFT-6164?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jens Geyer resolved THRIFT-6164.
--------------------------------
      Assignee: Jens Geyer
    Resolution: Fixed

> Erlang: bound the depth thrift_protocol:skip/2 will follow
> ----------------------------------------------------------
>
>                 Key: THRIFT-6164
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6164
>             Project: Thrift
>          Issue Type: Bug
>          Components: Erlang - Library
>            Reporter: Jens Geyer
>            Assignee: Jens Geyer
>            Priority: Major
>             Fix For: 0.25.0
>
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> h3. Problem
> {{thrift_protocol:skip/2}} walks type ids taken off the wire rather than the 
> types the IDL
> declared, so the peer chooses both the shape of the nesting and how deep it 
> goes. {{skip/2}}
> and the four skip loops -- {{skip_struct_loop}}, {{skip_map_loop}}, 
> {{skip_set_loop}},
> {{skip_list_loop}} -- call one another with nothing carrying a depth.
> A struct level costs the sender three bytes. 200 levels of nesting is 801 
> bytes on the wire.
> h3. Change
> {{skip/2}} seeds {{DEFAULT_RECURSION_DEPTH}}, 64 -- the same value {{lib/py}} 
> and {{lib/cpp}}
> already use -- and each level of nesting spends one. {{skip/3}} is exported 
> so a caller who
> knows what its own schema can contain can ask for a lower ceiling. Exceeding 
> the ceiling raises
> {code}
> error({protocol_error, max_skip_depth_exceeded})
> {code}
> matching the binding's existing {{negative_size}} idiom.
> h3. Two things the fix deliberately does not do
> * *No guard on the typed read path.* {{read/2}}'s {{struct}}, {{list}}, 
> {{map}} and {{set}}
> clauses recurse on a type taken from the generated {{struct_info}}, never 
> from the wire, so
> their depth is fixed by the IDL and a peer cannot drive it. That is why the 
> allowance starts
> fresh at {{skip/2}} instead of being threaded down from the reader.
> * *No charge for element counts.* The three container loops recurse once per 
> element in tail
> position, which costs no stack. Charging them there would refuse large flat 
> containers while
> leaving the dimension that does consume stack wide open.
> h3. Tests
> Seven, over a memory buffer: one per container type, one pinning the wire 
> cost of 200 struct
> levels at 801 bytes, one checking ordinary nesting still skips, and one 
> checking an explicit
> ceiling passed to {{skip/3}} is honoured. Five fail against the unmodified 
> library.
> _Drafted with AI assistance (Claude Opus 5); filed by Jens Geyer._



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

Reply via email to