Sylwester Lachiewicz created THRIFT-6332:
--------------------------------------------

             Summary: Graphviz generator crashes on struct, typedef and nested 
container constants
                 Key: THRIFT-6332
                 URL: https://issues.apache.org/jira/browse/THRIFT-6332
             Project: Thrift
          Issue Type: Bug
          Components: Graphviz - Compiler
    Affects Versions: 0.22.0, 0.25.0, 0.24.0, 0.23.0
            Reporter: Sylwester Lachiewicz


{{--gen gv}} crashes on a constant whose declared type is a struct, a typedef, 
or a container nested in either. {{t_gv_generator::print_const_value}} casts 
the declared type to {{t_map*}}, {{t_list*}} or {{t_set*}} by the shape of the 
*value* without checking the type: a struct literal is a {{CV_MAP}} value, so 
the cast reads a {{t_map}} member out of a {{t_struct}} object, and a typedef 
of a container is a {{t_typedef}} object cast the same way. An integer or 
string under the wrong type survives because nothing dereferences the type; an 
enum identifier or a nested container does not.

Minimal reproducer, crashes on every run:
{code}
enum E { A = 1 }
struct S { 1: E e }
const S C = { "e": E.A }
{code}
{noformat}
$ thrift --gen gv repro.thrift
Segmentation fault: 11
{noformat}

Under AddressSanitizer (master at 43cd5e041, {{-fsanitize=address}}):
{noformat}
==1556==ERROR: AddressSanitizer: heap-buffer-overflow ...
READ of size 8 at 0x602000000c58 thread T0
    #0 t_gv_generator::print_const_value(t_type*, t_const_value*) 
t_gv_generator.cc:286
    #1 t_gv_generator::print_const_value(t_type*, t_const_value*) 
t_gv_generator.cc:263
    #2 t_gv_generator::generate_const(t_const*) t_gv_generator.cc:171
{noformat}
Line 263 is {{((t_map*)type)->get_val_type()}} with {{type}} a {{t_struct}}; 
line 286 then calls {{type->get_name()}} on the garbage pointer that returned.

Other shapes that report the same overflow at lines 261/263, or segfault at 286 
through the {{t_set*}} branch: a typedef of {{map<string, E>}} with an enum 
value, a typedef of {{list<E>}}, a struct constant holding a map, a struct 
constant holding a struct. Only a flat {{{ "x": 1 }}} survives.

In the shipped test suite, {{--gen gv}} on {{test/DebugProtoTest.thrift}} and 
{{test/EnumTest.thrift}} crashes, as do 
{{lib/go/test/ConstOptionalField.thrift}} and 
{{lib/go/test/StructKeyTest.thrift}}: 18 of 20 runs of the last one segfault, 
the rest print empty type names where the enum should be.

Fix: resolve the declared type with {{get_true_type()}} for the shape dispatch, 
and for a struct literal look each key up as a field name and print the value 
with the field's type. Over every {{.thrift}} file in the repository the fixed 
generator is sanitizer-clean, produces byte-identical output for the 154 files 
that did not crash, and generates the 5 that did.




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

Reply via email to