hwc2: Add input validation and bound checks.

- Validate the input parameters to hwc2 and check if they
  are with in the allowed bounds.
- On the getter functions check the out counts before populating
  with output parameters

Change-Id: Ifd41aa4d4a0b08e521fabfe54f308a59622d109c
Crs-fixed: 2114346
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0530db8..e3b93cf 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -94,11 +94,12 @@
 HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
                                         android_color_mode_t *out_modes) {
   auto it = color_mode_transform_map_.begin();
-  for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
+  *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_transform_map_.size()));
+  for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
     out_modes[i] = it->first;
     DLOGI("Supports color mode[%d] = %d", i, it->first);
   }
-  *out_num_modes = UINT32(color_mode_transform_map_.size());
+
   return HWC2::Error::None;
 }
 
@@ -750,23 +751,28 @@
 }
 
 HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
-  if (out_modes) {
+  if (out_modes == nullptr) {
+    *out_num_modes = 1;
+  } else if (out_modes && *out_num_modes > 0) {
+    *out_num_modes = 1;
     out_modes[0] = HAL_COLOR_MODE_NATIVE;
   }
-  *out_num_modes = 1;
 
   return HWC2::Error::None;
 }
 
 HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+  if (out_num_configs == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
   if (out_configs == nullptr) {
     *out_num_configs = num_configs_;
     return HWC2::Error::None;
   }
 
-  *out_num_configs = num_configs_;
-
-  for (uint32_t i = 0; i < num_configs_; i++) {
+  *out_num_configs = std::min(*out_num_configs, num_configs_);
+  for (uint32_t i = 0; i < *out_num_configs; i++) {
     out_configs[i] = i;
   }
 
@@ -817,27 +823,38 @@
 
 HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
   // TODO(user): Get panel name and EDID name and populate it here
-  if (out_name == nullptr) {
-    *out_size = 32;
-  } else {
-    std::string name;
-    switch (id_) {
-      case HWC_DISPLAY_PRIMARY:
-        name = "Primary Display";
-        break;
-      case HWC_DISPLAY_EXTERNAL:
-        name = "External Display";
-        break;
-      case HWC_DISPLAY_VIRTUAL:
-        name = "Virtual Display";
-        break;
-      default:
-        name = "Unknown";
-        break;
-    }
-    std::strncpy(out_name, name.c_str(), name.size());
-    *out_size = UINT32(name.size());
+  if (out_size == nullptr) {
+    return HWC2::Error::BadParameter;
   }
+
+  std::string name;
+  switch (id_) {
+    case HWC_DISPLAY_PRIMARY:
+      name = "Primary Display";
+      break;
+    case HWC_DISPLAY_EXTERNAL:
+      name = "External Display";
+      break;
+    case HWC_DISPLAY_VIRTUAL:
+      name = "Virtual Display";
+      break;
+    default:
+      name = "Unknown";
+      break;
+  }
+
+  if (out_name == nullptr) {
+    *out_size = UINT32(name.size()) + 1;
+  } else {
+    *out_size = std::min((UINT32(name.size()) + 1), *out_size);
+    if (*out_size > 0) {
+      std::strncpy(out_name, name.c_str(), *out_size);
+      out_name[*out_size - 1] = '\0';
+    } else {
+      DLOGW("Invalid size requested");
+    }
+  }
+
   return HWC2::Error::None;
 }
 
@@ -1070,15 +1087,22 @@
 
 HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
                                          int32_t *out_fences) {
+  if (out_num_elements == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
   if (out_layers != nullptr && out_fences != nullptr) {
-    int i = 0;
-    for (auto hwc_layer : layer_set_) {
+    *out_num_elements = std::min(*out_num_elements, UINT32(layer_set_.size()));
+    auto it = layer_set_.begin();
+    for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+      auto hwc_layer = *it;
       out_layers[i] = hwc_layer->GetId();
       out_fences[i] = hwc_layer->PopReleaseFence();
-      i++;
     }
+  } else {
+    *out_num_elements = UINT32(layer_set_.size());
   }
-  *out_num_elements = UINT32(layer_set_.size());
+
   return HWC2::Error::None;
 }
 
@@ -1089,6 +1113,10 @@
     return HWC2::Error::None;
   }
 
+  if (out_display_requests == nullptr || out_num_elements == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
   // No display requests for now
   // Use for sharing blit buffers and
   // writing wfd buffer directly to output if there is full GPU composition
@@ -1099,14 +1127,15 @@
   }
 
   *out_display_requests = 0;
-  *out_num_elements = UINT32(layer_requests_.size());
   if (out_layers != nullptr && out_layer_requests != nullptr) {
-    int i = 0;
-    for (auto &request : layer_requests_) {
-      out_layers[i] = request.first;
-      out_layer_requests[i] = INT32(request.second);
-      i++;
+    *out_num_elements = std::min(*out_num_elements, UINT32(layer_requests_.size()));
+    auto it = layer_requests_.begin();
+    for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+      out_layers[i] = it->first;
+      out_layer_requests[i] = INT32(it->second);
     }
+  } else {
+    *out_num_elements = UINT32(layer_requests_.size());
   }
 
   auto client_target_layer = client_target_->GetSDMLayer();
@@ -1121,6 +1150,11 @@
                                            float *out_max_luminance,
                                            float *out_max_average_luminance,
                                            float *out_min_luminance) {
+  if (out_num_types == nullptr || out_max_luminance == nullptr ||
+      out_max_average_luminance == nullptr || out_min_luminance == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
   DisplayConfigFixedInfo fixed_info = {};
   display_intf_->GetConfig(&fixed_info);
 
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 7505b01..9053652 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -139,6 +139,11 @@
 
 HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
+
+  if (!output_buffer_->buffer_id) {
+    return HWC2::Error::NoResources;
+  }
+
   if (display_paused_) {
     DisplayError error = display_intf_->Flush();
     validated_ = false;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 99fbc1a..162c849 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -446,6 +446,9 @@
 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
                              int32_t /*android_color_mode_t*/ *int_out_modes) {
   auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+  if (out_num_modes == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
                                          out_modes);
 }
@@ -453,6 +456,10 @@
 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
                                    hwc2_config_t config, int32_t int_attribute,
                                    int32_t *out_value) {
+  if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
+      int_attribute > HWC2_ATTRIBUTE_DPI_Y) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
   auto attribute = static_cast<HWC2::Attribute>(int_attribute);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
                                          attribute, out_value);
@@ -510,6 +517,10 @@
 }
 
 static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+  if (device == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
   return 1;
 }
 
@@ -528,7 +539,9 @@
   if (!device) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
-
+  if (out_retire_fence == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
   auto status = HWC2::Error::BadDisplay;
   // TODO(user): Handle virtual display/HDMI concurrency
   if (hwc_session->hwc_display_[display]) {