title: How to parse asn.1 choice with openssl c api
body: <p>I am using c api of OpenSSL 1.1.1g to process asn.1 data, but d2i_type function cannot convert binary choice data to a structure, this is the definition of structure</p>
  <pre><code>typedef struct Obj_s {
    ASN1_PRINTABLESTRING *type;
    ASN1_OCTET_STRING *value;
  } Obj_t;
  
  DECLARE_ASN1_FUNCTIONS(Obj_t)
  DEFINE_STACK_OF(Obj_t)
  
  typedef struct Choice_s {
    int type;
    union {
      STACK_OF(ASN1_OCTET_STRING) *string;
      STACK_OF(Obj_t) *obj;
    } d;
  } Choice_t;
  
  DECLARE_ASN1_FUNCTIONS(Choice_t)
  </code></pre>
  <p>and implementation</p>
  <pre><code>ASN1_SEQUENCE(Obj_t) = {
      ASN1_SIMPLE(Obj_t, type, ASN1_PRINTABLESTRING),
      ASN1_SIMPLE(Obj_t, value, ASN1_OCTET_STRING)
  }ASN1_SEQUENCE_END(Obj_t)
  
  IMPLEMENT_ASN1_FUNCTIONS(Obj_t)
  
  ASN1_CHOICE(Choice_t) = {
      ASN1_SEQUENCE_OF(Choice_t, d.string, ASN1_OCTET_STRING),
      ASN1_SEQUENCE_OF(Choice_t, d.obj, Obj_t)
  }ASN1_CHOICE_END(Choice_t)
  
  IMPLEMENT_ASN1_FUNCTIONS(Choice_t)
  </code></pre>
  <p>I wrote some test code</p>
  <pre><code>Choice_t *choice = Choice_t_new();
  
  int stack_count = 0;
  int test_switch; //0 or 1
  switch(test_switch) {
      case 0: {
          choice-&gt;type = 0;
          choice-&gt;d.string = (STACK_OF(ASN1_OCTET_STRING) *) sk_ASN1_STRING_new_null();
          ASN1_STRING *string = ASN1_STRING_new();
          ASN1_STRING_set(string, /*some string*/, /*length of string*/);
          stack_count = sk_ASN1_STRING_push((STACK_OF(ASN1_STRING) *) choice-&gt;d.string, string); // count 1
          stack_count = sk_ASN1_STRING_push((STACK_OF(ASN1_STRING) *) choice-&gt;d.string, string); // count 2
          break;
      }
      case 1: {
          choice-&gt;type = 1;
          choice-&gt;d.obj = sk_Obj_t_new_null();
          
          Obj_t *obj = Obj_t_new();
          ASN1_STRING_set((ASN1_STRING *)obj-&gt;type, /*some string*/, /*length of string*/);
          ASN1_STRING_set((ASN1_STRING *)obj-&gt;value, /*some value*/, /*length of value*/);
          stack_count = sk_Obj_t_push(choice-&gt;d.obj, obj); // count 1
          stack_count = sk_Obj_t_push(choice-&gt;d.obj, obj); // count 2
          break;
      }
      default:return;
  }
  
  int write_choice_len = i2d_Choice_t(choice, nullptr);
  std::vector&lt;unsigned char&gt; write_choice_buf(write_choice_len + 1, 0);
  unsigned char *p_write_choice_buf = &amp;write_choice_buf[0];
  write_choice_len = i2d_Choice_t(choice, &amp;p_write_choice_buf);
  write_choice_buf.resize(write_choice_len);
  Utility::WriteFile(&quot;file name&quot;, &quot;wb+&quot;, &amp;write_choice_buf[0], write_choice_len);
  
  std::vector&lt;unsigned char&gt; read_choice_buf(Utility::ReadFile(&quot;file name&quot;, &quot;rb+&quot;));
  const unsigned char *p_read_choice_buf = &amp;read_choice_buf[0];
  Choice_t *test_choice = d2i_Choice_t(nullptr, &amp;p_read_choice_buf, (long)read_choice_buf.size());
  </code></pre>
  <p>When test_switch = 0, everything is ok, but when test_switch = 1, d2i_choice_t return null. What's wrong with me?</p>
  <p>When I change the order of the union members, I find that when type=1, the d2i_type function always returns null</p>