Search code examples
cserializationdeserializationprotocol-buffersprotoc

Improper deserialization of protocol message


I am trying out protocol buffer serialization & deserialization in C language. I created a learn.proto message as shown below and just tried to pack a message into a *uint8_t and unpack this.

syntax = "proto3";
package learn;

message learnmessage {

  enum LearnType {
        ZERO = 0;
        ONE = 1;
        TWO = 2;
        THREE = 3;
        FOUR = 4;
        FIVE = 5;
        SIX = 6;
    }
    LearnType typ = 1;
    string text = 2;
}

After unpacking, the enum values, always zero is obtained, no matter what I pack into the original message. But the text field values remain proper after deserialization. For example, I am packing enum LEARN__LEARNMESSAGE__LEARN_TYPE__THREE but after unpacking, it gets changed to LEARN__LEARNMESSAGE__LEARN_TYPE__ZERO

I compile it by gcc -o program mycode.c learn.pb-c.c -lprotobuf-c

Can someone help me figure out the mistake that I am doing:

#include <stdio.h>
#include <stdlib.h>
#include "learn.pb-c.h"


int main()
{
    Learn__Learnmessage msg = LEARN__LEARNMESSAGE__INIT, *msgCopy; 
    size_t len;
    uint8_t *msgStr;

    msg.typ = LEARN__LEARNMESSAGE__LEARN_TYPE__THREE; //corresponds to enum value 3
    msg.text = "again";

    len = learn__learnmessage__get_packed_size(&msg); //get the length of the uint8_t needed to pack the message
    msgStr = malloc(len * sizeof(uint8_t));

    learn__learnmessage__pack(&msg, msgStr); //packs the message into msgStr

    msgCopy = learn__learnmessage__unpack(NULL, len, msgStr); //unpack the message into msgCopy

    printf("Orginal: %d \n", msg.typ);  //prints 3 (expected)
    printf("Copy: %d \n", msgCopy->typ); //prints 0 (un-expected)


}

Solution

  • There is a field protobuf_c_boolean has_typ; in the generated C code. After setting it to 1, things started working as expected.

    So the code must actually be:

    msg.typ = LEARN__LEARNMESSAGE__LEARN_TYPE__THREE;
    msg.has_typ = 1;
    msg.text = "again";