как использовать два массива переменной длины в одной структуре в C - PullRequest
0 голосов
/ 24 октября 2011

У меня есть такая структура C:

 typedef struct ip_esp_private {         /* keep track of things privately */
    u_int32_t type;        
    u_int32_t ivlen;       
    u_int32_t icvlen;      
    u_int32_t keylen;       /* length of "Encryption key */
    u_int32_t akeylen;      /*length of authn key */
  //  u_int32_t key[0];       /* key itself */
  //  u_int32_t akey[0];      /*authn key itself */

    u_int32_t *key;       /* as suggested  */
    u_int32_t *akey;      /* as suggested */

 } esp_private;

Теперь проблема должна быть очевидна, когда я пытаюсь записать ключ, ключ будет перезаписан.

Я не уверен, как я могу его защитить ???

keylen и akeylen обеспечивают длину массива key и akey, и вся структура должна быть заполнена ввремя выполнения.

Пожалуйста, предоставьте несколько предложений.

РЕДАКТИРОВАТЬ:

  1. да ... u_int32_t является typedef, так что небеспокоиться об этом

  2. Я изменил массив нулевой длины на указатели, как отредактировано выше. Вот как мне нужно заполнить структуру ..

    case 'k':       /* Key */
            length = stringargument(arg, &temp);
            priv->keylen = length;
    
            priv->key=malloc(priv->keylen * sizeof(u_int32_t));
            /*as suggested added this step*/          
    
    
            /*as suggested commented this step*/
            priv = (esp_private *)realloc(priv,
                            sizeof(esp_private) + length);
    
    
    
            memcpy(priv->key, temp, priv->keylen);
            pack->private = priv;
            pack->modified |= ESP_MOD_KEY;
            break;
    
    case 'K':       /* Authentication  Key */       
            length = stringargument(arg, &temp);
            priv->akeylen = length;
    
            priv->akey=malloc(priv->akeylen * sizeof(u_int32_t));
            /*as suggested added this step*/
    
    
            /*as suggested commented this step*/
            priv = (esp_private *)realloc(priv,
                            sizeof(esp_private) + length);
    
    
    
            memcpy(priv->akey, temp, priv->akeylen);
            pack->private = priv;
            pack->modified |= ESP_MOD_AKEY;
    

, но не работает .. возможно, перераспределение не выполняется, пожалуйста, предложите также внести изменения.

РЕДАКТИРОВАТЬ 2:

Даже после комментированияrealloc как и предполагалось, это не сработало. key и akey должны были принимать значения, указанные в командной строке как arg, но они принимают некоторые случайные значения. Здесь все еще что-то не так, что требует внимания.

Пожалуйста, помогите мне, так как весь проект застрял из-за мелкой ошибки в этом маленьком пиКод кода. Нужен скоро ...

Ответы [ 4 ]

3 голосов
/ 24 октября 2011

Так почему бы вам не иметь key и akey в качестве указателей и malloc память для них при создании структуры esp_private?

 typedef struct ip_esp_private {  
    u_int32_t type;        
    u_int32_t ivlen;       
    u_int32_t icvlen;      
    u_int32_t keylen; 
    u_int32_t akeylen; 
    u_int32_t *key;  /* change */  
    u_int32_t *akey; /* change */
 } esp_private;

void esp_private_init(esp_private *ep, /* maybe some args here for type, ivlen, etc */
                     u_int32_t *key, u_int32_t keylen, u_int32_t *akey, u_int32_t akeylen)
{
   /* maybe set up type, ivlen, etc if neccesary */

   ep->keylen = keylen;
   ep->key = malloc(keylen * sizeof(u_int32_t));
   /* copy argument key into ep->key */

   ep->akeylen = akeylen;
   ep->akey = malloc(akeylen * sizeof(u_int32_t));
   /* copy argument akey into ep->akey */
}
3 голосов
/ 24 октября 2011

В принципе, вы не можете этого сделать.Смещение каждого члена структуры фиксируется во время компиляции, что означает, что вы не можете иметь более одного элемента, размер которого может варьироваться.

Кстати, это не массив переменной длины;это "struct hack" .Эта форма с использованием [0] строго недопустима в C;форма с [1] более или менее в порядке, но убедительно утверждается, что ее поведение не определено.

C99 добавляет «гибкие элементы массива» в качестве стандартной замены «struct hack».

Вы можете использовать один гибкий элемент массива для key и akey, отслеживая, где начинается каждый из них.Или вы можете объявить их как u_int32_t* указатели, а не как массивы - что, конечно, означает, что у вас больше возможностей для управления памятью.

Кстати, u_int32_t опечатка для uint32_t (определено в <stdint.h>)

1 голос
/ 24 октября 2011

Либо используйте динамический массив, либо используйте один массив переменной длины для хранения как key, так и akey.

0 голосов
/ 24 октября 2011

Почему бы вам просто не использовать обычные указатели вместо массивов из 0 (или 1) элементов для key и akey и выделять столько памяти, сколько необходимо?Например:

#include <assert.h>

// the rest of includes and other things can go here.

typedef struct ip_esp_private {         /* keep track of things privately */
    u_int32_t type;        
    u_int32_t ivlen;       
    u_int32_t icvlen;      
    u_int32_t keylen;       /* length of "Encryption key */
    u_int32_t akeylen;      /*length of authn key */
    u_int32_t* key;       /* key itself */
    u_int32_t* akey;      /*authn key itself */
 } esp_private;

esp_private* CreateStruct(u_int32_t KeyLength, u_int32_t AKeyLength)
{
  esp_private* p = malloc(sizeof(esp_private));
  if (p == NULL) return NULL;

  /* Allocate KeyLength and AKeyLength elements to p->key and p->akey */
  p->key = malloc(KeyLength * sizeof(u_int32_t));
  p->akey = malloc(AKeyLength * sizeof(u_int32_t));

  if ((p->key == NULL) || (p->akey == NULL))
  {
    if (p->key != NULL) free(p->key);
    if (p->akey != NULL) free(p->akey);
    free(p);
    p = NULL;
  }
  else
  {
    p->keylen = KeyLength;
    p->akeylen = AKeyLength;
  }

  return p;
}

void DestroyStruct(esp_private* p)
{
  assert(p != NULL);
  assert(p->key != NULL);
  assert(p->akey != NULL);
  free(p->key);
  free(p->akey);
  free(p);
}

int main(void)
{
    /* allocate a structure */
    esp_private* p = CreateStruct(5 /*KeyLength*/, 10 /*AKeyLength*/)
    assert(p != NULL);

    /* use the structure */
    p->key[0] = 0;
    p->key[4] = 0x44444444;
    p->akey[0] = 0;
    p->akey[9] = 0x99999999;

    /* deallocate the structure */
    DestroyStruct(p);
    return 0;
}
...