CVE-2018-0429: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: Stack-based buffer overflow in the Cisco Thor decoder before commit 18de8f9f0762c3a542b1122589edb8af859d9813 allows local users to cause a denial of service (segmentation fault) and execute arbitrary code via a crafted non-conformant Thor bitstream.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 7.8
Published: 2018-08-09T20:29Z
Repository: https://github.com/cisco/thor
Language: C
Files changed: dec/decode_block.c, dec/read_bits.c
Commit date: 2018-08-08 20:04:05 +0100
Commit message: Fix possible stack overflows in decoder for illegal bit streams

Fixes CVE-2018-0429
A vulnerability in the Thor decoder (available at:
https://github.com/cisco/thor) could allow an authenticated, local
attacker to cause segmentation faults and stack overflows when using a
non-conformant Thor bitstream as input.
The vulnerability is due to lack of input validation when parsing the
bitstream. A successful exploit could allow the attacker to cause a
stack overflow and potentially inject and execute arbitrary code.

Diff: diff --git a/dec/decode_block.c b/dec/decode_block.c
index a5cecab..85deeb5 100644
--- a/dec/decode_block.c
+++ b/dec/decode_block.c
@@ -648,11 +648,11 @@ void TEMPLATE(process_block_dec)(decoder_info_t *decoder_info,int size,int yposY
     decoder_info->frame_info.qpb = prev_qp + delta_qp;
   }
 
   decoder_info->bit_count.super_mode[decoder_info->bit_count.stat_frame_type] += (stream->bitcnt - bit_start);
 
-  if (split_flag){
+  if (split_flag && size >= MIN_BLOCK_SIZE){
     int new_size = size/2;
     TEMPLATE(process_block_dec)(decoder_info,new_size,yposY+0*new_size,xposY+0*new_size,sub);
     TEMPLATE(process_block_dec)(decoder_info,new_size,yposY+1*new_size,xposY+0*new_size,sub);
     TEMPLATE(process_block_dec)(decoder_info,new_size,yposY+0*new_size,xposY+1*new_size,sub);
     TEMPLATE(process_block_dec)(decoder_info,new_size,yposY+1*new_size,xposY+1*new_size,sub);
diff --git a/dec/read_bits.c b/dec/read_bits.c
index 130b53d..6eda9be 100644
--- a/dec/read_bits.c
+++ b/dec/read_bits.c
@@ -48,10 +48,11 @@ int YPOS, XPOS;
 
 void read_sequence_header(decoder_info_t *decoder_info, stream_t *stream) {
   decoder_info->width = get_flc(16, stream);
   decoder_info->height = get_flc(16, stream);
   decoder_info->log2_sb_size = get_flc(3, stream);
+  decoder_info->log2_sb_size = clip(decoder_info->log2_sb_size, log2i(MIN_BLOCK_SIZE), log2i(MAX_SB_SIZE));
   decoder_info->pb_split = get_flc(1, stream);
   decoder_info->tb_split_enable = get_flc(1, stream);
   decoder_info->max_num_ref = get_flc(2, stream) + 1;
   decoder_info->interp_ref = get_flc(2, stream);
   decoder_info->max_delta_qp = get_flc(1, stream);

Vulnerable code:   if (split_flag){
Fixed code:   if (split_flag && size >= MIN_BLOCK_SIZE){
  decoder_info->log2_sb_size = clip(decoder_info->log2_sb_size, log2i(MIN_BLOCK_SIZE), log2i(MAX_SB_SIZE));