kpumuk commented on PR #3414:
URL: https://github.com/apache/thrift/pull/3414#issuecomment-4340407178

   The remaining issue is that unknown union variants are swallowed in more 
places than optional user-struct fields.
   
   `render_struct_sync_read` is shared by normal structs, generated RPC args 
structs, and generated RPC result structs. The new branch catches 
`UnknownUnionVariant` unconditionally and leaves the field temp as `None`. That 
is correct for an optional user-struct field, but not for required fields or 
RPC wrapper fields.
   
   Minimal IDL:
   
   ```thrift
   union Response {
     1: i32 known
   }
   
   service Svc {
     Response get()
   }
   ```
   
   For a newer server response containing an unknown `Response` variant, the 
generated result reader leaves `result_value` unset. Then 
`SvcGetResult::ok_or()` reports:
   
   ```text
   ApplicationErrorKind::MissingResult
   ```
   
   That hides the real protocol/schema mismatch. Required union args/fields 
have the same shape: the union read error is converted into a later 
missing-field error.
   
   Regression test template, placed inside the generated module or adapted into 
an integration test:
   
   ```rust
   #[test]
   fn unknown_union_variant_in_rpc_result_is_not_missing_result() {
       use std::io::Cursor;
   
       use thrift::protocol::{
           TBinaryInputProtocol, TBinaryOutputProtocol, TFieldIdentifier, 
TOutputProtocol,
           TSerializable, TStructIdentifier, TType,
       };
   
       let mut write_buf = Vec::new();
       {
           let cursor = Cursor::new(&mut write_buf);
           let mut prot = TBinaryOutputProtocol::new(cursor, false);
   
           
prot.write_struct_begin(&TStructIdentifier::new("SvcGetResult")).unwrap();
           prot.write_field_begin(&TFieldIdentifier::new("result_value", 
TType::Struct, 0)).unwrap();
   
           
prot.write_struct_begin(&TStructIdentifier::new("Response")).unwrap();
           prot.write_field_begin(&TFieldIdentifier::new("future_variant", 
TType::I32, 99)).unwrap();
           prot.write_i32(7).unwrap();
           prot.write_field_end().unwrap();
           prot.write_field_stop().unwrap();
           prot.write_struct_end().unwrap();
   
           prot.write_field_end().unwrap();
           prot.write_field_stop().unwrap();
           prot.write_struct_end().unwrap();
       }
   
       let read_cursor = Cursor::new(write_buf);
       let mut rprot = TBinaryInputProtocol::new(read_cursor, false);
   
       let result = SvcGetResult::read_from_in_protocol(&mut rprot).unwrap();
       let err = result
           .ok_or()
           .expect_err("unknown success union variant should not become 
MissingResult");
   
       assert!(matches!(
           err,
           thrift::Error::Protocol(ref e)
               if e.kind == thrift::ProtocolErrorKind::UnknownUnionVariant
       ));
   }
   ```
   
   The fix should only suppress `UnknownUnionVariant` where treating the field 
as absent is actually intended, e.g. optional regular struct fields. For 
required fields and RPC args/result structs, the original union error should 
propagate.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to