Ошибка сегментации из-за копирования строки - PullRequest
0 голосов
/ 07 мая 2019

В приведенном ниже коде происходит сбой после выполнения цикла while в четвертый раз, и происходит сбой в strcpy

strcpy(userver_info[location].Tag_Name, field); 

При отладке выдает следующую ошибку

Can't find a source file at "strcpy-sse2-unaligned.S"

Я не могу выяснить, в чем заключается проблема, вызывающая сбой, после того, как я столкнулся с вышеуказанной проблемой, я сделал структурирование, думая, что это может быть проблемой, и даже если это не помогает, может кто-нибудь сказать мне, почему сбой кода.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define BUFFER_SIZE               1024
#define NUM_OF_UNDERLYING_SERVER  0


#define SHM_ADDR_LEN              15
#define SERVER_NAME_LEN           25
#define TAG_NAME_LEN              25
#define TAG_DESC_LEN              30
#define ACCESS_LEVEL_LEN          5
#define DATA_TYPE_NAME_LEN            10

typedef struct {
  char    SHM_Location[SHM_ADDR_LEN];
  char    Server_ID[SERVER_NAME_LEN];
  char    Tag_Name[TAG_NAME_LEN];
  int     Tag_ID;
  char    Tag_Description[TAG_DESC_LEN];
  char    Access_Level[ACCESS_LEVEL_LEN];
  char    Data_Type[DATA_TYPE_NAME_LEN];
}u_server_info;

typedef struct {
  int num_of_tags;
  u_server_info *underlying_server_data;
}opcua_u_server;



void parse_underlying_opcua_server(char * buffer, u_server_info *userver_info) {

  static int location = 0;
  char *field;
  /* get SHM_Location */
  field = strtok(buffer,",");
  strcpy(userver_info[location].SHM_Location, field);

  /* get Server_ID */
  field=strtok(NULL,",");
  strcpy(userver_info[location].Server_ID, field);

  /* get Tag_Name */
  field = strtok(NULL,",");
  strcpy(userver_info[location].Tag_Name, field);

  /* get Tag_ID */
  field=strtok(NULL,",");
  userver_info[location].Tag_ID = atoi(field);

  /* get Tag_Description */
  field = strtok(NULL,",");
  strcpy(userver_info[location].Tag_Description, field);

  /* get Access_Level */
  field = strtok(NULL,",");
  strcpy(userver_info[location].Access_Level, field);

  /* get Data_Type */
  field = strtok(NULL,",");
  strcpy(userver_info[location].Data_Type, field);

  /* display the result */
  printf("%s\t %s\t %s\t %d\t %s\t %s\t %s\n",
          userver_info[location].SHM_Location,
          userver_info[location].Server_ID,
          userver_info[location].Tag_Name,
          userver_info[location].Tag_ID,
          userver_info[location].Tag_Description,
          userver_info[location].Access_Level,
          userver_info[location].Data_Type);

  location++;
}


int get_line_count(char *filename) {

  FILE *fp;
  int line_count = 0;
  char c;
  fp = fopen(filename, "r");
  if (fp == NULL){
      printf("Unable to open file '%s' to count lines\n",filename);
      return -1;
  }
  for (c = getc(fp); c != EOF; c = getc(fp))
      if (c == '\n') // Increment count if this character is newline
          line_count = line_count + 1;
  fclose(fp);
  return line_count;
}

int main(int argc, char **argv)
{
  char filename[] = "underlying_server.csv";
  char buffer[BUFFER_SIZE];
  FILE *fp;
  int tags_count = 0;
  opcua_u_server *ua_server = NULL;

  /* open the CSV file */
  fp = fopen(filename,"r");
  if( fp == NULL) {
      printf("Unable to open file '%s'\n",filename);
      exit(EXIT_FAILURE);
  }

  tags_count = get_line_count(filename);
  /* Allocate memmory for each Underlying server */
  ua_server= malloc(sizeof(opcua_u_server));
  if (ua_server == NULL) {
      printf("Malloc failed");
      exit(EXIT_FAILURE);
  }
  /* Allocate memory for each underlying server tag information */
  ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data =
          malloc(tags_count * sizeof(ua_server->underlying_server_data));

  if (ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data == NULL) {
      printf("Malloc failed");
      exit(EXIT_FAILURE);
  }
  /* process the data */
  while(fgets(buffer,BUFFER_SIZE,fp)) {

      parse_underlying_opcua_server(buffer,
                      ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data);

  }
  ua_server->num_of_tags = tags_count;
  /*Reset the value for next server*/
  tags_count = 0;
  /* close file */
  fclose(fp);

  return(0);
}

