[SOLVED] free() causing (vPortFreeTagged)- assert failed!

aaquilina
Posts: 43
Joined: Fri Jan 20, 2017 3:10 pm

[SOLVED] free() causing (vPortFreeTagged)- assert failed!

Postby aaquilina » Fri Mar 03, 2017 12:56 pm

Hi,

Writing some code to serve a TCP and creating a character pointer to hold the received data. I then malloc the buffer, receive the data, decrypt it and try and free it. When I try to free I get the below error. As soon as I comment the free, the program works, but I'm pretty sure that with enough client requests, the esp will crash anyway. Any ideas what I'm doing wrong? I've tried various things, including avoiding malloc altogether, however, the netbuf_data instruction doesnt seem to work with a statically allocated array. This is the function that causes the esp to abort.

Code: Select all

static void networkTCPServe(struct netconn *conn)
{
	err_t err;
	struct netbuf *inbuf;
	u16_t buflen = 16;
	unsigned char plaintext[17];

	  /* Read the data from the port, blocking if nothing yet there.
	   We assume the request (the part we care about) is in one netbuf */

	err = netconn_recv(conn, &inbuf);

	if (err == ERR_OK)  
	{
		char* buf = malloc((size_t)buflen);
		netbuf_data(inbuf, (void**)&buf, &buflen);//16 byte for 128bit block size used in AES

		networkAES256CBCDecrypt(buf, buflen, plaintext);
		free(buf); //PROGRAM CRASHING
		serialEnqueue(plaintext, buflen);
	}
	else 
	{
		ESP_LOGE(TAG, "networkReceive: recv: %d %s", err, strerror(errno));
	}

	/* Close the connection (server closes in TCP) */
	netconn_close(conn);
	/* Delete the buffer (netconn_recv gives us ownership,
	so we have to make sure to deallocate the buffer) */
	netbuf_delete(inbuf);
}

Code: Select all

C:/SysGCC/esp32/esp32-bsp/esp-idf/components/freertos/heap_regions.c:368 (vPortF
reeTagged)- assert failed!
                                                    
Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception)
           
Register dump:
                                                                
PC      : 0x40009203  PS      : 0x00060136  A0      : 0x800d2be9  A1      : 0x3f
fd9dd0  
                                                                      
A2      : 0x0000006b  A3      : 0x0000006b  A4      : 0x00000010  A5      : 0xff
ffffff  
                                                                      
A6      : 0x00000000  A7      : 0xfffffff0  A8      : 0x00000000  A9      : 0x3f
fd9d40  
                                                                      
A10     : 0x00000000  A11     : 0x3f4048bf  A12     : 0x3ffd9d0f  A13     : 0x00
000038  
                                                                      
A14     : 0x00000000  A15     : 0x3ffd9d14  SAR     : 0x00000004  EXCCAUSE: 0x00
000001  
                                                                      
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00
000000  
                                                                      

                                                                               
                                                                                
 Backtrace: 0x40009203:0x3ffd9dd0 0x400d2be9:0x3ffd9df0 0x400d35b9:0x3ffd9e10 0x
4008202c:0x3ffd9e30 0x4000beca:0x3ffd9e50 0x400eb16b:0x3ffd9e70 0x400eb0f9:0x3ff
d9ed0
  
Last edited by aaquilina on Mon Mar 06, 2017 8:36 am, edited 1 time in total.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: free() causing (vPortFreeTagged)- assert failed!

Postby kolban » Fri Mar 03, 2017 1:48 pm

If I am understanding correctly, you are allocating 16 bytes on the heap and then copying data into that allocated storage ... you are then doing some un-described processing on it ... and then trying to release it. Is there any possibility that you are over-running the 16 bytes? It may be that free() checks storage before or after the allocated block to ensure that there has been no over-runs and asserting if there has been. A quick way to check would be test with an allocated size > 16 ... say 2000 and see if it then works. From there, it would become classic code debugging looking for the error.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

aaquilina
Posts: 43
Joined: Fri Jan 20, 2017 3:10 pm

Re: free() causing (vPortFreeTagged)- assert failed!

Postby aaquilina » Fri Mar 03, 2017 2:01 pm

Thanks for your suggestion, that didn't come to mind. I just tried it but I'm still getting the same error. The undescribed processing is that I populate it with whatever comes over the TCP socket and then read it so that I can decrypt it.

By the way, I wanted to thank you for your excellent videos on ESP development. They are really helpful!

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: free() causing (vPortFreeTagged)- assert failed!

Postby kolban » Fri Mar 03, 2017 6:20 pm

Is there any possibility that the data is freed() inside one of the calls? An attempt to free storage twice might also result in this kind of issue?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: free() causing (vPortFreeTagged)- assert failed!

Postby ESP_Angus » Mon Mar 06, 2017 7:13 am

free() is failing because the pointer you are freeing is not the pointer returned from malloc, it's something else!
aaquilina wrote:

Code: Select all

		netbuf_data(inbuf, (void**)&buf, &buflen);//16 byte for 128bit block size used in AES
  
netbuf_data() returns a reference to the data inside the netbuf. So it updates the second & third arguments to become a pointer to the data in the netbuf, and the length of data in the netbuf. The original values of these arguments are totally ignored.

So, before the netbuf_data call 'buf' is a pointer to 16 bytes of malloc()ed data, but afterwards it's a pointer to somewhere inside 'inbuf'.

An alternative is to use netbuf_copy:

Code: Select all

char* buf = malloc((size_t)buflen);
uint16_t received = netbuf_copy(inbuf, buf, buflen);//16 byte for 128bit block size used in AES
if (received < buflen) {
  // you may need to consider the possibility that not all 16 bytes were received yet, as this is a TCP socket
  // (unlikely for 16 bytes unless it's in the middle of a stream, but still possible)
}
Or you can still use netbuf_data(), in which case you don't need to malloc() anything and can use the pointer to inside the netbuf, saving some RAM and allocation overhead. However:
  • That data is only valid until you call netbuf_delete()
  • There's still the possibility that the data was split across multiple netbufs, as per the comment above.

aaquilina
Posts: 43
Joined: Fri Jan 20, 2017 3:10 pm

Re: free() causing (vPortFreeTagged)- assert failed!

Postby aaquilina » Mon Mar 06, 2017 8:36 am

Thanks! That was the problem. Using netbuf_copy now :) .

Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 114 guests