Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 778b15a2 authored by Brian Lindahl's avatar Brian Lindahl
Browse files

Fix bug with parsing vectors

Also move to StringUtils, add unit test and use std::from_chars.

Bug: 234833109
Test: statsd_testdrive 684 while watching YouTube videos
Test: atest mediametrics_tests#parseVector
Change-Id: I0eff0bcb7fb9542fdab0c08b98f7789decedb7d2
parent 13e40cb2
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -15,11 +15,13 @@
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetricsService::stringutils"
#define LOG_TAG "mediametrics::stringutils"
#include <utils/Log.h>

#include "StringUtils.h"

#include <charconv>

#include "AudioTypes.h"

namespace android::mediametrics::stringutils {
@@ -54,6 +56,26 @@ std::vector<std::string> split(const std::string& flags, const char *delim)
    }
}

bool parseVector(const std::string &str, std::vector<int32_t> *vector) {
    std::vector<int32_t> values;
    const char *p = str.c_str();
    const char *last = p + str.size();
    while (p != last) {
        if (*p == ',' || *p == '{' || *p == '}') {
            p++;
        }
        int32_t value = -1;
        auto [ptr, error] = std::from_chars(p, last, value);
        if (error == std::errc::invalid_argument || error == std::errc::result_out_of_range) {
            return false;
        }
        p = ptr;
        values.push_back(value);
    }
    *vector = std::move(values);
    return true;
}

std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string& devices)
{
    std::vector<std::pair<std::string, std::string>> result;
+4 −2
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

#pragma once

#include <audio_utils/SimpleLog.h>
#include <map>
#include <mutex>
#include <sstream>

#include <android-base/thread_annotations.h>
#include <audio_utils/SimpleLog.h>

namespace android::mediametrics {

class StatsdLog {
@@ -61,9 +63,9 @@ public:
   }

private:
    mutable std::mutex mLock;
    SimpleLog mSimpleLog; // internally locked
    std::map<int /* atom */, size_t /* count */> mCountMap GUARDED_BY(mLock); // sorted
    mutable std::mutex mLock;
};

} // namespace android::mediametrics
+6 −0
Original line number Diff line number Diff line
@@ -71,6 +71,12 @@ std::string tokenizer(std::string::const_iterator& it,
 */
std::vector<std::string> split(const std::string& flags, const char *delim);

/**
 * Parses a vector of integers using ',' '{' and '}' as delimeters. Leaves
 * vector unmodified if the parsing fails.
 */
bool parseVector(const std::string &str, std::vector<int32_t> *vector);

/**
 * Parse the devices string and return a vector of device address pairs.
 *
+2 −0
Original line number Diff line number Diff line
@@ -15,7 +15,9 @@
 */

#include <memory>

#include <stats_event.h>
#include <StatsdLog.h>

namespace android {
namespace mediametrics {
+9 −26
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <pthread.h>
#include <pwd.h>
#include <stdint.h>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -32,11 +33,12 @@
#include <stats_media_metrics.h>
#include <stats_event.h>

#include "cleaner.h"
#include "MediaMetricsService.h"
#include "ValidateId.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include "iface_statsd.h"
#include <frameworks/proto_logging/stats/message/mediametrics_message.pb.h>
#include <mediametricsservice/cleaner.h>
#include <mediametricsservice/iface_statsd.h>
#include <mediametricsservice/MediaMetricsService.h>
#include <mediametricsservice/StringUtils.h>
#include <mediametricsservice/ValidateId.h>

namespace android {

@@ -169,27 +171,8 @@ static int32_t getMetricsHdrFormatEnum(std::string &mime, std::string &component
}

static void parseVector(const std::string &str, std::vector<int32_t> *vector) {
    char valueStr[12] = {};
    int i = 0;
    for (char const * p = str.c_str(); *p != 0; ++p) {
        if (*p == ',' || *p == '{' || *p == '}') {
            valueStr[i] = 0;
            int64_t value = strtol(valueStr, nullptr, 10);
            if (value >= std::numeric_limits<int32_t>::max() ||
                value <= std::numeric_limits<int32_t>::min() ||
                value == 0) {
                ALOGE("failed to parse integer vector at '%s' from '%s'", p, str.c_str());
                return;
            }
            vector->push_back(int32_t(value));
            i = valueStr[0] = 0;
        } else {
            valueStr[i++] = *p;
            if (i == sizeof(valueStr) - 1) { // -1 because we need space for a null terminator
                ALOGE("failed to parse integer vector at '%s' from '%s'", p, str.c_str());
                return;
            }
        }
    if (!mediametrics::stringutils::parseVector(str, vector)) {
        ALOGE("failed to parse integer vector from '%s'", str.c_str());
    }
}

Loading