From bb3f84250514d5990939e57b5d1ff8badc566033 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 12 Nov 2024 16:53:17 +0100 Subject: tools/syz-declextract: improve declaration name extraction Extracting declaration name is trickier than removing casts. If the initialized type is a union, then the expression may also contain InitListExpr and other nodes. Remove all of them in a more robust way. --- sys/linux/auto.txt.json | 14 ++++++++++++++ tools/syz-declextract/syz-declextract.cpp | 27 ++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/sys/linux/auto.txt.json b/sys/linux/auto.txt.json index 7a87bf32b..f35cda062 100644 --- a/sys/linux/auto.txt.json +++ b/sys/linux/auto.txt.json @@ -1097,6 +1097,7 @@ "files": [ "net/netlink/genetlink.c" ], + "func": "ctrl_dumpfamily", "access": "user", "subsystems": [ "net" @@ -1110,6 +1111,7 @@ "files": [ "net/netlink/genetlink.c" ], + "func": "ctrl_dumppolicy_done", "access": "user", "subsystems": [ "net" @@ -1809,6 +1811,7 @@ "files": [ "net/handshake/genl.c" ], + "func": "handshake_nl_accept_doit", "access": "admin", "subsystems": [ "tls" @@ -1822,6 +1825,7 @@ "files": [ "net/handshake/genl.c" ], + "func": "handshake_nl_done_doit", "access": "user", "subsystems": [ "tls" @@ -3151,6 +3155,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_bind_rx_doit", "access": "admin", "subsystems": [ "net" @@ -3164,6 +3169,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_dev_get_doit", "access": "user", "subsystems": [ "net" @@ -3177,6 +3183,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_napi_get_dumpit", "access": "user", "subsystems": [ "net" @@ -3190,6 +3197,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_page_pool_get_doit", "access": "user", "subsystems": [ "net" @@ -3203,6 +3211,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_qstats_get_dumpit", "access": "user", "subsystems": [ "net" @@ -3216,6 +3225,7 @@ "files": [ "net/core/netdev-genl-gen.c" ], + "func": "netdev_nl_queue_get_dumpit", "access": "user", "subsystems": [ "net" @@ -3584,6 +3594,7 @@ "files": [ "fs/nfsd/netlink.c" ], + "func": "nfsd_nl_listener_set_doit", "access": "admin", "subsystems": [ "nfs" @@ -3597,6 +3608,7 @@ "files": [ "fs/nfsd/netlink.c" ], + "func": "nfsd_nl_pool_mode_set_doit", "access": "admin", "subsystems": [ "nfs" @@ -3610,6 +3622,7 @@ "files": [ "fs/nfsd/netlink.c" ], + "func": "nfsd_nl_threads_set_doit", "access": "admin", "subsystems": [ "nfs" @@ -3623,6 +3636,7 @@ "files": [ "fs/nfsd/netlink.c" ], + "func": "nfsd_nl_version_set_doit", "access": "admin", "subsystems": [ "nfs" diff --git a/tools/syz-declextract/syz-declextract.cpp b/tools/syz-declextract/syz-declextract.cpp index 698bc1263..3c6c40a23 100644 --- a/tools/syz-declextract/syz-declextract.cpp +++ b/tools/syz-declextract/syz-declextract.cpp @@ -110,9 +110,21 @@ struct SyzRecordDecl { // If expression refers to some identifier, returns the identifier name. // Otherwise returns an empty string. // For example, if the expression is `function_name`, returns "function_name" string. -std::string getDeclName(const clang::Expr *expr) { - auto *decl = llvm::dyn_cast(expr->IgnoreCasts()); - return decl ? decl->getDecl()->getNameAsString() : ""; +std::string getDeclName(ASTContext &context, const clang::Expr *expr) { + if (!expr) { + return ""; + } + // The expression can be complex and include casts and e.g. InitListExpr, + // to remove all of these we match the first/any DeclRefExpr. + struct Matcher : MatchFinder::MatchCallback { + const DeclRefExpr *decl = nullptr; + void run(const MatchFinder::MatchResult &Result) override { decl = Result.Nodes.getNodeAs("decl"); } + }; + MatchFinder finder; + Matcher matcher; + finder.addMatcher(stmt(forEachDescendant(declRefExpr().bind("decl"))), &matcher); + finder.match(*expr, context); + return matcher.decl ? matcher.decl->getDecl()->getNameAsString() : ""; } bool endsWith(const std::string_view &str, const std::string_view end) { @@ -825,9 +837,9 @@ private: if (opsName != "small_ops") { policyDecl = init->getInit(opsMember["policy"])->getAsBuiltinConstantDeclRef(*context); } - std::string func = getDeclName(init->getInit(opsMember["doit"])); + std::string func = getDeclName(*context, init->getInit(opsMember["doit"])); if (func.empty()) - func = getDeclName(init->getInit(opsMember["dumpit"])); + func = getDeclName(*context, init->getInit(opsMember["dumpit"])); const Expr *flagsDecl = init->getInit(opsMember["flags"]); Expr::EvalResult flags; flagsDecl->EvaluateAsConstantExpr(flags, *context); @@ -912,6 +924,7 @@ public: private: void run(const MatchFinder::MatchResult &Result) override { + ASTContext *context = Result.Context; const auto *ioIssueDefs = Result.Nodes.getNodeAs("io_issue_defs"); if (!ioIssueDefs) { return; @@ -924,11 +937,11 @@ private: } for (const auto &[i, op] : elements) { const auto &init = llvm::dyn_cast(initList->getInit(i)); - std::string prep = getDeclName(init->getInit(fields["prep"])); + std::string prep = getDeclName(*context, init->getInit(fields["prep"])); if (prep == "io_eopnotsupp_prep") { continue; } - std::string issue = getDeclName(init->getInit(fields["issue"])); + std::string issue = getDeclName(*context, init->getInit(fields["issue"])); emitInterface("IOURING", op.name, op.name, issue, AccessUser); } } -- cgit mrf-deployment