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

Commit 84954030 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Implement struct printing

Also:
- fix potential use-after-free in nlbuf iterator
- simplify getFirst usage by migrating from std::optional to std::pair

Bug: 161898189
Test: print all messages from RTMGRP_LINK group

Change-Id: I4aa785ccef60e397ba87088f37e35d9873fc3c82
parent 2aa1a124
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ cc_library_static {
        "protocols/generic/Unknown.cpp",
        "protocols/route/Link.cpp",
        "protocols/route/Route.cpp",
        "protocols/route/structs.cpp",
        "protocols/MessageDefinition.cpp",
        "protocols/NetlinkProtocol.cpp",
        "protocols/all.cpp",
+13 −6
Original line number Diff line number Diff line
@@ -66,9 +66,12 @@ class nlbuf {
        return mData;
    }

    std::optional<std::reference_wrapper<const T>> getFirst() const {
        if (!ok()) return std::nullopt;
        return *mData;
    std::pair<bool, const T&> getFirst() const {
        if (!ok()) {
            static const T dummy = {};
            return {false, dummy};
        }
        return {true, *mData};
    }

    /**
@@ -141,7 +144,7 @@ class nlbuf {
        size_t len() const { return mBuffer.remainingLength(); }

      private:
        const nlbuf<T>& mBuffer;
        const nlbuf<T> mBuffer;
    };

    raw_view getRaw() const { return {*this}; }
@@ -160,8 +163,12 @@ class nlbuf {
    size_t declaredLength() const {
        // We can't even fit a header, so let's return some absurd high value to trip off
        // buffer overflow checks.
        if (sizeof(T) > remainingLength()) return std::numeric_limits<size_t>::max() / 2;
        return declaredLengthImpl();
        static constexpr size_t badHeaderLength = std::numeric_limits<size_t>::max() / 2;

        if (sizeof(T) > remainingLength()) return badHeaderLength;
        const auto len = declaredLengthImpl();
        if (sizeof(T) > len) return badHeaderLength;
        return len;
    }

    size_t remainingLength() const {
+9 −5
Original line number Diff line number Diff line
@@ -85,17 +85,16 @@ static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,

    ss << attrtype.name << ": ";
    switch (attrtype.dataType) {
        case DataType::Raw: {
        case DataType::Raw:
            toStream(ss, attr.data<uint8_t>());
            break;
        }
        case DataType::Nested: {
            ss << '{';
            bool first = true;
            for (auto childattr : attr.data<nlattr>()) {
            for (const auto childattr : attr.data<nlattr>()) {
                if (!first) ss << ", ";
                first = false;
                toStream(ss, childattr, attrtype.subTypes);
                toStream(ss, childattr, std::get<protocols::AttributeMap>(attrtype.ops));
            }
            ss << '}';
            break;
@@ -105,9 +104,14 @@ static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,
            ss << '"' << sanitize({str.ptr(), str.len()}) << '"';
            break;
        }
        case DataType::Uint: {
        case DataType::Uint:
            ss << attr.data<uint32_t>().copyFirst();
            break;
        case DataType::Struct: {
            const auto structToStream =
                    std::get<protocols::AttributeDefinition::ToStream>(attrtype.ops);
            structToStream(ss, attr);
            break;
        }
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <map>
#include <sstream>
#include <variant>

namespace android::netdevice::protocols {

@@ -57,11 +58,13 @@ struct AttributeDefinition {
        Nested,
        String,
        Uint,
        Struct,
    };
    using ToStream = std::function<void(std::stringstream& ss, const nlbuf<nlattr> attr)>;

    std::string name;
    DataType dataType = DataType::Raw;
    AttributeMap subTypes = {};
    std::variant<AttributeMap, ToStream> ops = AttributeMap{};
};

/**
@@ -107,13 +110,13 @@ class MessageDefinition : public MessageDescriptor {
        : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}

    void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const override {
        const auto msg = hdr.data<T>().getFirst();
        if (!msg.has_value()) {
        const auto& [ok, msg] = hdr.data<T>().getFirst();
        if (!ok) {
            ss << "{incomplete payload}";
            return;
        }

        toStream(ss, *msg);
        toStream(ss, msg);
    }

  protected:
+4 −4
Original line number Diff line number Diff line
@@ -37,14 +37,14 @@ Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
    {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}},
    {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}},
    {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}},
    {CTRL_ATTR_OPS, {"OPS", DataType::Nested, {
        {std::nullopt, {"OP", DataType::Nested, {
    {CTRL_ATTR_OPS, {"OPS", DataType::Nested, AttributeMap{
        {std::nullopt, {"OP", DataType::Nested, AttributeMap{
            {CTRL_ATTR_OP_ID, {"ID", DataType::Uint}},
            {CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}},
        }}},
    }}},
    {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, {
        {std::nullopt, {"GRP", DataType::Nested, {
    {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{
        {std::nullopt, {"GRP", DataType::Nested, AttributeMap{
            {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::String}},
            {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}},
        }}},
Loading