From 78321addc0d5c4077fd4a7470f98ba4cc6c524d8 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 24 Nov 2022 09:57:30 +0800 Subject: [PATCH 01/15] support "settings set plugin.symbol-file.dwarf.comp-dir-symlink-paths /proc/self/cwd" command. Signed-off-by: xwx1135370 --- .../Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td index 2f1ce88808b7..ef6ae3498588 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td @@ -1,6 +1,10 @@ include "../../../../include/lldb/Core/PropertiesBase.td" let Definition = "symbolfiledwarf" in { + def SymLinkPaths: Property<"comp-dir-symlink-paths", "FileSpecList">, + Global, + DefaultStringValue<"">, + Desc<"If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time.">; def IgnoreIndexes: Property<"ignore-file-indexes", "Boolean">, Global, DefaultFalse, -- Gitee From 64bb9189f95000ea4351f1c052891f245cac0c16 Mon Sep 17 00:00:00 2001 From: Pavel Kosov Date: Thu, 1 Dec 2022 11:26:23 +0300 Subject: [PATCH 02/15] [OHOS][Docs] Add development guideline Signed-off-by: Pavel Kosov --- .gitee/PULL_REQUEST_TEMPLATE.en.md | 2 ++ OpenHarmonyDevelopmentGuidelines.md | 37 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 OpenHarmonyDevelopmentGuidelines.md diff --git a/.gitee/PULL_REQUEST_TEMPLATE.en.md b/.gitee/PULL_REQUEST_TEMPLATE.en.md index aa60947a3ec9..f6d433f6d188 100644 --- a/.gitee/PULL_REQUEST_TEMPLATE.en.md +++ b/.gitee/PULL_REQUEST_TEMPLATE.en.md @@ -1,2 +1,4 @@ ## PR Description A clear and concise description of changes and rationale. Provide a link to external references / discussion if appropriate + +Development Guidelines: https://gitee.com/openharmony/third_party_llvm-project/blob/master/OpenHarmonyDevelopmentGuidelines.md diff --git a/OpenHarmonyDevelopmentGuidelines.md b/OpenHarmonyDevelopmentGuidelines.md new file mode 100644 index 000000000000..212f6596d863 --- /dev/null +++ b/OpenHarmonyDevelopmentGuidelines.md @@ -0,0 +1,37 @@ +## Generic Guidelines + +--------------------- + +### LLVM-related rules + +All changes should adhere to LLVM Developer Policy / Coding Standarts: +- https://llvm.org/docs/CodingStandards.html +- https://llvm.org/docs/DeveloperPolicy.html + +--------------------- + +### Mark changes properly + +All OHOS-related changes to mainline LLVM / clang code MUST be clearly marked such as: + +``` +unsigned LoopSizeThreshold = 32; // OHOS_LOCAL +``` + +or in case of multiline change: + +``` +// OHOS_LOCAL begin + +Some local OHOS change + +// OHOS_LOCAL begin +``` + +The presence of such marks greatly simplifies porting such code snippets to new LLVM versions. All such changes MUST be accompanied with a test case that MUST fail should the change is reverted. + +--------------------- + +### ABI Breakage + +All ABI-breaking changes MUST be scheduled to a major toolchain releases. One should explicitly discuss and document such changes. Ideally ABI-breaking change should cause linking error, it should not cause silent and hard to track bugs. -- Gitee From b9b6a6a17fc71c6cf03f581d079256f1c51802b1 Mon Sep 17 00:00:00 2001 From: yaofeng wang Date: Fri, 16 Dec 2022 21:49:15 +0800 Subject: [PATCH 03/15] Create multiple sync-services for multiple threads avoid crashing while access same connection Issue: I66DKR Test: Build & lldb with attach command & Deveco debug native app Signed-off-by: yaofeng wang --- lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp | 9 +++------ lldb/source/Plugins/Platform/HOS/PlatformHOS.h | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp index 808d2af4a0b7..d31cadb0d1e6 100644 --- a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp @@ -440,11 +440,8 @@ PlatformHOS::GetLibdlFunctionDeclarations(lldb_private::Process *process) { return PlatformPOSIX::GetLibdlFunctionDeclarations(process); } -HdcClient::SyncService *PlatformHOS::GetSyncService(Status &error) { - if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) - return m_adb_sync_svc.get(); - +std::unique_ptr PlatformHOS::GetSyncService(Status &error) { HdcClient hdc(m_device_id); - m_adb_sync_svc = hdc.GetSyncService(error); - return (error.Success()) ? m_adb_sync_svc.get() : nullptr; + std::unique_ptr adb_sync_svc = hdc.GetSyncService(error); + return (error.Success()) ? std::move(adb_sync_svc) : nullptr; } diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.h b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h index d725972243ca..33d5c482042f 100644 --- a/lldb/source/Plugins/Platform/HOS/PlatformHOS.h +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h @@ -69,9 +69,8 @@ protected: GetLibdlFunctionDeclarations(lldb_private::Process *process) override; private: - HdcClient::SyncService *GetSyncService(Status &error); + std::unique_ptr GetSyncService(Status &error); - std::unique_ptr m_adb_sync_svc; std::string m_device_id; uint32_t m_sdk_version; }; -- Gitee From 9abd9d49e9a7ef14659ace78a7c0c4a07db018fb Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Mon, 26 Dec 2022 14:40:21 +0800 Subject: [PATCH 04/15] =?UTF-8?q?[LLDB][MAC]When=20OHOS=5FHDC=5FSERVER=5FP?= =?UTF-8?q?ORT=20is=20set=20to=2088888,=20the=20LLDB=20returns=20=E2=80=9C?= =?UTF-8?q?=20invalid=20host:port=20xxx"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xwx1135370 --- lldb/source/Plugins/Platform/OHOS/HdcClient.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp index 6807d24cf317..1f08dc55f642 100644 --- a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp @@ -153,8 +153,14 @@ Status HdcClient::Connect() { std::string port = "8710"; const char *env_port = std::getenv("OHOS_HDC_SERVER_PORT"); - if ((env_port != NULL) && (atoi(env_port) > 0)) { - port = env_port; + if (env_port != NULL) { + int iEnv_port = atoi(env_port); + if ((iEnv_port > 0) && (iEnv_port <= 65535)) { + port = env_port; + } + else { + return Status("invalid port specification: %s. $OHOS_HDC_SERVER_PORT must be a positive number in (0,65535]", env_port); + } } std::string uri = "connect://localhost:" + port; -- Gitee From 7426fbcc0c9eb242f81c22b97249951613f89dc9 Mon Sep 17 00:00:00 2001 From: Nikolai Kholiavin Date: Tue, 27 Dec 2022 18:24:52 +0300 Subject: [PATCH 05/15] Change step over breakpoint plan to resume past signal handler Change-Id: I2e2dc6c353771c3822247cf255667f3e236be1fe Signed-off-by: Nikolai Kholiavin --- .../Target/ThreadPlanStepOverBreakpoint.h | 2 + .../Target/ThreadPlanStepOverBreakpoint.cpp | 55 ++++++++++++++++--- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h index 1f3aff45c49a..c23c844b83c5 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h +++ b/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -46,6 +46,8 @@ private: lldb::user_id_t m_breakpoint_site_id; bool m_auto_continue; bool m_reenabled_breakpoint_site; + bool m_stopped_at_my_breakpoint; + bool m_handling_signal; ThreadPlanStepOverBreakpoint(const ThreadPlanStepOverBreakpoint &) = delete; const ThreadPlanStepOverBreakpoint & diff --git a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp index f88a2b895931..399a5ef62c6f 100644 --- a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp +++ b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp @@ -28,8 +28,9 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint(Thread &thread) // first in the thread plan stack when stepping over // a breakpoint m_breakpoint_addr(LLDB_INVALID_ADDRESS), - m_auto_continue(false), m_reenabled_breakpoint_site(false) - + m_auto_continue(false), m_reenabled_breakpoint_site(false), + m_stopped_at_my_breakpoint(false), + m_handling_signal(false) { m_breakpoint_addr = thread.GetRegisterContext()->GetPC(); m_breakpoint_site_id = @@ -48,6 +49,8 @@ void ThreadPlanStepOverBreakpoint::GetDescription( bool ThreadPlanStepOverBreakpoint::ValidatePlan(Stream *error) { return true; } bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) { + m_stopped_at_my_breakpoint = false; + StopInfoSP stop_info_sp = GetPrivateStopInfo(); if (stop_info_sp) { StopReason reason = stop_info_sp->GetStopReason(); @@ -80,16 +83,29 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) { lldb::addr_t pc_addr = GetThread().GetRegisterContext()->GetPC(); if (pc_addr == m_breakpoint_addr) { + m_stopped_at_my_breakpoint = true; + // If we came from a signal handler, just reset the flag and try again. + m_handling_signal = false; LLDB_LOGF(log, "Got breakpoint stop reason but pc: 0x%" PRIx64 - "hasn't changed.", + " hasn't changed, resetting m_handling_signal." + " If we came from a signal handler, trying again.", pc_addr); return true; } + // Even if we are in a signal handler, handle the breakpoint as usual + SetAutoContinue(false); return false; } + case eStopReasonSignal: + if (!m_handling_signal) { + // Next stop may be a signal handler. + LLDB_LOG(log, "Preparing for signal handler handling."); + m_handling_signal = true; + } + return false; default: return false; } @@ -104,6 +120,12 @@ bool ThreadPlanStepOverBreakpoint::ShouldStop(Event *event_ptr) { bool ThreadPlanStepOverBreakpoint::StopOthers() { return true; } StateType ThreadPlanStepOverBreakpoint::GetPlanRunState() { + if (m_handling_signal) { + // Resume & wait to hit our initial breakpoint + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOG(log, "Step over breakpoint resuming through a potential signal handler."); + return eStateRunning; + } return eStateStepping; } @@ -112,9 +134,19 @@ bool ThreadPlanStepOverBreakpoint::DoWillResume(StateType resume_state, if (current_plan) { BreakpointSiteSP bp_site_sp( m_process.GetBreakpointSiteList().FindByAddress(m_breakpoint_addr)); - if (bp_site_sp && bp_site_sp->IsEnabled()) { - m_process.DisableBreakpointSite(bp_site_sp.get()); - m_reenabled_breakpoint_site = false; + if (bp_site_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (m_handling_signal) { + // Turn the breakpoint back on and wait to hit it. + // Even if there is no userspace signal handler, we'll immediately stop + // on the breakpoint and try again. + LLDB_LOG(log, "Step over breakpoint reenabling breakpoint to try again after a potential signal handler"); + ReenableBreakpointSite(); + } else if (bp_site_sp->IsEnabled()) { + LLDB_LOG(log, "Step over breakpoint disabling breakpoint."); + m_process.DisableBreakpointSite(bp_site_sp.get()); + m_reenabled_breakpoint_site = false; + } } } return true; @@ -132,7 +164,7 @@ bool ThreadPlanStepOverBreakpoint::MischiefManaged() { if (pc_addr == m_breakpoint_addr) { // If we are still at the PC of our breakpoint, then for some reason we - // didn't get a chance to run. + // didn't get a chance to run, or we received a signal and want to try again. return false; } else { Log *log = GetLog(LLDBLog::Step); @@ -164,9 +196,16 @@ void ThreadPlanStepOverBreakpoint::SetAutoContinue(bool do_it) { } bool ThreadPlanStepOverBreakpoint::ShouldAutoContinue(Event *event_ptr) { + if (m_stopped_at_my_breakpoint) { + // Do not stop again at the breakpoint we are trying to step over + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOG(log, "Stopped step over breakpoint plan on its own breakpoint, auto-continue."); + return true; + } return m_auto_continue; } bool ThreadPlanStepOverBreakpoint::IsPlanStale() { - return GetThread().GetRegisterContext()->GetPC() != m_breakpoint_addr; + // TODO: validate + return !m_handling_signal && GetThread().GetRegisterContext()->GetPC() != m_breakpoint_addr; } -- Gitee From 388e0b968f13345b383de12585421e23f8cfb473 Mon Sep 17 00:00:00 2001 From: Anastasia Lyupa Date: Thu, 12 Jan 2023 21:35:58 +0300 Subject: [PATCH 06/15] [OHOS] Update mask of supported sanitizers Enable -fsanitize=kernel-address clang option Signed-off-by: Anastasia Lyupa --- clang/lib/Driver/ToolChains/OHOS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp index 64dcec7bb1f2..1084b6cec107 100644 --- a/clang/lib/Driver/ToolChains/OHOS.cpp +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -393,7 +393,7 @@ SanitizerMask OHOS::getSupportedSanitizers() const { Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; Res |= SanitizerKind::Scudo; - // TODO: kASAN for liteos ?? + Res |= SanitizerKind::KernelAddress; // TODO: Support TSAN and HWASAN and update mask. return Res; } -- Gitee From e890c89c9d9cff9846a010357227203c111c2559 Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Fri, 13 Jan 2023 11:06:17 +0300 Subject: [PATCH 07/15] [OHOS] Update mask of supported sanitizers Enable -fsanitize=kernel-memory clang option Signed-off-by: Lyupa Anastasia --- clang/lib/Driver/ToolChains/OHOS.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp index 1084b6cec107..5293b92a0e58 100644 --- a/clang/lib/Driver/ToolChains/OHOS.cpp +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -394,6 +394,7 @@ SanitizerMask OHOS::getSupportedSanitizers() const { Res |= SanitizerKind::SafeStack; Res |= SanitizerKind::Scudo; Res |= SanitizerKind::KernelAddress; + Res |= SanitizerKind::KernelMemory; // TODO: Support TSAN and HWASAN and update mask. return Res; } -- Gitee From 9ee1b9a78f73f8dcc7f3d2e737b68f13f18392bd Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Thu, 2 Feb 2023 12:19:47 +0300 Subject: [PATCH 08/15] [BUILD] Strip LLVM binaries if strip option given Add --strip option to build script. Default value is false. Strip final binaries only if this option is provided. Signed-off-by: Lyupa Anastasia --- llvm-build/build.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/llvm-build/build.py b/llvm-build/build.py index f2c08612a5b6..701fe0406040 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -37,6 +37,7 @@ class BuildConfig(): self.do_package = not args.skip_package self.build_name = args.build_name self.debug = args.debug + self.strip = args.strip self.no_lto = args.no_lto self.build_instrumented = args.build_instrumented self.xunit_xml_output = args.xunit_xml_output @@ -98,6 +99,12 @@ class BuildConfig(): default=False, help='Building Clang and LLVM Tools for Debugging (only affects stage2)') + parser.add_argument( + '--strip', + action='store_true', + default=False, + help='Strip final LLVM binaries.') + parser.add_argument( '--no-build-arm', action='store_true', @@ -535,7 +542,9 @@ class LlvmCore(BuildUtils): cflags = '-fstack-protector-strong -fPIE' if not self.host_is_darwin(): - ldflags += ' -Wl,-z,relro,-z,now -pie -s' + ldflags += ' -Wl,-z,relro,-z,now -pie' + if self.build_config.strip: + ldflags += ' -s' self.llvm_compile_llvm_defines(llvm_defines, llvm_cc, llvm_cxx, cflags, ldflags) @@ -819,7 +828,9 @@ class LlvmLibs(BuildUtils): '-stdlib=libc++', ] if not self.host_is_darwin(): - ldflag.append('-Wl,-z,relro,-z,now -s -pie') + ldflag.append('-Wl,-z,relro,-z,now -pie') + if self.build_config.strip: + ldflag.append('-s') ldflags.extend(ldflag) @@ -1247,7 +1258,9 @@ class LldbMi(BuildUtils): cflags = [] cxxflags =[] ldflags = ['-fuse-ld=lld', '-Wl,-rpath,%s' % '\$ORIGIN/../lib'] - ldflags.append('-Wl,-z,relro,-z,now -pie -s') + ldflags.append('-Wl,-z,relro,-z,now -pie') + if self.build_config.strip: + ldflags.append('-s') ldflags.append('-L%s' % os.path.join(llvm_path, 'lib')) cxxflags.append('-std=c++14') @@ -1479,7 +1492,7 @@ class LlvmPackage(BuildUtils): continue if bin_filename not in necessary_bin_files: os.remove(binary) - elif bin_filename not in script_bins: + elif bin_filename not in script_bins and self.build_config.strip: if bin_filename not in need_x_bins_darwin and self.host_is_darwin(): self.check_call(['strip', '-x', binary]) else: @@ -1489,7 +1502,7 @@ class LlvmPackage(BuildUtils): def strip_lldb_server(self, host, install_dir): clang_version_bin_dir = os.path.join(install_dir, 'lib', 'clang', self.build_config.CLANG_VERSION, 'bin') - if not host.startswith('linux') or not os.path.exists(clang_version_bin_dir): + if not host.startswith('linux') or not os.path.exists(clang_version_bin_dir) or not self.build_config.strip: return llvm_strip = os.path.join(install_dir, 'bin', 'llvm-strip') for llvm_triple_dir in os.listdir(clang_version_bin_dir): -- Gitee From a67aa57b21e3bb6e6f9ccd0508fbd6cf0c5dba3e Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Thu, 2 Feb 2023 15:38:20 +0300 Subject: [PATCH 09/15] [BUILD] Update README Add new option --strip Signed-off-by: Lyupa Anastasia --- llvm-build/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm-build/README.md b/llvm-build/README.md index fd76e9fcf755..caedd116f21c 100644 --- a/llvm-build/README.md +++ b/llvm-build/README.md @@ -52,6 +52,7 @@ build.py options: --enable-assertions # enable assertion when compiling --build-name # specify release package name --debug # build debug version llvm toolchain +--strip # strip llvm toolchain binaries --no-build-arm # skip triplet arm --no-build-aarch64 # skip triplet arm64 --no-build-x86_64 # skip triplet x86_64 -- Gitee From 973070c671da0bcbb58b638e2d9e14ac2f0ef60c Mon Sep 17 00:00:00 2001 From: Hongjin Li Date: Wed, 8 Feb 2023 16:40:09 +0800 Subject: [PATCH 10/15] feat: add SignalHandlerChecker and PrintSensitiveInfoChecker SignalHandlerChecker checks for calling non-async-function within a signal handler function. PrintSensitiveInfoChecker checks for sensitive information leak. Signed-off-by: Hongjin Li --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 22 ++ .../StaticAnalyzer/Checkers/CMakeLists.txt | 2 + .../OpenHarmony/PrintSensitiveInfoChecker.cpp | 313 ++++++++++++++++++ .../OpenHarmony/SignalHandlerChecker.cpp | 243 ++++++++++++++ clang/test/Analysis/print-sensitive-info.c | 23 ++ clang/test/Analysis/signal-handler.c | 16 + 6 files changed, 619 insertions(+) create mode 100644 clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp create mode 100644 clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp create mode 100644 clang/test/Analysis/print-sensitive-info.c create mode 100644 clang/test/Analysis/signal-handler.c diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 3b1326ffc37e..d159e2a3641d 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1749,4 +1749,26 @@ def UnixAPIArgsChecker : Checker<"UnixAPIArgs">, def MemcpyChecker : Checker<"Memcpy">, HelpText<"Check for memcpy_s api arguments">, Documentation; + +def PrintSensitiveInfoChecker : Checker<"PrintSensitiveInfo">, + HelpText<"Check for sensitive information disclosure">, + CheckerOptions<[ + CmdLineOption, + ]>, + Documentation; + +def SignalHandlerChecker : Checker<"SignalHandler">, + HelpText<"Check for signal handler">, + CheckerOptions<[ + CmdLineOption, + ]>, + Documentation; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 9a0c774b859a..1749bd6233d6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -137,6 +137,8 @@ add_clang_library(clangStaticAnalyzerCheckers WebKit/UncountedLocalVarsChecker.cpp OpenHarmony/UnixAPIArgsChecker.cpp OpenHarmony/MemcpyChecker.cpp + OpenHarmony/PrintSensitiveInfoChecker.cpp + OpenHarmony/SignalHandlerChecker.cpp LINK_LIBS clangAST diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp new file mode 100644 index 000000000000..3c5e6fdab63d --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp @@ -0,0 +1,313 @@ +//== PrintSensitiveInfoChecker.cpp ------------------------------*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines PrintSensitiveInfoChecker, checks for sensitive information leak +// such as printing password in log. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "Yaml.h" + +using namespace std; +using namespace clang; +using namespace ento; + +namespace { + struct SensitiveState { + public: + bool isSensitive; + SensitiveState() { + isSensitive = false; + } + + SensitiveState(const SensitiveState &another) { + this->isSensitive = another.isSensitive; + } + + SensitiveState &operator=(const SensitiveState &another) { + if (&another != this) { + this->isSensitive = another.isSensitive; + } + return *this; + } + + ~SensitiveState() {} + + bool operator==(const SensitiveState &x) const { + return isSensitive == x.isSensitive; + } + + void Profile(llvm::FoldingSetNodeID &id) const {} + }; + + class PrintSensitiveInfoChecker : public Checker, + check::PreStmt, + check::PreStmt> { + public: + // lowercase string in following sets + mutable std::set m_sensitive_var_set; + mutable std::set m_sensitive_func_set; + mutable std::set m_output_set; + + mutable map m_output_map; + + struct SensitiveValueConfiguration { + struct SensitiveList { + std::string type; + std::vector list; + }; + std::vector sensitiveList; + }; + + PrintSensitiveInfoChecker(); + ~PrintSensitiveInfoChecker(){}; + + void checkPreStmt(const DeclStmt *declStmt, CheckerContext &c) const; + void checkPreStmt(const BinaryOperator *BO, CheckerContext &c) const; + void checkPreStmt(const CallExpr *call, CheckerContext &c) const; + + void saveVardeclStateForBo(const Expr *lhs, const Expr *rhs, CheckerContext &c) const; + void saveVardeclStateForDeclStmt(const DeclStmt *ds, CheckerContext &c) const; + const VarDecl *GetVarDeclFromExpr(const Expr *E) const; + const string GetCurrentCalleeName(const CallExpr *CE) const; + + void parseConfiguration(const SensitiveValueConfiguration *config); + string convertStrToLowerCase(const string &str) const; + + void report(const Stmt *Opera, const string &msg, CheckerContext &c) const; + }; +} + +using sensitiveConfig = PrintSensitiveInfoChecker::SensitiveValueConfiguration; +LLVM_YAML_IS_SEQUENCE_VECTOR(sensitiveConfig::SensitiveList) + +namespace llvm { + namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, sensitiveConfig &info) { + io.mapRequired("List", info.sensitiveList); + } + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, sensitiveConfig::SensitiveList &info) { + io.mapRequired("type", info.type); + io.mapOptional("value", info.list); + } + }; + } // end namespace yaml +} // end namespace llvm + +REGISTER_MAP_WITH_PROGRAMSTATE(SensitiveInfoMap, const VarDecl *, SensitiveState) + +PrintSensitiveInfoChecker::PrintSensitiveInfoChecker() { + // some base patterns in set + m_sensitive_var_set.insert("password"); + m_sensitive_var_set.insert("pwd"); + m_sensitive_func_set.insert("getpassword"); + m_output_set.insert("hilog"); +} + +const VarDecl *PrintSensitiveInfoChecker::GetVarDeclFromExpr(const Expr *E) const { + if (const auto *DRE = dyn_cast(E)) { + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { + return VD; + } + } + return nullptr; +} + +const string PrintSensitiveInfoChecker::GetCurrentCalleeName(const CallExpr *CE) const { + return CE->getDirectCallee()->getNameInfo().getName().getAsString(); +} + +string PrintSensitiveInfoChecker::convertStrToLowerCase(const string &str) const { + string ret(str); + transform(str.begin(), str.end(), ret.begin(), [](unsigned char c){ return tolower(c); }); + return ret; +} + +void PrintSensitiveInfoChecker::parseConfiguration(const SensitiveValueConfiguration *config) { + if (config) { + for (auto &sl : config->sensitiveList) { + if (sl.type == "fnCall") { + for (auto &value : sl.list) { + m_sensitive_func_set.insert(convertStrToLowerCase(value)); + } + } + else if (sl.type == "varName") { + for (auto &value : sl.list) { + m_sensitive_var_set.insert(convertStrToLowerCase(value)); + } + } + else if (sl.type == "outputFn") { + for (auto &value : sl.list) { + m_output_set.insert(convertStrToLowerCase(value)); + } + } + } + } +} + +void PrintSensitiveInfoChecker::report(const Stmt *operaExpr, const string &msg, CheckerContext &context) const { + if (operaExpr == nullptr) { + return; + } + AnalysisDeclContext *declContext = + context.getAnalysisManager().getAnalysisDeclContext(context.getStackFrame()->getDecl()); + PathDiagnosticLocation location = + PathDiagnosticLocation::createBegin(operaExpr, context.getSourceManager(), declContext); + + SourceRange range = operaExpr->getSourceRange(); + if (!(declContext->getDecl())) { + return; + } + context.getBugReporter().EmitBasicReport(declContext->getDecl(), this, + "PrintSensitiveInfo", "Indicator of poor code quality", msg, + location, range); + context.addTransition(); +} + +void PrintSensitiveInfoChecker::checkPreStmt(const DeclStmt *ds, CheckerContext &c) const { + if (ds == nullptr) { + return; + } + saveVardeclStateForDeclStmt(ds, c); +} + +void PrintSensitiveInfoChecker::checkPreStmt(const BinaryOperator *binary, CheckerContext &c) const { + + if (binary == nullptr) { + return; + } + if (binary->getOpcode() == clang::BO_Assign) + { + const Expr *lhs = binary->getLHS()->IgnoreParenImpCasts(); + const Expr *rhs = binary->getRHS()->IgnoreParenImpCasts(); + if (lhs == nullptr || rhs == nullptr) + { + return; + } + saveVardeclStateForBo(lhs, rhs, c); + } +} + +void PrintSensitiveInfoChecker::checkPreStmt(const CallExpr *call, CheckerContext &c) const { + if (call == nullptr) { + return; + } + const string funcName = GetCurrentCalleeName(call); + if (m_output_set.find(convertStrToLowerCase(funcName)) == m_output_set.end()) { + return; + } + unsigned int nums = call->getNumArgs(); + + for (unsigned int i = 0; i < nums; i++) { + const Expr *arg = call->getArg(i)->IgnoreParenImpCasts(); + if (arg == nullptr) { + continue; + } + + const VarDecl *varDecl = GetVarDeclFromExpr(arg); + if (varDecl == nullptr) { + continue; + } + // check by variable's name only + if (m_sensitive_var_set.find(convertStrToLowerCase(varDecl->getNameAsString())) != m_sensitive_var_set.end()) { + string msg = varDecl->getNameAsString() + " is a sensitive information"; + report(call, msg, c); + } + // check by state map + ProgramStateRef state = c.getState(); + const SensitiveState *sens = state->get(varDecl); + if (sens == nullptr) { + continue; + } + if (sens->isSensitive) { + // report bug + string msg = varDecl->getNameAsString() + " is a sensitive information"; + report(call, msg, c); + } + } +} + +void PrintSensitiveInfoChecker::saveVardeclStateForBo(const Expr *lhs, const Expr *rhs, + CheckerContext &c) const { + if (rhs == nullptr || lhs == nullptr) { + return; + } + const VarDecl *varDecl = GetVarDeclFromExpr(lhs); + if (varDecl == nullptr) { + return; + } + if (isa(rhs)) { + const CallExpr *call = llvm::dyn_cast_or_null(rhs); + const string funcName = GetCurrentCalleeName(call); + if (m_sensitive_func_set.find(convertStrToLowerCase(funcName)) != m_sensitive_func_set.end()) { + ProgramStateRef state = c.getState(); + SensitiveState sens; + sens.isSensitive = true; + state = state->set(varDecl, sens); + c.addTransition(state); + } + } +} + +void PrintSensitiveInfoChecker::saveVardeclStateForDeclStmt(const DeclStmt *ds, CheckerContext &c) const { + + const VarDecl *varDecl = llvm::dyn_cast_or_null(ds->getSingleDecl()); + if (varDecl == nullptr) { + return; + } + const Expr *expr = varDecl->getInit()->IgnoreParenImpCasts(); + if (expr == nullptr) { + return; + } + + if (isa(expr)) { + const CallExpr *call = llvm::dyn_cast_or_null(expr); + const string funcName = GetCurrentCalleeName(call); + if (m_sensitive_func_set.find(convertStrToLowerCase(funcName)) != m_sensitive_func_set.end()) { + ProgramStateRef state = c.getState(); + SensitiveState sens; + sens.isSensitive = true; + state = state->set(varDecl, sens); + c.addTransition(state); + } + } +} + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerPrintSensitiveInfoChecker(CheckerManager &mgr) { + auto *Checker = mgr.registerChecker(); + std::string Option{"Config"}; + StringRef ConfigFile = mgr.getAnalyzerOptions().getCheckerStringOption(Checker, Option); + llvm::Optional obj = getConfiguration(mgr, Checker, Option, ConfigFile); + // If no Config is provided, obj is null + if (obj) { + Checker->parseConfiguration(obj.getPointer()); + } +} + +// This checker should be enabled regardless of how language options are set. +bool ento::shouldRegisterPrintSensitiveInfoChecker(const CheckerManager &mgr) { + return true; +} \ No newline at end of file diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp new file mode 100644 index 000000000000..06382d93742b --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp @@ -0,0 +1,243 @@ +//== SignalHandlerChecker.cpp ------------------------------*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines SignalHandlerChecker, checks for calling non-async-safe +// functionos within signalhandler function +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" +#include "llvm/ADT/DenseSet.h" +#include "Yaml.h" + +using namespace std; +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +namespace { + static bool isSystemCall(const FunctionDecl *FD) { + return FD->getASTContext().getSourceManager().isInSystemHeader( + FD->getCanonicalDecl()->getLocation()); + } + AST_MATCHER(FunctionDecl, isSystemCallCheck) { return isSystemCall(&Node); } + + class SignalHandlerChecker : public Checker { + public: + mutable std::set m_async_safe_func_set; + struct FunctionConfiguration + { + struct FunctionList { + std::string type; + std::vector list; + }; + std::vector functionList; + }; + void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, + AnalysisManager &AM, + BugReporter &BR) const; + void parseConfiguration(const FunctionConfiguration *config); + }; + + class Callback : public MatchFinder::MatchCallback { + const SignalHandlerChecker *C; + BugReporter &BR; + AnalysisDeclContext *ADC; + + public : + void run(const MatchFinder::MatchResult &Result) override; + void Report(const Stmt *stmt, const string &msg); + bool isSystemCallAllowed(const FunctionDecl *FD) const; + Callback(const SignalHandlerChecker *C, + BugReporter &BR, AnalysisDeclContext *ADC) + : C(C), BR(BR), ADC(ADC) {} + + private: + llvm::StringSet<> StrictConformingFunctions = { + "signal", "abort", "_Exit", "quick_exit"}; + }; +} + +using functionConfig = SignalHandlerChecker::FunctionConfiguration; +LLVM_YAML_IS_SEQUENCE_VECTOR(functionConfig::FunctionList) + +namespace llvm +{ + namespace yaml + { + template <> + struct MappingTraits + { + static void mapping(IO &io, functionConfig &info) + { + io.mapRequired("List", info.functionList); + } + }; + + template <> + struct MappingTraits + { + static void mapping(IO &io, functionConfig::FunctionList &info) + { + io.mapRequired("type", info.type); + io.mapOptional("value", info.list); + } + }; + } // end namespace yaml +} // end namespace llvm + +void SignalHandlerChecker::parseConfiguration(const FunctionConfiguration *config) { + if (config) { + for (auto &sl : config->functionList) { + if (sl.type == "asyncSafeFunction") { + for (auto &value : sl.list) { + m_async_safe_func_set.insert(value); + } + } + } + } +} + +void SignalHandlerChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU, + AnalysisManager &AM, + BugReporter &BR) const { + MatchFinder F; + Callback CB(this, BR, AM.getAnalysisDeclContext(TU)); + + auto SignalFunction = functionDecl(hasAnyName("signal", "::signal", "::std::signal"), + parameterCountIs(2), isSystemCallCheck()); + auto HandlerExpr = + declRefExpr(hasDeclaration(functionDecl().bind("handler_decl"))) + .bind("handler_expr"); + F.addMatcher((callExpr(callee(SignalFunction), hasArgument(1, HandlerExpr)) + .bind("register_call")), &CB); + F.matchAST(AM.getASTContext()); +} + +void Callback::run(const MatchFinder::MatchResult &Result) { + const auto *SignalCall = Result.Nodes.getNodeAs("register_call"); + const auto *HandlerDecl = + Result.Nodes.getNodeAs("handler_decl"); + const auto *HandlerExpr = Result.Nodes.getNodeAs("handler_expr"); + llvm::DenseSet SeenFunctions; + + // The worklist of the callgraph visitation algorithm. + std::deque CalledFunctions; + + auto ProcessFunction = [&](const FunctionDecl *F, const Expr *CallOrRef) { + // Ensure that canonical declaration is used. + F = F->getCanonicalDecl(); + + // Do not visit function if already encountered. + if (!SeenFunctions.insert(F).second) + return true; + // Check if the call is allowed. + // Non-system calls are not considered. + if (isSystemCall(F)) { + if (isSystemCallAllowed(F)) { + return true; + } + // disallowed + const string funcName = F->getNameInfo().getName().getAsString(); + string msg = "The non-async-safe function \'"+ funcName + "\' cannot be used in the callback function of signal"; + Report(CallOrRef,msg); + return false; + } + + // Get the body of the encountered non-system call function. + const FunctionDecl *FBody; + if (!F->hasBody(FBody)) { + const string funcName = F->getNameInfo().getName().getAsString(); + string msg = "The non-async-safe function \'"+ funcName + "\' cannot be used in the callback function of signal"; + Report(CallOrRef,msg); + return false; + } + + // Collect all called functions. + auto Matches = match(decl(forEachDescendant(callExpr().bind("call"))), + *FBody, FBody->getASTContext()); + for (const auto &Match: Matches) { + const auto *CE = Match.getNodeAs("call"); + if (isa(CE->getCalleeDecl())) { + CalledFunctions.push_back(CE); + } + } + return true; + }; + + if (!ProcessFunction(HandlerDecl, HandlerExpr)) + return; + + // Visit the definition of every function referenced by the handler function. + // Check for allowed function calls. + while (!CalledFunctions.empty()) { + const CallExpr *FunctionCall = CalledFunctions.front(); + CalledFunctions.pop_front(); + // At insertion we have already ensured that only function calls are there. + const auto *F = cast(FunctionCall->getCalleeDecl()); + + if (!ProcessFunction(F, FunctionCall)) + break; + } +} + +bool Callback::isSystemCallAllowed(const FunctionDecl *FD) const { + const IdentifierInfo *II = FD->getIdentifier(); + // Unnamed functions are not explicitly allowed. + if (!II) + return false; + + // user defined in yaml configuration + if (C->m_async_safe_func_set.count(II->getName().str())) { + return true; + } + + if (StrictConformingFunctions.count(II->getName())) + return true; + + return false; +} + +void Callback::Report(const Stmt *stmt, const std::string &msg) +{ + PathDiagnosticLocation ceLoc = PathDiagnosticLocation::createBegin(stmt, BR.getSourceManager(), ADC); + SourceRange r = stmt->getSourceRange(); + if (ADC->getDecl() == nullptr) { + return; + } + BR.EmitBasicReport(ADC->getDecl(), C, + "SignalHandlerChecker", "Indicator of Poor Code Quality", msg, ceLoc, r); +} + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerSignalHandlerChecker(CheckerManager &mgr) { + auto *Checker = mgr.registerChecker(); + std::string Option{"Config"}; + StringRef ConfigFile = mgr.getAnalyzerOptions().getCheckerStringOption(Checker, Option); + llvm::Optional obj = getConfiguration(mgr, Checker, Option, ConfigFile); + if (obj) { + Checker->parseConfiguration(obj.getPointer()); + } +} + +// This checker should be enabled regardless of how language options are set. +bool ento::shouldRegisterSignalHandlerChecker(const CheckerManager &mgr) { + return true; +} \ No newline at end of file diff --git a/clang/test/Analysis/print-sensitive-info.c b/clang/test/Analysis/print-sensitive-info.c new file mode 100644 index 000000000000..b381a4cc5034 --- /dev/null +++ b/clang/test/Analysis/print-sensitive-info.c @@ -0,0 +1,23 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=openharmony -verify %s + +void HILOG(int x, int y) { + return; +} + +int getPassword() { + return 1; +} + +void test1() { + int x = getPassword(); + int y = getPassword(); + HILOG(x, y); + // expected-warning@-1 {{x is a sensitive information}} + // expected-warning@-2 {{y is a sensitive information}} +} + +void test2(int password, int PWD) { + HILOG(password, PWD); + // expected-warning@-1 {{password is a sensitive information}} + // expected-warning@-2 {{PWD is a sensitive information}} +} \ No newline at end of file diff --git a/clang/test/Analysis/signal-handler.c b/clang/test/Analysis/signal-handler.c new file mode 100644 index 000000000000..8ceafccf5d2e --- /dev/null +++ b/clang/test/Analysis/signal-handler.c @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=openharmony -verify %s +// expected-no-diagnostics + +#define SIGINT 1 +void sighandler1(int); +int printf(const char *, ...); +void signal(int, void *); + +int main () { + signal(SIGINT, sighandler1); + return 0; +} + +void sighandler1(int signum) { + printf("in signalhandler1"); +} \ No newline at end of file -- Gitee From 6446d729438a270e6ab1a2dbc03c4f3cd70da002 Mon Sep 17 00:00:00 2001 From: dhy308 Date: Wed, 11 Jan 2023 16:03:46 +0800 Subject: [PATCH 11/15] After musl supports cross-dso, clang rt needn't support it. Issue: I6A41P Test: Cfi Cross-dso testcase pass. Signed-off-by: dhy308 --- clang/lib/Driver/SanitizerArgs.cpp | 2 +- clang/test/Driver/sanitizer-ld.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 68fe90c7a69d..20c93c03a4c0 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -830,7 +830,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() || TC.getTriple().isOSDarwin()); - ImplicitCfiRuntime = TC.getTriple().isAndroid(); + ImplicitCfiRuntime = TC.getTriple().isAndroid() || TC.getTriple().isOHOSFamily(); if (AllAddedKinds & SanitizerKind::Address) { NeedPIE |= TC.getTriple().isOSFuchsia(); diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index 423ce8beaa84..09b5bdc9860e 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -594,6 +594,14 @@ // CHECK-CFI-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-CFI-LINUX-NOT: libclang_rt. +// [OHOS]CFI by itself does not link runtime libraries. +// RUN: %clang -fsanitize=cfi %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-ohos -fuse-ld=lld -rtlib=platform \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: | FileCheck --check-prefix=CHECK-CFI-LINUX %s +// CHECK-CFI-LINUX: "{{.*}}ld{{(.exe)?}}" +// CHECK-CFI-LINUX-NOT: libclang_rt. + // CFI with diagnostics links the UBSan runtime. // RUN: %clang -fsanitize=cfi -fno-sanitize-trap=cfi -fsanitize-recover=cfi \ // RUN: -### %s 2>&1\ -- Gitee From 626be2f2a7c79777317e953feabb56f45819bf33 Mon Sep 17 00:00:00 2001 From: Hongjin Li Date: Tue, 14 Feb 2023 15:35:05 +0800 Subject: [PATCH 12/15] review fix Signed-off-by: Hongjin Li --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 4 + .../OpenHarmony/PrintSensitiveInfoChecker.cpp | 91 +++++++++---------- .../OpenHarmony/SignalHandlerChecker.cpp | 53 ++++++----- clang/test/Analysis/print-sensitive-info.c | 8 +- clang/test/Analysis/signal-handler.c | 2 +- 5 files changed, 80 insertions(+), 78 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index d159e2a3641d..df70f03f0939 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1737,6 +1737,8 @@ def UncountedLocalVarsChecker : Checker<"UncountedLocalVarsChecker">, } // end alpha.webkit +// OHOS_LOCAL begin + //===----------------------------------------------------------------------===// // OpenHarmony checkers. //===----------------------------------------------------------------------===// @@ -1772,3 +1774,5 @@ def SignalHandlerChecker : Checker<"SignalHandler">, ]>, Documentation; } + +// OHOS_LOCAL end diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp index 3c5e6fdab63d..e613f05961f3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/PrintSensitiveInfoChecker.cpp @@ -27,30 +27,19 @@ using namespace ento; namespace { struct SensitiveState { + private: + bool sensitive; + public: - bool isSensitive; - SensitiveState() { - isSensitive = false; - } + bool isSensitive() const { return sensitive; } + void setSensitive(bool B) { sensitive = B; } - SensitiveState(const SensitiveState &another) { - this->isSensitive = another.isSensitive; + bool operator==(const SensitiveState &X) const { + return sensitive == X.sensitive; } - - SensitiveState &operator=(const SensitiveState &another) { - if (&another != this) { - this->isSensitive = another.isSensitive; - } - return *this; + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddBoolean(sensitive); } - - ~SensitiveState() {} - - bool operator==(const SensitiveState &x) const { - return isSensitive == x.isSensitive; - } - - void Profile(llvm::FoldingSetNodeID &id) const {} }; class PrintSensitiveInfoChecker : public Checker, @@ -58,18 +47,16 @@ namespace { check::PreStmt> { public: // lowercase string in following sets - mutable std::set m_sensitive_var_set; - mutable std::set m_sensitive_func_set; - mutable std::set m_output_set; - - mutable map m_output_map; + set m_sensitive_var_set; + set m_sensitive_func_set; + set m_output_set; struct SensitiveValueConfiguration { struct SensitiveList { - std::string type; - std::vector list; + string type; + vector list; }; - std::vector sensitiveList; + vector sensitiveList; }; PrintSensitiveInfoChecker(); @@ -82,10 +69,10 @@ namespace { void saveVardeclStateForBo(const Expr *lhs, const Expr *rhs, CheckerContext &c) const; void saveVardeclStateForDeclStmt(const DeclStmt *ds, CheckerContext &c) const; const VarDecl *GetVarDeclFromExpr(const Expr *E) const; - const string GetCurrentCalleeName(const CallExpr *CE) const; + string GetCurrentCalleeName(const CallExpr *CE) const; - void parseConfiguration(const SensitiveValueConfiguration *config); - string convertStrToLowerCase(const string &str) const; + void parseConfiguration(CheckerManager &mgr, const std::string &Option, const SensitiveValueConfiguration *config); + string convertStrToLowerCase(string str) const; void report(const Stmt *Opera, const string &msg, CheckerContext &c) const; }; @@ -118,7 +105,7 @@ REGISTER_MAP_WITH_PROGRAMSTATE(SensitiveInfoMap, const VarDecl *, SensitiveState PrintSensitiveInfoChecker::PrintSensitiveInfoChecker() { // some base patterns in set m_sensitive_var_set.insert("password"); - m_sensitive_var_set.insert("pwd"); + m_sensitive_var_set.insert("passwd"); m_sensitive_func_set.insert("getpassword"); m_output_set.insert("hilog"); } @@ -132,33 +119,36 @@ const VarDecl *PrintSensitiveInfoChecker::GetVarDeclFromExpr(const Expr *E) cons return nullptr; } -const string PrintSensitiveInfoChecker::GetCurrentCalleeName(const CallExpr *CE) const { +string PrintSensitiveInfoChecker::GetCurrentCalleeName(const CallExpr *CE) const { return CE->getDirectCallee()->getNameInfo().getName().getAsString(); } -string PrintSensitiveInfoChecker::convertStrToLowerCase(const string &str) const { - string ret(str); - transform(str.begin(), str.end(), ret.begin(), [](unsigned char c){ return tolower(c); }); - return ret; +string PrintSensitiveInfoChecker::convertStrToLowerCase(string str) const { + transform(str.begin(), str.end(), str.begin(), [](unsigned char c){ return tolower(c); }); + return str; } -void PrintSensitiveInfoChecker::parseConfiguration(const SensitiveValueConfiguration *config) { +void PrintSensitiveInfoChecker::parseConfiguration(CheckerManager &mgr, const std::string &Option, const SensitiveValueConfiguration *config) { if (config) { for (auto &sl : config->sensitiveList) { if (sl.type == "fnCall") { - for (auto &value : sl.list) { + for (auto value : sl.list) { m_sensitive_func_set.insert(convertStrToLowerCase(value)); } } else if (sl.type == "varName") { - for (auto &value : sl.list) { + for (auto value : sl.list) { m_sensitive_var_set.insert(convertStrToLowerCase(value)); } } else if (sl.type == "outputFn") { - for (auto &value : sl.list) { + for (auto value : sl.list) { m_output_set.insert(convertStrToLowerCase(value)); } + } else { + mgr.reportInvalidCheckerOptionValue( + this, Option, + "a valid key: fnCall, varName, outputFn"); } } } @@ -211,7 +201,7 @@ void PrintSensitiveInfoChecker::checkPreStmt(const CallExpr *call, CheckerContex if (call == nullptr) { return; } - const string funcName = GetCurrentCalleeName(call); + string funcName = GetCurrentCalleeName(call); if (m_output_set.find(convertStrToLowerCase(funcName)) == m_output_set.end()) { return; } @@ -231,6 +221,7 @@ void PrintSensitiveInfoChecker::checkPreStmt(const CallExpr *call, CheckerContex if (m_sensitive_var_set.find(convertStrToLowerCase(varDecl->getNameAsString())) != m_sensitive_var_set.end()) { string msg = varDecl->getNameAsString() + " is a sensitive information"; report(call, msg, c); + continue; } // check by state map ProgramStateRef state = c.getState(); @@ -238,7 +229,7 @@ void PrintSensitiveInfoChecker::checkPreStmt(const CallExpr *call, CheckerContex if (sens == nullptr) { continue; } - if (sens->isSensitive) { + if (sens->isSensitive()) { // report bug string msg = varDecl->getNameAsString() + " is a sensitive information"; report(call, msg, c); @@ -257,11 +248,11 @@ void PrintSensitiveInfoChecker::saveVardeclStateForBo(const Expr *lhs, const Exp } if (isa(rhs)) { const CallExpr *call = llvm::dyn_cast_or_null(rhs); - const string funcName = GetCurrentCalleeName(call); + string funcName = GetCurrentCalleeName(call); if (m_sensitive_func_set.find(convertStrToLowerCase(funcName)) != m_sensitive_func_set.end()) { ProgramStateRef state = c.getState(); SensitiveState sens; - sens.isSensitive = true; + sens.setSensitive(true); state = state->set(varDecl, sens); c.addTransition(state); } @@ -281,11 +272,11 @@ void PrintSensitiveInfoChecker::saveVardeclStateForDeclStmt(const DeclStmt *ds, if (isa(expr)) { const CallExpr *call = llvm::dyn_cast_or_null(expr); - const string funcName = GetCurrentCalleeName(call); + string funcName = GetCurrentCalleeName(call); if (m_sensitive_func_set.find(convertStrToLowerCase(funcName)) != m_sensitive_func_set.end()) { ProgramStateRef state = c.getState(); SensitiveState sens; - sens.isSensitive = true; + sens.setSensitive(true); state = state->set(varDecl, sens); c.addTransition(state); } @@ -298,16 +289,16 @@ void PrintSensitiveInfoChecker::saveVardeclStateForDeclStmt(const DeclStmt *ds, void ento::registerPrintSensitiveInfoChecker(CheckerManager &mgr) { auto *Checker = mgr.registerChecker(); - std::string Option{"Config"}; + string Option{"Config"}; StringRef ConfigFile = mgr.getAnalyzerOptions().getCheckerStringOption(Checker, Option); llvm::Optional obj = getConfiguration(mgr, Checker, Option, ConfigFile); // If no Config is provided, obj is null if (obj) { - Checker->parseConfiguration(obj.getPointer()); + Checker->parseConfiguration(mgr, Option, obj.getPointer()); } } // This checker should be enabled regardless of how language options are set. bool ento::shouldRegisterPrintSensitiveInfoChecker(const CheckerManager &mgr) { return true; -} \ No newline at end of file +} diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp index 06382d93742b..067a8e9cb1de 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/SignalHandlerChecker.cpp @@ -38,25 +38,29 @@ namespace { class SignalHandlerChecker : public Checker { public: - mutable std::set m_async_safe_func_set; + set m_async_safe_func_set; struct FunctionConfiguration { struct FunctionList { - std::string type; - std::vector list; + string type; + vector list; }; - std::vector functionList; + vector functionList; }; void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &AM, BugReporter &BR) const; - void parseConfiguration(const FunctionConfiguration *config); + void parseConfiguration(CheckerManager &mgr, + const std::string &Option, + const FunctionConfiguration *config); }; class Callback : public MatchFinder::MatchCallback { const SignalHandlerChecker *C; BugReporter &BR; AnalysisDeclContext *ADC; + const llvm::StringSet<> StrictConformingFunctions = { + "signal", "abort", "_Exit", "quick_exit"}; public : void run(const MatchFinder::MatchResult &Result) override; @@ -65,10 +69,6 @@ namespace { Callback(const SignalHandlerChecker *C, BugReporter &BR, AnalysisDeclContext *ADC) : C(C), BR(BR), ADC(ADC) {} - - private: - llvm::StringSet<> StrictConformingFunctions = { - "signal", "abort", "_Exit", "quick_exit"}; }; } @@ -100,13 +100,19 @@ namespace llvm } // end namespace yaml } // end namespace llvm -void SignalHandlerChecker::parseConfiguration(const FunctionConfiguration *config) { +void SignalHandlerChecker::parseConfiguration(CheckerManager &mgr, + const std::string &Option, + const FunctionConfiguration *config) { if (config) { for (auto &sl : config->functionList) { if (sl.type == "asyncSafeFunction") { for (auto &value : sl.list) { m_async_safe_func_set.insert(value); } + } else { + mgr.reportInvalidCheckerOptionValue( + this, Option, + "a valid key: asyncSafeFunction"); } } } @@ -129,16 +135,17 @@ void SignalHandlerChecker::checkEndOfTranslationUnit(const TranslationUnitDecl * } void Callback::run(const MatchFinder::MatchResult &Result) { - const auto *SignalCall = Result.Nodes.getNodeAs("register_call"); - const auto *HandlerDecl = - Result.Nodes.getNodeAs("handler_decl"); + const auto *HandlerDecl = Result.Nodes.getNodeAs("handler_decl"); const auto *HandlerExpr = Result.Nodes.getNodeAs("handler_expr"); llvm::DenseSet SeenFunctions; // The worklist of the callgraph visitation algorithm. - std::deque CalledFunctions; + queue CalledFunctions; auto ProcessFunction = [&](const FunctionDecl *F, const Expr *CallOrRef) { + if (F == nullptr || CallOrRef == nullptr) { + return false; + } // Ensure that canonical declaration is used. F = F->getCanonicalDecl(); @@ -153,8 +160,8 @@ void Callback::run(const MatchFinder::MatchResult &Result) { } // disallowed const string funcName = F->getNameInfo().getName().getAsString(); - string msg = "The non-async-safe function \'"+ funcName + "\' cannot be used in the callback function of signal"; - Report(CallOrRef,msg); + string msg = "The non-async-safe function '" + funcName + "' cannot be used in the callback function of signal"; + Report(CallOrRef, msg); return false; } @@ -162,8 +169,8 @@ void Callback::run(const MatchFinder::MatchResult &Result) { const FunctionDecl *FBody; if (!F->hasBody(FBody)) { const string funcName = F->getNameInfo().getName().getAsString(); - string msg = "The non-async-safe function \'"+ funcName + "\' cannot be used in the callback function of signal"; - Report(CallOrRef,msg); + string msg = "The non-async-safe function '" + funcName + "' cannot be used in the callback function of signal"; + Report(CallOrRef, msg); return false; } @@ -172,8 +179,8 @@ void Callback::run(const MatchFinder::MatchResult &Result) { *FBody, FBody->getASTContext()); for (const auto &Match: Matches) { const auto *CE = Match.getNodeAs("call"); - if (isa(CE->getCalleeDecl())) { - CalledFunctions.push_back(CE); + if (CE && isa(CE->getCalleeDecl())) { + CalledFunctions.push(CE); } } return true; @@ -186,7 +193,7 @@ void Callback::run(const MatchFinder::MatchResult &Result) { // Check for allowed function calls. while (!CalledFunctions.empty()) { const CallExpr *FunctionCall = CalledFunctions.front(); - CalledFunctions.pop_front(); + CalledFunctions.pop(); // At insertion we have already ensured that only function calls are there. const auto *F = cast(FunctionCall->getCalleeDecl()); @@ -233,11 +240,11 @@ void ento::registerSignalHandlerChecker(CheckerManager &mgr) { StringRef ConfigFile = mgr.getAnalyzerOptions().getCheckerStringOption(Checker, Option); llvm::Optional obj = getConfiguration(mgr, Checker, Option, ConfigFile); if (obj) { - Checker->parseConfiguration(obj.getPointer()); + Checker->parseConfiguration(mgr, Option, obj.getPointer()); } } // This checker should be enabled regardless of how language options are set. bool ento::shouldRegisterSignalHandlerChecker(const CheckerManager &mgr) { return true; -} \ No newline at end of file +} diff --git a/clang/test/Analysis/print-sensitive-info.c b/clang/test/Analysis/print-sensitive-info.c index b381a4cc5034..66d67373f7dd 100644 --- a/clang/test/Analysis/print-sensitive-info.c +++ b/clang/test/Analysis/print-sensitive-info.c @@ -16,8 +16,8 @@ void test1() { // expected-warning@-2 {{y is a sensitive information}} } -void test2(int password, int PWD) { - HILOG(password, PWD); +void test2(int password, int passwd) { + HILOG(password, passwd); // expected-warning@-1 {{password is a sensitive information}} - // expected-warning@-2 {{PWD is a sensitive information}} -} \ No newline at end of file + // expected-warning@-2 {{passwd is a sensitive information}} +} diff --git a/clang/test/Analysis/signal-handler.c b/clang/test/Analysis/signal-handler.c index 8ceafccf5d2e..ad3025c5a0b2 100644 --- a/clang/test/Analysis/signal-handler.c +++ b/clang/test/Analysis/signal-handler.c @@ -13,4 +13,4 @@ int main () { void sighandler1(int signum) { printf("in signalhandler1"); -} \ No newline at end of file +} -- Gitee From 9da37329b57ebc9fb49b489ad895a2dcd084f22e Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Mon, 20 Feb 2023 18:07:23 +0300 Subject: [PATCH 13/15] [BUILD] Add manifest.xml into release packages Signed-off-by: Lyupa Anastasia --- llvm-build/build.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm-build/build.py b/llvm-build/build.py index 701fe0406040..1573e2c0e310 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -1706,6 +1706,16 @@ class LlvmPackage(BuildUtils): shutil.copyfile(os.path.join(self.build_config.LLVM_BUILD_DIR, "toolchain_readme.md"), os.path.join(install_dir, "README.md")) + # Generate manifest in install_dir + manifest = os.path.join(install_dir, 'manifest.xml') + repo_tool = os.path.join(self.build_config.REPOROOT_DIR, '.repo', 'repo', 'repo') + if os.path.isfile(repo_tool): + self.logger().info('Generating manifest.') + subprocess.run([repo_tool, 'manifest', '-r', '-o', manifest], shell=False, + stdout=subprocess.PIPE, cwd=self.build_config.REPOROOT_DIR) + else: + self.logger().error('Cannot generate manifest, repo tool not found.') + # Remove unnecessary binaries. necessary_bin_files = [] self.package_clang_bin_file(necessary_bin_files, ext) -- Gitee From 39c5d20e48229fd7d53974f6a46d6caf3e46ee64 Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Tue, 21 Feb 2023 12:31:33 +0300 Subject: [PATCH 14/15] [BUILD] Use python3 by default for build.py Signed-off-by: Lyupa Anastasia --- llvm-build/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-build/build.py b/llvm-build/build.py index 1573e2c0e310..401aa68fc561 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (C) 2021 Huawei Device Co., Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); -- Gitee From 0f1fe54cf8a641a5e58436260eb4ee109f559857 Mon Sep 17 00:00:00 2001 From: weifulun Date: Wed, 22 Feb 2023 21:43:12 +0800 Subject: [PATCH 15/15] title: disable LIBUNWIND_SHARED_ENABLE by default in llvm build description: it is not supported in mac env as described in the issue test:x86 llvmts issue:https:https://gitee.com/openharmony/third_party_llvm-project/issues/I6H32M Signed-off-by: liwentao_uiw Change-Id: Ie6c20dff2e88c784a779990552a8cee6b54da9c4 --- llvm-build/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm-build/build.py b/llvm-build/build.py index 401aa68fc561..65a85c3e0612 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -436,6 +436,7 @@ class LlvmCore(BuildUtils): def llvm_compile_darwin_defines(self, llvm_defines): if self.host_is_darwin(): + llvm_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF' llvm_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF' llvm_defines['LLDB_NO_DEBUGSERVER'] = 'ON' llvm_defines['LLDB_ENABLE_PYTHON'] = 'ON' -- Gitee