簡體   English   中英

Valgrind:在strcpy上寫入大小為1的無效

[英]Valgrind: Invalid write of size 1 on a strcpy

代碼試圖將大型uint8_t數組序列化為二進制字符流。 我應該在緩沖區中有足夠的空間來復制這些數據; 為什么我會收到這些錯誤? 發布是一個完整的可運行代碼,輸出錯誤。 使用的valgrind命令是:

valgrind --leak-check=yes --track-origins=yes ./prog

主要:

#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include <unistd.h>

#define MAX_FRAME_SIZE 9236
#define DAT_LEN 8202

void create_bit_stream(uint8_t frame[], size_t frame_size, char *frame_bits)
{
  /*
   * Takes in uint8_t array of data and converts to binary stream of characters
   * frame        : input array of uint8_t type data
   * frame_size   : size_t length of frame --> sizeof(frame)/sizeof(frame[0])
   * frame_bits   : pointer for returning the character string
   *
   * RETURNS string of binary values generated from input array
  */

  uint8_t tmp[frame_size];
  memset(tmp,0,frame_size);
  memcpy(tmp,frame,frame_size);
  // char bit_string[frame_size*8+1];
  char *bit_string = malloc(frame_size*8+1);
  memset(bit_string,'\0',frame_size*8 + 1);
  for (int i = 0; i < frame_size; i++)
  {
    for (int j = 0; j < 8; j++)
    {
      bit_string[i*8+j] = '0' + (tmp[i] >> 7);
      tmp[i] <<= 1;
    }
  }
  bit_string[frame_size*8] = '\0';
  strcpy(frame_bits, bit_string);
  free(bit_string);
  return;

}

int main(int argc, char *argv[])
{

 char *frame_bits = malloc(MAX_FRAME_SIZE + 1);
 if(!frame_bits)
 {exit(EXIT_FAILURE);}
 memset(frame_bits,'\0',MAX_FRAME_SIZE + 1);

 uint8_t *DAT_frame = malloc(DAT_LEN);
 if(!DAT_frame)
 {exit(EXIT_FAILURE);}
 memset(DAT_frame,0,DAT_LEN);

 //fill with arbitrary data
 for(int i = 0; i < DAT_LEN; i++)
 {
   DAT_frame[i] = i % 255;
 }

 create_bit_stream(DAT_frame, DAT_LEN, frame_bits);

 free(frame_bits); free(DAT_frame);
 return 0;
}

錯誤:

==2994== Invalid write of size 1
==2994==    at 0x4C31060: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2994==    by 0x40088B: create_bit_stream (stack.c:36)
==2994==    by 0x400993: main (stack.c:61)
==2994==  Address 0x5205455 is 0 bytes after a block of size 9,237 alloc'd
==2994==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2994==    by 0x4008CE: main (stack.c:45)
==2994== 
==2994== Source and destination overlap in strcpy(0x5203040, 0x52074f0)
==2994==    at 0x4C310E6: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2994==    by 0x40088B: create_bit_stream (stack.c:36)
==2994==    by 0x400993: main (stack.c:61)

您的create_bit_stream采用字節流並將其擴展為ASCII編碼位流。 也就是說,如果你輸入字節0x42('B'),它將產生字符串01000010 ”,這是9個字節長(計算終止nul)。 您為frame_bits分配空間時忘了考慮這frame_bits - 不是在create_bit_stream ,而是在main

char *frame_bits = (char *)malloc((MAX_FRAME_SIZE + 1)*sizeof(char));

應該讀

char *frame_bits = malloc(MAX_FRAME_SIZE * 8 + 1);

不要轉換malloc的結果。

(正如我在問題的評論中所指出的, sizeof(char) == 1sizeof(uint8_t) == 1 的定義 ;顯式寫入既是冗余的又是代碼異味。)

(像這樣的API,調用者提供一個被調用者寫入的可變長度緩沖區,應該總是傳遞輸出緩沖區的大小。你的設計是危險的,因為getssprintf是危險的。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM