Talos Vulnerability Report

TALOS-2016-0154

Libarchive Rar RestartModel Code Execution Vulnerability

June 19, 2016

Report ID

CVE-2016-4302

Summary

An exploitable heap overflow vulnerability exists in the Rar decompression functionality of libarchive. A specially crafted Rar file can cause a heap corruption eventually leading to code execution. An attacker can send a malformed file to trigger this vulnerability.

Tested Versions

libarchive git version on date 02.12.2015 Platform : x86/x64

Product URLs

https://github.com/libarchive/libarchive

CVSSv3 Score

7.8 - CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CVSSv3 Calculator: https://www.first.org/cvss/calculator/3.0

Details

Here we see the execution flow leading to heap corruption:

archive_read_next_header
	   archive_read_format_rar_read_header
	head_type : 0x72
	head_type : 0x73
	head_type : 0x74
	read_header
	rar->packed_size : 0x1
	rar->dictionary_size = 0;
	archive_format_name : RAR
archive_read_extract
	rar->compression_method : 0x31
	read_data_compressed
	   archive_read_format_rar_read_header
	head_type : 0x7a
	read_header
	parse_codes
		if (ppmd_flags & 0x20)
		   archive_read_format_rar_read_header
		head_type : 0x7b
		   archive_read_format_rar_read_header
		head_type : 0x74
		read_header
		rar->packed_size : 0x1
		rar->dictionary_size = 0;
		   archive_read_format_rar_read_header
		head_type : 0x7a
		read_header
		rar->dictionary_size : 0x10000000
		   archive_read_format_rar_read_header
		head_type : 0x7b
		   archive_read_format_rar_read_header
		head_type : 0x74
		read_header
		rar->packed_size : 0x1
		rar->dictionary_size = 0;
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		__archive_ppmd7_functions.PpmdRAR_RangeDec_CreateVTable(&rar->range_dec);
		ppmd_alloc : 0
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		   archive_read_format_rar_read_header
		Ppmd7_Init
		RestartModel
	*** Heap corruption ***

Lets we focus on extraction phase, so everyting below archive_read_extract. The key variable/field here is rar->dictionary_size.

First we see that its value is set to:

rar->dictionary_size : 0x10000000

libarchive\archive_read_support_format_rar.c

Line 2073    /* Memory is allocated in MB */
Line 2074    if (ppmd_flags & 0x20)
Line 2075    {
Line 2076      if (!rar_br_read_ahead(a, br, 8))
Line 2077        goto truncated_data;
Line 2078      rar->dictionary_size = (rar_br_bits(br, 8) + 1) << 20;
Line 2079      rar_br_consume(br, 8);
Line 2080    }

Next, because of small value of “packed_size”:

rar->packed_size : 0x1

another portion of data are read from file and parsed like during “reading phase” in archive_read_next_header by calling archive_read_format_rar_read_header and read_header functions. During on of these calls we see that value of dictionary_size is set to zero. Next allocation for Ppmd context depends on the value of dictionary_size:

libarchive\archive_read_support_format_rar.c
Line 2115      if ( !__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,rar->dictionary_size, &g_szalloc) )

libarchive\archive_ppmd7.c

Line 125	static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
Line 126	{
Line 127	  if (p->Base == 0 || p->Size != size)
Line 128	  {
Line 129		Ppmd7_Free(p, alloc);
Line 130		p->AlignOffset =
Line 131		  #ifdef PPMD_32BIT
Line 132			(4 - size) & 3;
Line 133		  #else
Line 134			4 - (size & 3);
Line 135		  #endif
Line 136		if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
Line 137			#ifndef PPMD_32BIT
Line 138			+ UNIT_SIZE
Line 139			#endif
Line 140			)) == 0)
Line 141		  return False;
Line 142		p->Size = size;
Line 143	  }
Line 144	  return True;
Line 145	}

As we can see for dictionary_size equal 0 we will have allocation made for 0 bytes:

python import gdbheap
p p->Base
$5 = (Byte *) 0x80e2480 " \b\r\brn"
heap select size==16
Reading in symbols for malloc.c...done.
     Start         End         Domain         Kind    Detail                                                                             Hexdump
----------  ----------  -------------  -----------  --------  ----------------------------------------------------------------------------------
0x080d0798  0x080d07a7  uncategorized               16 bytes  a8 07 0d 08 03 00 00 00 57 4d 54 00 19 00 00 00 c0 07 0d 08 |........WMT.........|
0x080d07c0  0x080d07cf  uncategorized               16 bytes  d0 07 0d 08 03 00 00 00 43 45 54 00 19 00 00 00 e8 07 0d 08 |........CET.........|
0x080d07e8  0x080d07f7  uncategorized               16 bytes  00 00 00 00 03 00 00 00 45 45 54 00 21 00 00 00 72 61 72 2d |........EET.!...rar-|
0x080d0818  0x080d0827  uncategorized               16 bytes  00 00 00 00 50 a4 d8 f7 00 00 00 00 11 00 00 00 50 70 6d 64 |....P...........Ppmd|
0x080d0828  0x080d0837              C  string data            50 70 6d 64 37 5f 49 6e 69 74 0a 00 21 00 00 00 44 00 00 00 |Ppmd7_Init..!...D...|
0x080d0cd8  0x080d0ce7  uncategorized               16 bytes  e8 0c 0d 08 00 00 00 00 00 00 00 00 f9 01 00 00 c5 b0 01 c0 |....................|
0x080e2470  0x080e247f  uncategorized               16 bytes  00 69 62 61 32 2e 68 74 6d 6c c0 cc 11 00 00 00 20 08 0d 08 |.iba2.html...... ...|
0x080e2480  0x080e248f              C  string data            20 08 0d 08 72 6e 00 00 00 00 00 00 21 00 00 00 72 61 72 2d | ...rn......!...rar-|

