Valgrind给出错误,但一切似乎都很好

Udi*_*pta 2 c memory valgrind memory-management buffer-overflow

这个看起来像我以前的帖子的重复,但它不是.....

这里Valgrind发出以下错误:

 udit@udit-Dabba ~/mec $  valgrind --leak-check=full
 sendip -v -p ipv6 -f file.txt -6s ::1 -p esp -es 0x20 -eq 0x40
 -ei z30 -eI z100  -p tcp -ts 21 -td 21 ::2  

 ==4331== Memcheck, a memory error detector
 ==4331== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
 ==4331== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
 ==4331== Command: sendip -v -p ipv6 -f file.txt -6s ::1 -p esp -es 0x20
 -eq 0x40 -ei z30 -eI z100 -p tcp -ts 21 -td 21 ::2
==4331== 
esp
Added 43 options
Initializing module ipv6
Initializing module esp
Initializing module tcp
==4331== Invalid write of size 4
==4331==    at 0x4027EB8: memcpy (mc_replace_strmem.c:635)
==4331==    by 0x4032269: do_opt (esp.c:113)
==4331==    by 0x804A51D: main (sendip.c:575)
==4331==  Address 0x41ceab0 is 144 bytes inside a block of size 146 alloc'd
==4331==    at 0x402699A: realloc (vg_replace_malloc.c:525)
==4331==    by 0x4032231: do_opt (esp.c:111)
==4331==    by 0x804A51D: main (sendip.c:575)
==4331== 

valgrind: m_mallocfree.c:225 (mk_plain_bszB): Assertion 'bszB != 0' failed.
valgrind: This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata.  If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away.  Please try that before reporting this as a bug.

==4331==    at 0x380282BD: report_and_quit (m_libcassert.c:193)
==4331==    by 0x38028415: vgPlain_assert_fail (m_libcassert.c:267)
==4331==    by 0x380351E7: vgPlain_arena_malloc (m_mallocfree.c:225)
==4331==    by 0x380662C7: vgPlain_cli_malloc (replacemalloc_core.c:83)
==4331==    by 0x38001FA8: vgMemCheck_new_block (mc_malloc_wrappers.c:201)
==4331==    by 0x38002196: vgMemCheck_malloc (mc_malloc_wrappers.c:238)
==4331==    by 0x38068BF8: vgPlain_scheduler (scheduler.c:1394)
==4331==    by 0x3807A354: run_a_thread_NORETURN (syswrap-linux.c:94)

sched status:
running_tid=1

Thread 1: status = VgTs_Runnable
==4331==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
==4331==    by 0x4152415: gethostbyname2 (getXXbyYY.c:103)
==4331==    by 0x402CC68: set_addr (ipv6.c:33)
==4331==    by 0x804A642: main (sendip.c:594)


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.
Run Code Online (Sandbox Code Playgroud)

esp.c(第113号行)

  case 'eI':       /* ICV data (variable length) */
                   /* For right now, we will do either random generation
                   * or a user-provided string. We put it in the header,
                   * then move it into the trailer in finalize.
                   */
            length = stringargument(arg, &temp);
            priv->icvlen = length;
            pack->alloc_len += length;
            pack->data = realloc(esp, pack->alloc_len);
            esp = (esp_header *)pack->data;                                                                              
      113:      
            memcpy(&esp->tail.ivicv[priv->ivlen],temp, priv->icvlen);
            pack->modified |= ESP_MOD_ICV;
Run Code Online (Sandbox Code Playgroud)

这些是相应的头文件,我想这可能有助于调试......

ip6.h

/*
 * authentication header
*/
struct ip_auth_hdr {
    u_int8_t  nexthdr;
    u_int8_t  hdrlen;       /* This one is measured in 32 bit units! */
    u_int16_t reserved;
    u_int32_t spi;
    u_int32_t seq_no;       /* Sequence number */
    u_int8_t  auth_data[0]; /* Variable len but >=4. Mind the
                               64 bit alignment! */
 #define icv     auth_data       /* rfc 4302 name */
    /* TBD - high-order sequence number */

 };

