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

Sylwester Lachiewicz updated THRIFT-6337:
-----------------------------------------
    Description: 
Two typedefs that name each other, both declared before their target is known, 
are accepted by the parser and hang the compiler in 
[t_type::get_true_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/parse.cc#L29],
 which follows typedefs until it reaches a non-typedef and never does.

{code}
typedef B A
typedef A B
{code}
{noformat}
$ thrift --gen json repro.thrift
(runs until killed)
{noformat}

On the two-line file only {{--gen json}} hangs; {{cpp}}, {{java}}, {{py}}, 
{{html}} and {{netstd}} exit 0 because they never resolve an unused typedef. 
Once a struct field uses either name ({{struct S { 1: A a }}}), every generator 
tried hangs except {{html}}. {{typedef T T}} and {{typedef list<L> L}} behave 
the same. The parser only catches the case where the first name is already 
defined ({{Type "A" is already defined.}}); a forward reference goes through 
[t_typedef::get_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/t_typedef.cc#L28],
 which resolves lazily and has no cycle check. The Go front end on the same 
input reports the cycle.

Reproduced on master at 1ae43c8ae. Fixed by [PR 
#3925|https://github.com/apache/thrift/pull/3925] for 
[THRIFT-6333|https://issues.apache.org/jira/browse/THRIFT-6333], which resolves 
every type at the end of parsing and reports {{Type "A" refers to itself}}.

  was:
Two typedefs that name each other, both declared before their target is known, 
are accepted by the parser and hang the compiler in 
[t_type::get_true_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/parse.cc#L29],
 which follows typedefs until it reaches a non-typedef and never does.

{code}
typedef B A
typedef A B
{code}
{noformat}
$ thrift --gen json repro.thrift
(runs until killed)
{noformat}

Every generator is affected, since all of them call {{get_true_type()}}; a 
struct field using either name is enough to reach it and the two-line file 
above hangs even without one. The parser only catches the case where the first 
name is already defined ({{Type "A" is already defined.}}); a forward reference 
goes through 
[t_typedef::get_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/t_typedef.cc#L27],
 which resolves lazily and has no cycle check. The Go front end on the same 
input reports the cycle.

Reproduced on master at 3af0cfff1. Related: 
[THRIFT-6333|https://issues.apache.org/jira/browse/THRIFT-6333] resolves 
forward typedefs at the end of parsing, which is where the cycle can be 
detected.


> A typedef cycle makes the compiler loop forever instead of reporting an error
> -----------------------------------------------------------------------------
>
>                 Key: THRIFT-6337
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6337
>             Project: Thrift
>          Issue Type: Bug
>          Components: Compiler (General)
>    Affects Versions: 0.25.0
>            Reporter: Sylwester Lachiewicz
>            Priority: Major
>
> Two typedefs that name each other, both declared before their target is 
> known, are accepted by the parser and hang the compiler in 
> [t_type::get_true_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/parse.cc#L29],
>  which follows typedefs until it reaches a non-typedef and never does.
> {code}
> typedef B A
> typedef A B
> {code}
> {noformat}
> $ thrift --gen json repro.thrift
> (runs until killed)
> {noformat}
> On the two-line file only {{--gen json}} hangs; {{cpp}}, {{java}}, {{py}}, 
> {{html}} and {{netstd}} exit 0 because they never resolve an unused typedef. 
> Once a struct field uses either name ({{struct S { 1: A a }}}), every 
> generator tried hangs except {{html}}. {{typedef T T}} and {{typedef list<L> 
> L}} behave the same. The parser only catches the case where the first name is 
> already defined ({{Type "A" is already defined.}}); a forward reference goes 
> through 
> [t_typedef::get_type|https://github.com/apache/thrift/blob/master/compiler/cpp/src/thrift/parse/t_typedef.cc#L28],
>  which resolves lazily and has no cycle check. The Go front end on the same 
> input reports the cycle.
> Reproduced on master at 1ae43c8ae. Fixed by [PR 
> #3925|https://github.com/apache/thrift/pull/3925] for 
> [THRIFT-6333|https://issues.apache.org/jira/browse/THRIFT-6333], which 
> resolves every type at the end of parsing and reports {{Type "A" refers to 
> itself}}.



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

Reply via email to