sthal: fix static analysis issues

- Use %pK instead of %p to avoid info leak.
- Avoid null pointer dereference.
- Check for integer overflow during addition.

Change-Id: Ifdfbf5025c19c554ec1ff60f2cfb95a98c9ced7e
diff --git a/st_session.c b/st_session.c
index aaac3df..5993fe5 100644
--- a/st_session.c
+++ b/st_session.c
@@ -474,7 +474,7 @@
     sm_info->num_users = sm_header.numUsers;
 
     tmp = sm_header.numKeywords;
-    ALOGV("%s: stdb: model.data %p, model.size %d", __func__, model.data,
+    ALOGV("%s: stdb: model.data %pK, model.size %d", __func__, model.data,
             model.size);
     sm_ret = stdev->smlib_getKeywordPhrases(&model, &tmp, sm_info->keyphrases);
     if (sm_ret) {
@@ -628,7 +628,7 @@
 
     stc_ses->sm_info.sm_data = sm_data;
     stc_ses->sm_info.sm_size = sm_size;
-    ALOGV("%s: stc_ses %p - sm_data %p, sm_size %d", __func__,
+    ALOGV("%s: stc_ses %pK - sm_data %pK, sm_size %d", __func__,
           stc_ses, stc_ses->sm_info.sm_data,
           stc_ses->sm_info.sm_size);
 
@@ -770,7 +770,7 @@
         return 0;
     }
 
-    ALOGV("%s: stc_ses %p - sm_data %p, sm_size %d", __func__,
+    ALOGV("%s: stc_ses %pK - sm_data %pK, sm_size %d", __func__,
           stc_ses, stc_ses->sm_info.sm_data,
           stc_ses->sm_info.sm_size);
 
@@ -1378,20 +1378,28 @@
    const struct sound_trigger_phrase_sound_model *phrase_sm,
    const struct sound_trigger_recognition_config *rc_config,
    unsigned char *conf_levels,
-   unsigned int num_conf_levels,
    unsigned int total_num_users
 )
 {
     int status = 0;
     unsigned int user_level, user_id;
     unsigned int i = 0, j = 0;
+    unsigned int num_conf_levels = 0;
     unsigned char *user_id_tracker;
 
-    if (!phrase_sm || !rc_config || !conf_levels || !num_conf_levels) {
+    if (!phrase_sm || !rc_config || !conf_levels) {
         ALOGE("%s: ERROR. Invalid inputs",__func__);
         return -EINVAL;
     }
 
+    if ((UINT32_MAX - total_num_users) > rc_config->num_phrases)
+        num_conf_levels = total_num_users + rc_config->num_phrases;
+
+    if (!num_conf_levels) {
+        ALOGE("%s: ERROR. Invalid num_conf_levels input", __func__);
+        return -EINVAL;
+    }
+
     /*  Example: Say the recognition structure has 3 keywords with users
      *  |kid|
      *  [0] k1 |uid|
@@ -1425,7 +1433,13 @@
     }
 
     for (i = 0; i < rc_config->num_phrases; i++) {
-        conf_levels[i] = rc_config->phrases[i].confidence_level;
+        if (i < num_conf_levels) {
+            conf_levels[i] = rc_config->phrases[i].confidence_level;
+        } else {
+            ALOGE("%s: ERROR. Invalid number of phrases", __func__);
+            status = -EINVAL;
+            goto exit;
+        }
         for (j = 0; j < rc_config->phrases[i].num_levels; j++) {
             user_level = rc_config->phrases[i].levels[j].level;
             user_id = rc_config->phrases[i].levels[j].user_id;
@@ -1497,7 +1511,7 @@
     }
 
     status = fill_conf_levels_payload_from_rc_config(phrase_sm, rc_config,
-       conf_levels, num_conf_levels, total_num_users);
+       conf_levels, total_num_users);
     if (status) {
         ALOGE("%s: fill config payload failed, error %d", __func__, status);
         goto exit;
@@ -1565,7 +1579,7 @@
     conf_levels[0] = 1; /* minor version */
     conf_levels[1] = num_conf_levels; /* num_active_models */
     status = fill_conf_levels_payload_from_rc_config(phrase_sm, rc_config,
-        conf_levels + 2, num_conf_levels, total_num_users);
+        conf_levels + 2, total_num_users);
     if (status) {
         ALOGE("%s: fill config payload failed, error %d", __func__, status);
         goto exit;
@@ -1592,7 +1606,6 @@
 (
    const void *sm_levels_generic,
    unsigned char *conf_levels,
-   unsigned int num_conf_levels,
    unsigned int total_num_users,
    uint32_t version
 )
@@ -1600,6 +1613,7 @@
     int status = 0;
     unsigned int user_level = 0, user_id = 0;
     unsigned int i = 0, j = 0;
+    unsigned int num_conf_levels = 0;
     unsigned char *user_id_tracker = NULL;
     struct st_sound_model_conf_levels *sm_levels = NULL;
     struct st_sound_model_conf_levels_v2 *sm_levels_v2 = NULL;
@@ -1622,10 +1636,19 @@
 
     if (version != CONF_LEVELS_INTF_VERSION_0002) {
         sm_levels = (struct st_sound_model_conf_levels *)sm_levels_generic;
-        if (!sm_levels || !conf_levels || !num_conf_levels) {
+        if (!sm_levels || !conf_levels) {
             ALOGE("%s: ERROR. Invalid inputs", __func__);
             return -EINVAL;
         }
+
+        if ((UINT32_MAX - total_num_users) > sm_levels->num_kw_levels)
+            num_conf_levels = total_num_users + sm_levels->num_kw_levels;
+
+        if (!num_conf_levels) {
+            ALOGE("%s: ERROR. Invalid num_conf_levels input", __func__);
+            return -EINVAL;
+        }
+
         user_id_tracker = calloc(1, num_conf_levels);
         if (!user_id_tracker) {
             ALOGE("%s: failed to allocate user_id_tracker", __func__);
@@ -1643,7 +1666,13 @@
         }
 
         for (i = 0; i < sm_levels->num_kw_levels; i++) {
-            conf_levels[i] = sm_levels->kw_levels[i].kw_level;
+            if (i < num_conf_levels) {
+                conf_levels[i] = sm_levels->kw_levels[i].kw_level;
+            } else {
+                ALOGE("%s: ERROR. Invalid numver of kw levels", __func__);
+                status = -EINVAL;
+                goto exit;
+            }
             for (j = 0; j < sm_levels->kw_levels[i].num_user_levels; j++) {
                 user_level = sm_levels->kw_levels[i].user_levels[j].level;
                 user_id = sm_levels->kw_levels[i].user_levels[j].user_id;
@@ -1671,10 +1700,19 @@
     } else {
         sm_levels_v2 =
             (struct st_sound_model_conf_levels_v2 *)sm_levels_generic;
-        if (!sm_levels_v2 || !conf_levels || !num_conf_levels) {
+        if (!sm_levels_v2 || !conf_levels) {
             ALOGE("%s: ERROR. Invalid inputs", __func__);
             return -EINVAL;
         }
+
+        if ((UINT32_MAX - total_num_users) > sm_levels_v2->num_kw_levels)
+            num_conf_levels = total_num_users + sm_levels_v2->num_kw_levels;
+
+        if (!num_conf_levels) {
+            ALOGE("%s: ERROR. Invalid num_conf_levels input", __func__);
+            return -EINVAL;
+        }
+
         user_id_tracker = calloc(1, num_conf_levels);
         if (!user_id_tracker) {
             ALOGE("%s: failed to allocate user_id_tracker", __func__);
@@ -1692,7 +1730,13 @@
         }
 
         for (i = 0; i < sm_levels_v2->num_kw_levels; i++) {
-            conf_levels[i] = sm_levels_v2->kw_levels[i].kw_level;
+            if (i < num_conf_levels) {
+                conf_levels[i] = sm_levels_v2->kw_levels[i].kw_level;
+            } else {
+                ALOGE("%s: ERROR. Invalid numver of kw levels", __func__);
+                status = -EINVAL;
+                goto exit;
+            }
             for (j = 0; j < sm_levels_v2->kw_levels[i].num_user_levels; j++) {
                 user_level = sm_levels_v2->kw_levels[i].user_levels[j].level;
                 user_id = sm_levels_v2->kw_levels[i].user_levels[j].user_id;
@@ -1799,7 +1843,7 @@
     }
 
     status = fill_sound_trigger_recognition_config_payload(sm_levels_generic,
-        conf_levels, num_conf_levels, total_num_users, version);
+        conf_levels, total_num_users, version);
     if (status) {
         ALOGE("%s: fill config payload failed, error %d", __func__, status);
         goto exit;
@@ -1893,7 +1937,7 @@
     conf_levels[0] = 1; /* minor version */
     conf_levels[1] = num_conf_levels; /* num_active_models */
     status = fill_sound_trigger_recognition_config_payload(sm_levels_generic,
-        conf_levels + 2, num_conf_levels, total_num_users, version);
+        conf_levels + 2, total_num_users, version);
     if (status) {
         ALOGE("%s: fill config payload failed, error %d", __func__, status);
         goto exit;