In libming 0.4.8, the parseSWF_DEFINELOSSLESS2 function in util/parser.c lacks a boundary check that would lead to denial-of-service attacks via a crafted SWF file.
version: master(commit [04aee52](https://github.com/libming/libming/commit/04aee52363688426eab74f5d6180c149654a6473) )
command: listswf $FILE
```
root:/path_to_libming/build/bin# ./listswf poc
==26225==WARNING: AddressSanitizer failed to allocate 0xfffffffffffffff9 bytes
==26225==AddressSanitizer's allocator is terminating the process instead of returning 0
==26225==If you don't like this behavior set allocator_may_return_null=1
==26225==AddressSanitizer CHECK failed: /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225 "((0)) != (0)" (0x0, 0x0)
    #0 0x4e3385 in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_rtl.cc:69
    #1 0x500c45 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc:79
    #2 0x4e9786 in __sanitizer::ReportAllocatorCannotReturnNull() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225
    #3 0x4e97c6 in __sanitizer::ReturnNullOrDieOnFailure::OnBadRequest() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:241
    #4 0x41f676 in __asan::asan_malloc(unsigned long, __sanitizer::BufferedStackTrace*) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_allocator.cc:856
    #5 0x4da20b in malloc /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:89
    #6 0x5b7e7e in readBytes /path_to_libming/util/read.c:252:17
    #7 0x59b963 in parseSWF_DEFINELOSSLESS2 /path_to_libming/util/parser.c:2168:38
    #8 0x546cf9 in blockParse /path_to_libming/util/blocktypes.c:145:14
    #9 0x53bc13 in readMovie /path_to_libming/util/main.c:269:11
    #10 0x53a0d6 in main /path_to_libming/util/main.c:354:2
    #11 0x7fce52d93bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310
    #12 0x41a2f9 in _start (/path_to_libming/build/bin/listswf+0x41a2f9)
```
The cause of this bug is the lack of boundary checks. Specifically, in the `parseSWF_DEFINELOSSLESS2` function, the size of `end` and `fileOffset` is not compared when `readBytes` is called. As a result, `end-fileOffset` may be a negative integer, which eventually leads to allocation failure.

The detailed call chain analysis is as follows. 
Download [poc](https://github.com/dandanxu96/PoC/blob/7cbf5b7f7b62e4a95725a226b29cae362b425ec8/libming/parseSWF_DEFINELOSSLESS2-readBytes-malloc-failure-poc)
```C
static void readMovie(FILE *f)
{
	int block, type, length, nextFrame=0;
	SWF_Parserstruct *blockp;
	for (;;)
	{
		if(filelen_check_fails(2))
			break;
                // Read 16 bits from the input file, the block is controlled by the attacker
		block = readUInt16 (f);
		type = block >> 6;
                
                 // length = block & 0x3f, which means length<=3f
		length = block & ((1 << 6) - 1);
		if (length == 63)		/* it's a long block. */ 
		{
			if(filelen_check_fails(4))
				break;
			unsigned long real_length = readUInt32 (f);

                        if (real_length > INT_MAX) {
		            SWF_warn(" Could not process long block with length %lu:"
                                     " blocks with length > %d not supported on this system\n",
                                     real_length, INT_MAX);
                            continue;
                        } else {
                            length = (int) real_length;
                        }
		}
		nextFrame = fileOffset+length;
		
		if(filelen_check_fails(length))
			break;
		blockp= blockParse(f, length, type);
                ......
	}
	......
}


SWF_Parserstruct *
blockParse (FILE *f, int length, SWFBlocktype header)
{
  int i;

  for (i = 0; i < numBlocks; i++)
  {
    // Select the corresponding parser to parse
    if (blocks[i].type == header)
    {
      return blocks[i].parser(f,length);
    }
  }
  return parseSWF_UNKNOWNBLOCK(f, length);
}


SWF_Parserstruct *
parseSWF_DEFINELOSSLESS2 (FILE * f, int length)
{
  int end = fileOffset + length;
  PAR_BEGIN (SWF_DEFINELOSSLESS2);

  parserrec->CharacterID = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
  parserrec->BitmapFormat = readUInt8 (f); // Read 8 bits from the input file, and fileOffset = fileOffset+1
  parserrec->BitmapWidth = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
  parserrec->BitmapHeight = readUInt16 (f); Read 16 bits from the input file, and fileOffset = fileOffset+2
  if( parserrec->BitmapFormat == 3 /* 8-bit */ ) {
      parserrec->BitmapColorTableSize = readUInt8 (f);
  }
  // When length=0, at this moment end=Old_fileOffset, fileOffset=Old_fileOffset+7, then end-fileOffset will be equal to -7 which is a negative integer
  parserrec->ZlibBitmapData = (UI8 *)readBytes (f,end-fileOffset);

  PAR_END;
}


char *readBytes(FILE *f, unsigned long size)
{

  if (size < 1) {
#if DEBUG
    SWF_warn("readBytes: want to read %lu < 1 bytes: Handling a 0\n", size);
#endif
    size = 0;
  }

  unsigned long i;
  char *buf;
  // The parameter size's type is unsigned long. Given a negative integer as input, it will be treated as a large unsigned integer and passed to malloc, causing allocation failures.
  buf = (char *)malloc(sizeof(char)*size);

  if (buf == NULL) {
    fprintf(stderr, "readBytes: Failed to allocate %lu bytes", sizeof(char) * size);
    exit(-1);
  }

  for(i=0;i<size;i++)
  {
    buf[i]=(char)readUInt8(f);
  }

  return buf;
}

```
Memory allocation failure caused by the missing boundary check in parseSWF_DEFINELOSSLESS2
This is a GitHub Issue
repo:libming
owner:libming
Title : Memory allocation failure caused by the missing boundary check in parseSWF_DEFINELOSSLESS2
Issue date:

--- start body ---
version: master(commit [04aee52](https://github.com/libming/libming/commit/04aee52363688426eab74f5d6180c149654a6473) )
command: listswf $FILE
```
root:/path_to_libming/build/bin# ./listswf poc
==26225==WARNING: AddressSanitizer failed to allocate 0xfffffffffffffff9 bytes
==26225==AddressSanitizer's allocator is terminating the process instead of returning 0
==26225==If you don't like this behavior set allocator_may_return_null=1
==26225==AddressSanitizer CHECK failed: /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225 "((0)) != (0)" (0x0, 0x0)
    #0 0x4e3385 in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_rtl.cc:69
    #1 0x500c45 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc:79
    #2 0x4e9786 in __sanitizer::ReportAllocatorCannotReturnNull() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225
    #3 0x4e97c6 in __sanitizer::ReturnNullOrDieOnFailure::OnBadRequest() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:241
    #4 0x41f676 in __asan::asan_malloc(unsigned long, __sanitizer::BufferedStackTrace*) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_allocator.cc:856
    #5 0x4da20b in malloc /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:89
    #6 0x5b7e7e in readBytes /path_to_libming/util/read.c:252:17
    #7 0x59b963 in parseSWF_DEFINELOSSLESS2 /path_to_libming/util/parser.c:2168:38
    #8 0x546cf9 in blockParse /path_to_libming/util/blocktypes.c:145:14
    #9 0x53bc13 in readMovie /path_to_libming/util/main.c:269:11
    #10 0x53a0d6 in main /path_to_libming/util/main.c:354:2
    #11 0x7fce52d93bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310
    #12 0x41a2f9 in _start (/path_to_libming/build/bin/listswf+0x41a2f9)
```
The cause of this bug is the lack of boundary checks. Specifically, in the `parseSWF_DEFINELOSSLESS2` function, the size of `end` and `fileOffset` is not compared when `readBytes` is called. As a result, `end-fileOffset` may be a negative integer, which eventually leads to allocation failure.

The detailed call chain analysis is as follows. 
Download [poc](https://github.com/dandanxu96/PoC/blob/7cbf5b7f7b62e4a95725a226b29cae362b425ec8/libming/parseSWF_DEFINELOSSLESS2-readBytes-malloc-failure-poc)
```C
static void readMovie(FILE *f)
{
	int block, type, length, nextFrame=0;
	SWF_Parserstruct *blockp;
	for (;;)
	{
		if(filelen_check_fails(2))
			break;
                // Read 16 bits from the input file, the block is controlled by the attacker
		block = readUInt16 (f);
		type = block >> 6;
                
                 // length = block & 0x3f, which means length<=3f
		length = block & ((1 << 6) - 1);
		if (length == 63)		/* it's a long block. */ 
		{
			if(filelen_check_fails(4))
				break;
			unsigned long real_length = readUInt32 (f);

                        if (real_length > INT_MAX) {
		            SWF_warn(" Could not process long block with length %lu:"
                                     " blocks with length > %d not supported on this system\n",
                                     real_length, INT_MAX);
                            continue;
                        } else {
                            length = (int) real_length;
                        }
		}
		nextFrame = fileOffset+length;
		
		if(filelen_check_fails(length))
			break;
		blockp= blockParse(f, length, type);
                ......
	}
	......
}


SWF_Parserstruct *
blockParse (FILE *f, int length, SWFBlocktype header)
{
  int i;

  for (i = 0; i < numBlocks; i++)
  {
    // Select the corresponding parser to parse
    if (blocks[i].type == header)
    {
      return blocks[i].parser(f,length);
    }
  }
  return parseSWF_UNKNOWNBLOCK(f, length);
}


SWF_Parserstruct *
parseSWF_DEFINELOSSLESS2 (FILE * f, int length)
{
  int end = fileOffset + length;
  PAR_BEGIN (SWF_DEFINELOSSLESS2);

  parserrec->CharacterID = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
  parserrec->BitmapFormat = readUInt8 (f); // Read 8 bits from the input file, and fileOffset = fileOffset+1
  parserrec->BitmapWidth = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
  parserrec->BitmapHeight = readUInt16 (f); Read 16 bits from the input file, and fileOffset = fileOffset+2
  if( parserrec->BitmapFormat == 3 /* 8-bit */ ) {
      parserrec->BitmapColorTableSize = readUInt8 (f);
  }
  // When length=0, at this moment end=Old_fileOffset, fileOffset=Old_fileOffset+7, then end-fileOffset will be equal to -7 which is a negative integer
  parserrec->ZlibBitmapData = (UI8 *)readBytes (f,end-fileOffset);

  PAR_END;
}


char *readBytes(FILE *f, unsigned long size)
{

  if (size < 1) {
#if DEBUG
    SWF_warn("readBytes: want to read %lu < 1 bytes: Handling a 0\n", size);
#endif
    size = 0;
  }

  unsigned long i;
  char *buf;
  // The parameter size's type is unsigned long. Given a negative integer as input, it will be treated as a large unsigned integer and passed to malloc, causing allocation failures.
  buf = (char *)malloc(sizeof(char)*size);

  if (buf == NULL) {
    fprintf(stderr, "readBytes: Failed to allocate %lu bytes", sizeof(char) * size);
    exit(-1);
  }

  for(i=0;i<size;i++)
  {
    buf[i]=(char)readUInt8(f);
  }

  return buf;
}

```
--- end body ---
