From b451ba82e0adb61c59b574b374a6f10d3bc6350d Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Tue, 15 Nov 2016 22:19:59 +0000 Subject: [PATCH] [C API] Prevent nullptr dereferences in C API for counting attributes. See https://reviews.llvm.org/D26392 Patch by @maleadt git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287044 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Bindings/llvm-c/callsite_attributes.ll | 12 ++++ test/Bindings/llvm-c/function_attributes.ll | 7 ++ tools/llvm-c-test/CMakeLists.txt | 1 + tools/llvm-c-test/attributes.c | 75 +++++++++++++++++++++ tools/llvm-c-test/llvm-c-test.h | 4 ++ tools/llvm-c-test/main.c | 4 ++ 6 files changed, 103 insertions(+) create mode 100644 test/Bindings/llvm-c/callsite_attributes.ll create mode 100644 test/Bindings/llvm-c/function_attributes.ll create mode 100644 tools/llvm-c-test/attributes.c diff --git a/test/Bindings/llvm-c/callsite_attributes.ll b/test/Bindings/llvm-c/callsite_attributes.ll new file mode 100644 index 00000000000..4b4e488a695 --- /dev/null +++ b/test/Bindings/llvm-c/callsite_attributes.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-c-test --test-callsite-attributes < %t.bc +; This used to segfault + +define void @Y() { + ret void +} + +define void @X() { + call void @X() + ret void +} diff --git a/test/Bindings/llvm-c/function_attributes.ll b/test/Bindings/llvm-c/function_attributes.ll new file mode 100644 index 00000000000..9aa1787fde7 --- /dev/null +++ b/test/Bindings/llvm-c/function_attributes.ll @@ -0,0 +1,7 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-c-test --test-function-attributes < %t.bc +; This used to segfault + +define void @X() { + ret void +} diff --git a/tools/llvm-c-test/CMakeLists.txt b/tools/llvm-c-test/CMakeLists.txt index 858f2b07214..a2bde0d9714 100644 --- a/tools/llvm-c-test/CMakeLists.txt +++ b/tools/llvm-c-test/CMakeLists.txt @@ -36,6 +36,7 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE) endif () add_llvm_tool(llvm-c-test + attributes.c calc.c diagnostic.c disassemble.c diff --git a/tools/llvm-c-test/attributes.c b/tools/llvm-c-test/attributes.c new file mode 100644 index 00000000000..7f07a220ad3 --- /dev/null +++ b/tools/llvm-c-test/attributes.c @@ -0,0 +1,75 @@ +/*===-- attributes.c - tool for testing libLLVM and llvm-c API ------------===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file implements the --test-attributes and --test-callsite-attributes *| +|* commands in llvm-c-test. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c-test.h" + +#include + +int llvm_test_function_attributes(void) { + LLVMEnablePrettyStackTrace(); + + LLVMModuleRef M = llvm_load_module(false, true); + + LLVMValueRef F = LLVMGetFirstFunction(M); + while (F) { + // Read attributes + for (int Idx = LLVMAttributeFunctionIndex, ParamCount = LLVMCountParams(F); + Idx <= ParamCount; ++Idx) { + int AttrCount = LLVMGetAttributeCountAtIndex(F, Idx); + LLVMAttributeRef *Attrs = + (LLVMAttributeRef *)malloc(AttrCount * sizeof(LLVMAttributeRef)); + LLVMGetAttributesAtIndex(F, Idx, Attrs); + free(Attrs); + } + F = LLVMGetNextFunction(F); + } + + LLVMDisposeModule(M); + + return 0; +} + +int llvm_test_callsite_attributes(void) { + LLVMEnablePrettyStackTrace(); + + LLVMModuleRef M = llvm_load_module(false, true); + + LLVMValueRef F = LLVMGetFirstFunction(M); + while (F) { + LLVMBasicBlockRef BB; + for (BB = LLVMGetFirstBasicBlock(F); BB; BB = LLVMGetNextBasicBlock(BB)) { + LLVMValueRef I; + for (I = LLVMGetFirstInstruction(BB); I; I = LLVMGetNextInstruction(I)) { + if (LLVMIsACallInst(I)) { + // Read attributes + for (int Idx = LLVMAttributeFunctionIndex, + ParamCount = LLVMCountParams(F); + Idx <= ParamCount; ++Idx) { + int AttrCount = LLVMGetCallSiteAttributeCount(I, Idx); + LLVMAttributeRef *Attrs = (LLVMAttributeRef *)malloc( + AttrCount * sizeof(LLVMAttributeRef)); + LLVMGetCallSiteAttributes(I, Idx, Attrs); + free(Attrs); + } + } + } + } + + F = LLVMGetNextFunction(F); + } + + LLVMDisposeModule(M); + + return 0; +} diff --git a/tools/llvm-c-test/llvm-c-test.h b/tools/llvm-c-test/llvm-c-test.h index 0d1ade093bc..0401f1dbae3 100644 --- a/tools/llvm-c-test/llvm-c-test.h +++ b/tools/llvm-c-test/llvm-c-test.h @@ -52,6 +52,10 @@ int llvm_echo(void); // diagnostic.c int llvm_test_diagnostic_handler(void); +// attributes.c +int llvm_test_function_attributes(); +int llvm_test_callsite_attributes(); + #ifdef __cplusplus } #endif /* !defined(__cplusplus) */ diff --git a/tools/llvm-c-test/main.c b/tools/llvm-c-test/main.c index 90d35017785..9bc0c96c3d6 100644 --- a/tools/llvm-c-test/main.c +++ b/tools/llvm-c-test/main.c @@ -88,6 +88,10 @@ int main(int argc, char **argv) { return llvm_add_named_metadata_operand(); } else if (argc == 2 && !strcmp(argv[1], "--set-metadata")) { return llvm_set_metadata(); + } else if (argc == 2 && !strcmp(argv[1], "--test-function-attributes")) { + return llvm_test_function_attributes(); + } else if (argc == 2 && !strcmp(argv[1], "--test-callsite-attributes")) { + return llvm_test_callsite_attributes(); } else if (argc == 2 && !strcmp(argv[1], "--echo")) { return llvm_echo(); } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { -- 2.40.0