From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sagar Verma <quic_sagarv@quicinc.com>
Date: Sun, 12 Jun 2022 00:05:07 +0530
Subject: [PATCH] AVRC: Validating msg size before accessing fields

This change adds buffer length validation during the parsing of AVRCP
browse commands.

Change-Id: I3a6c7a9ea2323a04ce5c5368eabfa940a8152cba
---
 stack/avrc/avrc_pars_tg.cc | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc
index 7042f4da7..38c0ca385 100644
--- a/stack/avrc/avrc_pars_tg.cc
+++ b/stack/avrc/avrc_pars_tg.cc
@@ -407,6 +407,12 @@ tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) {
   return status;
 }
 
+#define RETURN_STATUS_IF_FALSE(_status_, _b_, _msg_, ...) \
+  if (!(_b_)) {                                           \
+    AVRC_TRACE_DEBUG(_msg_, ##__VA_ARGS__);               \
+    return _status_;                                      \
+  }
+
 /*******************************************************************************
  *
  * Function         avrc_pars_browsing_cmd
@@ -425,6 +431,7 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
   tAVRC_STS status = AVRC_STS_NO_ERROR;
   uint8_t* p = p_msg->p_browse_data;
   int count;
+  uint16_t min_len = 3;
 
   p_result->pdu = *p++;
   AVRC_TRACE_DEBUG("avrc_pars_browsing_cmd() pdu:0x%x", p_result->pdu);
@@ -438,6 +445,7 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
       break;
 
     case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
+      min_len += 10;
       STREAM_TO_UINT8(p_result->get_items.scope, p);
       // To be modified later here (Scope) when all browsing commands are
       // supported
@@ -458,6 +466,11 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
         if (buf_len < (count << 2))
           p_result->get_items.attr_count = count = (buf_len >> 2);
         for (int idx = 0; idx < count; idx++) {
+          min_len += 4;
+          RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
+                                (p_msg->browse_len >= min_len),
+                                 "msg too short");
+
           BE_STREAM_TO_UINT32(p_result->get_items.p_attr_list[idx], p);
         }
       }
@@ -474,6 +487,7 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
       break;
 
     case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */
+      min_len += 12;
       BE_STREAM_TO_UINT8(p_result->get_attrs.scope, p);
       if (p_result->get_attrs.scope > AVRC_SCOPE_NOW_PLAYING) {
         status = AVRC_STS_BAD_SCOPE;
@@ -490,6 +504,11 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
           p_result->get_attrs.attr_count = count = (buf_len >> 2);
         for (int idx = 0, count = 0; idx < p_result->get_attrs.attr_count;
              idx++) {
+          min_len += 4;
+          RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
+                                (p_msg->browse_len >= min_len),
+                                 "msg too short");
+
           BE_STREAM_TO_UINT32(p_result->get_attrs.p_attr_list[count], p);
           if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(
                   p_result->get_attrs.p_attr_list[count])) {
