# Vim bug report
We have found four potential **double free** vulnerablities and report them for you.

## Bug 1:
###Summary
in the file: src/netbeans.c:684:6
The function `nb_get_buf` is not secure.
```
    static nbbuf_T *
nb_get_buf(int bufno)
{
    // find or create a buffer with the given number
    int incr;

    if (bufno <= 0)
	return NULL;

    if (!buf_list)
    {
	// initialize
	buf_list = alloc_clear(100 * sizeof(nbbuf_T));
	buf_list_size = 100;
    }
    if (bufno >= buf_list_used) // new
    {
	if (bufno >= buf_list_size) // grow list
	{
677:	    nbbuf_T *t_buf_list = buf_list;

679:	    incr = bufno - buf_list_size + 90;
680:	    buf_list_size += incr;
681:	    buf_list = vim_realloc(buf_list, buf_list_size * sizeof(nbbuf_T));
	    if (buf_list == NULL)
	    {
684:		vim_free(t_buf_list);
		buf_list_size = 0;
		return NULL;
	    }
```
In line 681, we call a `realloc` function with new size`buf_list_size * sizeof(nbbuf_T)`.

The new size can be changed by parameter `bufno`, and if we overflow it to `0x0`, `realloc` will **free** the memory chunk pointed by `buf_list` and reutrn **NULL**.

Then run the line 684, and **free** the same memory chunk again!

###Here is my prove
>In 32 bit system,using Glibc.

If we pass `bufno=0x3fffffa6` to function `nb_get_buf`, it will pass all checks and go to line 679.

In line 679:`incr =0x3fffffa6 -100 + 90 = 0x3fffff9c `
In line 680: `buf_list_size = 0x3fffff9c + 100 = 0x40000000`
In line 681: `sizeof(nbbuf_T) = 0x24`, `new size =buf_list_size * sizeof(nbbuf_T) = 0x900000000`

In glibc, 
```
void *
__libc_realloc (void *oldmem, size_t bytes)
```
`size_t` is defined as `unsigned long` which is 32 bits here.

And if we call `realloc` with `new size = 0x900000000`, the size will be cast to `0x0`.

It will cause double free at line 684!

**I have write a demo to verify it:**
```
#include<stdio.h>
#include<stdlib.h>
typedef unsigned short	short_u;
struct nbbuf_struct
{
    unsigned int	*bufp;
    unsigned int	 fireChanges:1;
    unsigned int	 initDone:1;
    unsigned int	 insertDone:1;
    unsigned int	 modified:1;
    int			 nbbuf_number;
    char		*displayname;
    int			*signmap;
    short_u		 signmaplen;
    short_u		 signmapused;
};

typedef struct nbbuf_struct nbbuf_T;
int main()
{
	int bufno=0x3fffffa6;

	int incr;

    	if (bufno <= 0)
		return NULL;
	char * buf_list = malloc(100 * sizeof(nbbuf_T));
	int buf_list_size = 100;

	char *t_buf_list = buf_list;

	incr = bufno - buf_list_size + 90;
	buf_list_size += incr;
	unsigned long new_size = buf_list_size * sizeof(nbbuf_T);
	printf("new size:0x%x",new_size);
	buf_list = realloc(buf_list, buf_list_size * sizeof(nbbuf_T));
	if (buf_list == NULL)
	{
		free(t_buf_list);
		buf_list_size = 0;
		return NULL;
	}
}
```
![](https://yunlongs-1253041399.cos.ap-chengdu.myqcloud.com/image/Similary_Detection/162.png)

### How to fix
Check the size that passed to realloc cannot be zero.


## Bug 2-4:
>I also found 3 bugs same to bug 1. I am not sure these can be exploited,but it is better to fix them to avoid possible attack.

In the file :src/netbeans.c:3264:5
```
    static void
addsigntype(
    nbbuf_T	*buf,
    int		typeNum,
    char_u	*typeName,
    char_u	*tooltip UNUSED,
    char_u	*glyphFile,
    char_u	*fg,
    char_u	*bg)
{
        ....
            int *t_signmap = buf->signmap;
	    buf->signmaplen *= 2;
	    incr = buf->signmaplen - oldlen;
	    buf->signmap = vim_realloc(buf->signmap,
					       buf->signmaplen * sizeof(int));
	    if (buf->signmap == NULL)
	    {
3264:		vim_free(t_signmap);
		buf->signmaplen = 0;
		return;
	    }
```

in the file: src/netbeans.c:3227:5

```
		char **t_globalsignmap = globalsignmap;

		globalsignmaplen *= 2;
		incr = globalsignmaplen - oldlen;
		globalsignmap = vim_realloc(globalsignmap,
					   globalsignmaplen * sizeof(char *));
		if (globalsignmap == NULL)
		{
3227:		    vim_free(t_globalsignmap);
		    globalsignmaplen = 0;
		    return;
		}
```

in the file :src/normal.c:3695:6	
```
	newbuf = vim_realloc(buf, STRLEN(buf) + STRLEN(p) + 1);
	if (newbuf == NULL)
	{
3695:	    vim_free(buf);
	    vim_free(p);
	    return;
	}
```