Finally we land in RestartModel function:

libarchive\archive_ppmd7.c
Line 314	static void RestartModel(CPpmd7 *p)
Line 315	{
Line 316	  unsigned i, k, m;
Line 317
Line 318	  memset(p->FreeList, 0, sizeof(p->FreeList));
Line 319	  p->Text = p->Base + p->AlignOffset;
Line 320	  p->HiUnit = p->Text + p->Size;
Line 321	  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
Line 322	  p->GlueCount = 0;
Line 323
Line 324	  p->OrderFall = p->MaxOrder;
Line 325	  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
Line 326	  p->PrevSuccess = 0;
Line 327
Line 328	  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
Line 329	  p->MinContext->Suffix = 0;
Line 330	  p->MinContext->NumStats = 256;
Line 331	  p->MinContext->SummFreq = 256 + 1;
Line 332	  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
Line 333	  p->LoUnit += U2B(256 / 2);
Line 334	  p->MinContext->Stats = REF(p->FoundState);

The key values here are:

p p->AlignOffset
$6 = 0
p p->Size
$7 = 0

As we can see above both equal 0 which has consequences in line 328 where UNIT_SIZE (12) is subtracted from p->HiUnit pointer and assigned to p->MinContext: When everything is correct p->HiUnit first is set at the end of allocated space for Ppmd context, but because AlignOffset and Size is equal 0 it still points to the beginning. In result of this substraction p->MinContext is set to the inside of previous heap chunk space.

p p->MinContext
$8 = (CPpmd7_Context *) 0x80e2474

heap:
0x080e2470  0x080e247f  uncategorized               16 bytes  00 69 62 61 32
2e 68 74 6d 6c c0 cc 11 00 00 00 20 08 0d 08 |.iba2.html...... ...|
0x080e2480  0x080e248f              C  string data            20 08 0d 08 72
6e 00 00 00 00 00 00 21 00 00 00 72 61 72 2d | ...rn......!...rar-|

Further writes to this structure overwrite heap chunks:

Heap check before execution of line 329:

python from heap.glibc import *
python print MChunkPtr(gdb.Value(0x080e2480-8).cast(MChunkPtr.gdb_type()))
<MChunkPtr chunk=0x80e2478 mem=0x80e2480 PREV_INUSE inuse chunksize=16 memsize=8>

After execution:

python print MChunkPtr(gdb.Value(0x080e2480-8).cast(MChunkPtr.gdb_type()))
<MChunkPtr chunk=0x80e2478 mem=0x80e2480 prev_size=3435162733 free chunksize=0 memsize=-8>

Crash Information

Valgrind Output:
==13328== Memcheck, a memory error detector
==13328== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==13328== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==13328== Command: libarchive-pure32/bin/ext /home/icewall/samples/rar/pmd7.rar rar
==13328==
==13328== Invalid write of size 4
==13328==    at 0x809C4D4: RestartModel (archive_ppmd7.c:329)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c06c is 4 bytes before a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 2
==13328==    at 0x809C4E0: RestartModel (archive_ppmd7.c:330)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c064 is 12 bytes before a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 2
==13328==    at 0x809C4EA: RestartModel (archive_ppmd7.c:331)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c066 is 10 bytes before a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 4
==13328==    at 0x809C519: RestartModel (archive_ppmd7.c:334)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c068 is 8 bytes before a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 1
==13328==    at 0x809C543: RestartModel (archive_ppmd7.c:338)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c070 is 0 bytes after a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 1
==13328==    at 0x809C548: RestartModel (archive_ppmd7.c:339)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==    by 0x804A45A: main (ext.c:85)
==13328==  Address 0x445c071 is 1 bytes after a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 2
==13328==    at 0x809C3CC: SetSuccessor (archive_ppmd7.c:310)
==13328==    by 0x809C55E: RestartModel (archive_ppmd7.c:340)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==  Address 0x445c072 is 2 bytes after a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==
==13328== Invalid write of size 2
==13328==    at 0x809C3DB: SetSuccessor (archive_ppmd7.c:311)
==13328==    by 0x809C55E: RestartModel (archive_ppmd7.c:340)
==13328==    by 0x809C693: Ppmd7_Init (archive_ppmd7.c:364)
==13328==    by 0x807C20F: parse_codes (archive_read_support_format_rar.c:2128)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==  Address 0x445c074 is 4 bytes after a block of size 0 alloc'd
==13328==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13328==    by 0x80783CC: ppmd_alloc (archive_read_support_format_rar.c:611)
==13328==    by 0x809BD73: Ppmd7_Alloc (archive_ppmd7.c:136)
==13328==    by 0x807C190: parse_codes (archive_read_support_format_rar.c:2115)
==13328==    by 0x807B8CA: read_data_compressed (archive_read_support_format_rar.c:1919)
==13328==    by 0x8079049: archive_read_format_rar_read_data (archive_read_support_format_rar.c:1025)
==13328==    by 0x804ED6B: _archive_read_data_block (archive_read.c:982)
==13328==    by 0x8091B3B: archive_read_data_block (archive_virtual.c:161)
==13328==    by 0x805083C: copy_data (archive_read_extract2.c:139)
==13328==    by 0x8050770: archive_read_extract2 (archive_read_extract2.c:101)
==13328==    by 0x80505CE: archive_read_extract (archive_read_extract.c:59)
==13328==    by 0x804A3E2: extract (ext.c:63)
==13328==

Credit

Discovered by Marcin ‘Icewall’ Noga of Cisco TALOS http://talosintel.com/vulnerability-reports/

Timeline

2016-04-19 - Vendor Disclosure
2016-06-19 - Public Release