Duskre
Duskre

Reputation: 1

Setting the size of an array inside a struct with a value of another value within the same struct, in C

    struct {
        uint16 msg_length;
        uint8 msg_type;
        ProtocolVersion version;
        uint16 cipher_spec_length;
        uint16 session_id_length;
        uint16 challenge_length;
        V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
        opaque session_id[V2ClientHello.session_id_length];
        opaque challenge[V2ClientHello.challenge_length;
    } V2ClientHello;

Is it possible to do something similar to the above (https://www.rfc-editor.org/rfc/rfc5246)? If so how do I go about coding this inside C?

To be more specific this line in the struct:

V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];


Uses:
> V2ClientHello.cipher_spec_length
Which is defined in the same struct, to set the length of the array.

Upvotes: 0

Views: 87

Answers (4)

Kapil
Kapil

Reputation: 31

Value of "V2ClientHello.cipher_spec_length" is not available at compile time. You can not specify the size of an array at run time, instead use:

V2CipherSpec *cipher_specs;

in struct and use malloc or calloc to allocate a block of memory at run time.

V2ClientHello.cipher_specs = (V2CipherSpec *)malloc(V2ClientHello.cipher_spec_length);

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249123

Absolutely not. C does not have dynamic-size arrays. Instead, we can rely on tricks like this:

struct {
    uint16 msg_length;
    uint8 msg_type;
    ProtocolVersion version;
    uint16 cipher_spec_length;
    uint16 session_id_length;
    uint16 challenge_length;
    char extra[0]; // or 1 if your compiler hates this
} V2ClientHello;

Then, do not create instances of this struct directly, but rather via malloc():

struct V2ClientHello* hello = malloc(sizeof(V2ClientHello) + 
    len1*sizeof(V2CipherSpec) + len2 + len3);

Now you have a dynamically-allocated structure of the size you need. You can make accessor functions to get the "extra" fields:

V2CipherSpec* get_spec(V2ClientHello* hello, int idx) {
    assert(idx < hello->cipher_spec_length);
    return ((V2CipherSpec*)&hello->extra)[idx];
}

And of course you can wrap up the malloc() call inside a create routine which takes the sizes of all three dynamic parts and does everything in one place for robustness.

Upvotes: 3

thumbmunkeys
thumbmunkeys

Reputation: 20764

The shown code from the RFC is pseudo code, you can not implement it as shown.

You need to allocate these arrays manually depending on V2ClientHello.cipher_spec_length and the other length specification fields, once their values are known.

Upvotes: 0

Sourav Ghosh
Sourav Ghosh

Reputation: 134286

C does not support dynamic-sized arrays. To achieve your goal, you can use a pointer of type V2CipherSpec as structure variable and allocate memory at a later stage using the V2ClientHello.cipher_spec_length value.

Upvotes: 4

Related Questions