ClickHouse
200 строк · 5.9 Кб
1#if 0
2
3#include <Functions/IFunction.h>
4#include <Functions/FunctionFactory.h>
5#include <Functions/FunctionHelpers.h>
6#include <DataTypes/DataTypeString.h>
7#include <DataTypes/DataTypesNumber.h>
8#include <Columns/ColumnString.h>
9#include <Interpreters/Context.h>
10#include <base/scope_guard.h>
11
12#include <thread>
13#include <memory>
14#include <cstdlib>
15#include <unistd.h>
16#include <sys/mman.h>
17#include <dlfcn.h>
18
19
20namespace DB
21{
22
23namespace ErrorCodes
24{
25extern const int ILLEGAL_COLUMN;
26extern const int ILLEGAL_TYPE_OF_ARGUMENT;
27extern const int BAD_ARGUMENTS;
28extern const int CANNOT_ALLOCATE_MEMORY;
29extern const int CANNOT_DLOPEN;
30extern const int LOGICAL_ERROR;
31}
32
33
34/// Various illegal actions to test diagnostic features of ClickHouse itself. Should not be enabled in production builds.
35class FunctionTrap : public IFunction
36{
37private:
38ContextPtr context;
39
40public:
41static constexpr auto name = "trap";
42static FunctionPtr create(ContextPtr context)
43{
44return std::make_shared<FunctionTrap>(context);
45}
46
47FunctionTrap(ContextPtr context_) : context(context_) {}
48
49String getName() const override
50{
51return name;
52}
53
54size_t getNumberOfArguments() const override
55{
56return 1;
57}
58
59bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
60
61DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
62{
63if (!isString(arguments[0]))
64throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The only argument for function {} must be constant String", getName());
65
66return std::make_shared<DataTypeUInt8>();
67}
68
69[[clang::optnone]]
70ColumnPtr executeImpl(const ColumnsWithTypeAndName & block, const DataTypePtr & result_type, size_t input_rows_count) const override
71{
72if (const ColumnConst * column = checkAndGetColumnConst<ColumnString>(block[0].column.get()))
73{
74String mode = column->getValue<String>();
75
76if (mode == "read nullptr c++")
77{
78volatile int x = *reinterpret_cast<const volatile int *>(0);
79(void)x;
80}
81else if (mode == "read nullptr asm")
82{
83__asm__ volatile ("movq $0, %rax");
84__asm__ volatile ("movq (%rax), %rax");
85}
86else if (mode == "illegal instruction")
87{
88__asm__ volatile ("ud2a");
89}
90else if (mode == "abort")
91{
92abort();
93}
94else if (mode == "std::terminate")
95{
96std::terminate();
97}
98else if (mode == "use after free")
99{
100int * x_ptr;
101{
102auto x = std::make_unique<int>();
103x_ptr = x.get();
104}
105*x_ptr = 1;
106(void)x_ptr;
107}
108else if (mode == "use after scope")
109{
110volatile int * x_ptr;
111[&]{
112volatile int x = 0;
113x_ptr = &x;
114(void)x;
115}();
116[&]{
117volatile int y = 1;
118*x_ptr = 2;
119(void)y;
120}();
121(void)x_ptr;
122}
123else if (mode == "uninitialized memory")
124{
125int x;
126(void)write(2, &x, sizeof(x));
127}
128else if (mode == "data race")
129{
130int x = 0;
131std::thread t1([&]{ ++x; });
132std::thread t2([&]{ ++x; });
133t1.join();
134t2.join();
135}
136else if (mode == "throw exception")
137{
138std::vector<int>().at(0);
139}
140else if (mode == "access context")
141{
142(void)context->getCurrentQueryId();
143}
144else if (mode == "stack overflow")
145{
146executeImpl(block, result_type, input_rows_count);
147}
148else if (mode == "harmful function")
149{
150double res = drand48();
151(void)res;
152}
153else if (mode == "mmap many")
154{
155std::vector<void *> maps;
156SCOPE_EXIT(
157{
158//for (void * map : maps)
159// munmap(map, 4096);
160});
161
162while (true)
163{
164void * hint = reinterpret_cast<void *>(
165std::uniform_int_distribution<intptr_t>(0x100000000000UL, 0x700000000000UL)(thread_local_rng));
166void * map = mmap(hint, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
167if (MAP_FAILED == map)
168throw ErrnoException(ErrorCodes::CANNOT_ALLOCATE_MEMORY, "Allocator: Cannot mmap");
169maps.push_back(map);
170}
171}
172else if (mode == "dlopen")
173{
174void * handle = dlopen("libc.so.6", RTLD_NOW);
175if (!handle)
176throw Exception(ErrorCodes::CANNOT_DLOPEN, "Cannot dlopen: ({})", dlerror()); // NOLINT(concurrency-mt-unsafe) // MT-Safe on Linux, see man dlerror
177}
178else if (mode == "logical error")
179{
180throw Exception(ErrorCodes::LOGICAL_ERROR, "Trap");
181}
182else
183throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown trap mode");
184}
185else
186throw Exception(ErrorCodes::ILLEGAL_COLUMN, "The only argument for function {} must be constant String", getName());
187
188return result_type->createColumnConst(input_rows_count, 0ULL);
189}
190};
191
192
193REGISTER_FUNCTION(Trap)
194{
195factory.registerFunction<FunctionTrap>();
196}
197
198}
199
200#endif
201