/*
 * encapsulated security payload header
 */
 struct ip_esp_hdr {
    u_int32_t spi;
    u_int32_t seq_no;       /* Sequence number */
    u_int8_t  enc_data[0];  /* Variable len but >=8. Mind the
                             64 bit alignment! */
  };
Run Code Online (Sandbox Code Playgroud)

esp.h

 struct ip_esp_tail {
    u_int8_t padlen;        /* padding is pushed before tail */
    u_int8_t nexthdr;
    u_int32_t ivicv[0];     /* both IV and ICV, if any */
 };

 struct ip_esp_headtail {
    struct ip_esp_hdr hdr;
    struct ip_esp_tail tail;
  };

  typedef struct ip_esp_headtail esp_header;

  #define ESP_MIN_PADDING 4 

  typedef struct ip_esp_private { /* keep track of things privately */
    u_int32_t type;         /* type = IPPROTO_ESP */
    u_int32_t ivlen;        /* length of IV portion */
    u_int32_t icvlen;       /* length of ICV portion */
    u_int32_t keylen;       /* length of "key" (not transmitted data) */
    u_int32_t key[0];       /* key itself */
  } esp_private;

  struct ip_auth_hdr {
    u_int8_t  nexthdr;
    u_int8_t  hdrlen;       /* This one is measured in 32 bit units! */
    u_int16_t reserved;
    u_int32_t spi;
    u_int32_t seq_no;       /* Sequence number */
    u_int8_t  auth_data[0]; /* Variable len but >=4. Mind the
                               64 bit alignment! */
  #define icv     auth_data       /* rfc 4302 name */
    /* TBD - high-order sequence number */

  };

 /*
  * encapsulated security payload header
  */
  struct ip_esp_hdr {
    u_int32_t spi;
    u_int32_t seq_no;       /* Sequence number */
    u_int8_t  enc_data[0];  /* Variable len but >=8. Mind the
                            64 bit alignment! */  
  };
Run Code Online (Sandbox Code Playgroud)

如果有人得到任何线索泄漏在哪里?以及如何修补它?

And*_*org 14

正如克里斯所说,valgrind告诉你,你的程序正在尝试写入分配区域之外的内存:

Invalid write of size 4
   at 0x4027EB8: memcpy (mc_replace_strmem.c:635)
   by 0x4032269: do_opt (esp.c:113)
   by 0x804A51D: main (sendip.c:575)
 Address 0x41ceab0 is 144 bytes inside a block of size 146 alloc'd
   at 0x402699A: realloc (vg_replace_malloc.c:525)
   by 0x4032231: do_opt (esp.c:111)
   by 0x804A51D: main (sendip.c:575)
Run Code Online (Sandbox Code Playgroud)

它告诉你在do_opt中(在第111行的文件esp.c中)你已经调用了realloc来分配146个字节的内存,现在函数memcpy正在尝试从144字节开始执行一个4字节的写操作.内存块,它将导致写入分配区域之外(144 + 4> 146).它还告诉您memcpy是从do_opt函数调用的.

因此,要么分配给很少的内存,要么在复制到内存时使用错误的偏移量.因此,下一步是检查valgrind报告的位置中的代码.

但是,如果在查看代码时问题不明显怎么办?

一种选择是使用valgrind --db-attach option,它允许你输入gdb.这将允许你环顾四周并检查诸如天气包之类的东西 - > alloc_len是你期望的值,如果&esp->tail.ivicv[priv->ivlen]指向宫殿,你期望它与pack->数据进行比较.(这也可以通过添加printf打印这些值的经典方式来完成).

以下是我的猜测问题是什么,但如果您想先尝试自己解决问题,请隐藏:

也许你忘记了ivicv是一个uint32,你有priv-> ivlen以字节为单位.在这种情况下,改变它&esp->tail.ivicv[priv->ivlen / sizeof(u_int32_t)]会有所帮助

  • 哈哈,我不知道SO在答案中支持"破坏者" (4认同)