Мой базовый_сервер.csv похож на это

1000,Server_1,Tag_1,3000,Created_tag_3000,AR,BOOL
1001,Server_1,Tag_2,3001,Created_tag_3001,AR,BOOL
1002,Server_1,Tag_3,3002,Created_tag_3002,AR,BOOL
1003,Server_1,Tag_4,3003,Created_tag_3003,AR,BOOL
1004,Server_1,Tag_5,3004,Created_tag_3004,AR,REAL
1005,Server_1,Tag_6,3005,Created_tag_3005,AR,REAL
1006,Server_1,Tag_7,3006,Created_tag_3006,AW,REAL
1007,Server_1,Tag_8,3007,Created_tag_3007,AW,REAL
1008,Server_1,Tag_9,3008,Created_tag_3008,AW,REAL
1009,Server_1,Tag_10,3009,Created_tag_3009,AW,REAL
1010,Server_1,Tag_11,3010,Created_tag_3010,AW,REAL
1011,Server_1,Tag_12,3011,Created_tag_3011,AW,DWORD
1012,Server_1,Tag_13,3012,Created_tag_3012,AW,DWORD
1013,Server_1,Tag_14,3013,Created_tag_3013,AR,DWORD
1014,Server_1,Tag_15,3014,Created_tag_3014,AR,DWORD
1015,Server_1,Tag_16,3015,Created_tag_3015,AR,DWORD
1016,Server_1,Tag_17,3016,Created_tag_3016,AR,DWORD
1017,Server_1,Tag_18,3017,Created_tag_3017,AR,DWORD
1018,Server_1,Tag_19,3018,Created_tag_3018,AR,DWORD
1019,Server_1,Tag_20,3019,Created_tag_3019,AR,DWORD
1020,Server_1,Tag_21,3020,Created_tag_3020,AR,DWORD
1021,Server_1,Tag_22,3021,Created_tag_3021,AW,BOOL
1022,Server_1,Tag_23,3022,Created_tag_3022,AW,BOOL
1023,Server_1,Tag_24,3023,Created_tag_3023,AW,BOOL
1024,Server_1,Tag_25,3024,Created_tag_3024,AW,BOOL
1025,Server_1,Tag_26,3025,Created_tag_3025,AW,BOOL
1026,Server_1,Tag_27,3026,Created_tag_3026,AW,DWORD
1027,Server_1,Tag_28,3027,Created_tag_3027,AR,DWORD
1028,Server_1,Tag_29,3028,Created_tag_3028,AR,DWORD
1029,Server_1,Tag_30,3029,Created_tag_3029,AR,DWORD
1030,Server_1,Tag_31,3030,Created_tag_3030,AR,REAL

Ответы [ 2 ]

5 голосов
/ 07 мая 2019

Я уверен, что для этого есть дубликат, вы выделяете второй буфер на основе размера указателя, а не объекта, на который указывает:

/* Allocate memory for each underlying server tag information */
ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data =
      malloc(tags_count * sizeof(ua_server->underlying_server_data));

становится:

/* Allocate memory for each underlying server tag information */
ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data =
      malloc(tags_count * sizeof(*(ua_server->underlying_server_data)));

Обратите внимание, что действительный код *(ua_server->underlying_server_data в данный момент плох, но sizeof находится во время компиляции и просто использует код в качестве шаблона для получения размера объекта.

Иногда мне хотелось бы, чтобы было предупреждение компилятора "Вы запросили размер указателя"

0 голосов
/ 07 мая 2019

Никогда не используйте strcpy, это небезопасно, потому что оно не выполняет никаких форм ограничения границ и будет просто копировать, пока не достигнет 0 байт в исходном буфере.Если исходный буфер не (должным образом) завершен 0, или содержимое исходного буфера слишком длинное, чтобы уместиться в место назначения, это создаст неопределенное поведение (аварийное завершение или уязвимость для атаки).

Оставляя в стороне проблему с полями фиксированного размера, абсолютно необходимо проверить пределы размера буферных операций.Стандартная функция, которую вы бы использовали (хотя она все еще не идеальна) - strncpy (обратите внимание на дополнительные n).Предостережение заключается в том, что strncpy пропустит завершающий байт 0, если он не вписывается в место назначения.

Поскольку ваши поля имеют фиксированный размер, вы можете использовать его следующим образом

strncpy(userver_info[location].SHM_Location, field, SHM_ADDR_LEN-1);
userver_info[location].SHM_Location[SHM_ADDR_LEN-1] = 0;

т.е. он копирует до SHM_ADDR_LEN-1 байтов и всегда помещает завершающий 0 в самый конец буфера.

...