Skip to content

Commit 6c4d7d5

Browse files
authored
Merge pull request #71 from apple1417/master
make `DLLSafeCallback` safer
2 parents 693de07 + 224407d commit 6c4d7d5

File tree

5 files changed

+121
-81
lines changed

5 files changed

+121
-81
lines changed

src/unrealsdk/commands.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ namespace unrealsdk::commands {
66

77
namespace {
88

9-
#ifndef UNREALSDK_IMPORTING
10-
11-
utils::StringViewMap<std::wstring, DLLSafeCallback*> commands{};
9+
using DLLSafeCallback = utils::DLLSafeCallback<Callback>;
1210

11+
#ifndef UNREALSDK_IMPORTING
12+
utils::StringViewMap<std::wstring, DLLSafeCallback> commands{};
1313
#endif
1414

1515
} // namespace
@@ -18,25 +18,25 @@ utils::StringViewMap<std::wstring, DLLSafeCallback*> commands{};
1818
const std::wstring NEXT_LINE{};
1919

2020
#ifdef UNREALSDK_SHARED
21-
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback* callback);
21+
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback&& callback);
2222
#endif
2323
#ifndef UNREALSDK_IMPORTING
24-
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback* callback) {
24+
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback&& callback) {
2525
std::wstring lower_cmd(size, '\0');
2626
std::transform(cmd, cmd + size, lower_cmd.begin(), &std::towlower);
2727

2828
if (commands.contains(lower_cmd)) {
2929
return false;
3030
}
3131

32-
commands.emplace(std::move(lower_cmd), callback);
32+
commands.emplace(std::move(lower_cmd), std::move(callback));
3333
return true;
3434
}
3535
#endif
3636

3737
bool add_command(std::wstring_view cmd, const Callback& callback) {
3838
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
39-
return UNREALSDK_MANGLE(add_command)(cmd.data(), cmd.size(), new DLLSafeCallback(callback));
39+
return UNREALSDK_MANGLE(add_command)(cmd.data(), cmd.size(), {callback});
4040
}
4141

4242
#ifdef UNREALSDK_SHARED
@@ -67,9 +67,7 @@ UNREALSDK_CAPI(bool, remove_command, const wchar_t* cmd, size_t size) {
6767
return false;
6868
}
6969

70-
iter->second->destroy();
7170
commands.erase(iter);
72-
7371
return true;
7472
}
7573
#endif
@@ -101,12 +99,10 @@ bool is_command_valid(std::wstring_view line, bool direct_user_input) {
10199
void run_command(std::wstring_view line) {
102100
auto iter = commands.find(NEXT_LINE);
103101
if (iter != commands.end()) {
104-
auto callback = iter->second;
102+
auto callback = std::move(iter->second);
105103
commands.erase(iter);
106104

107-
callback->operator()(line.data(), line.size(), 0);
108-
109-
callback->destroy();
105+
callback(line.data(), line.size(), 0);
110106
return;
111107
}
112108

@@ -122,7 +118,7 @@ void run_command(std::wstring_view line) {
122118
std::wstring cmd(cmd_end - non_space, '\0');
123119
std::transform(non_space, cmd_end, cmd.begin(), &std::towlower);
124120

125-
commands.at(cmd)->operator()(line.data(), line.size(), cmd_end - line.begin());
121+
commands.at(cmd)(line.data(), line.size(), cmd_end - line.begin());
126122
}
127123

128124
#endif

src/unrealsdk/commands.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ extern const std::wstring NEXT_LINE;
3636
* points to the first whitespace char after the command (or off the end of the
3737
* string if there was none). 0 in the case of a `NEXT_LINE` match.
3838
*/
39-
using DLLSafeCallback = utils::DLLSafeCallback<void, const wchar_t*, size_t, size_t>;
40-
using Callback = DLLSafeCallback::InnerFunc;
39+
using Callback = std::function<void(const wchar_t*, size_t, size_t)>;
4140

4241
/**
4342
* @brief Adds a custom console command.

src/unrealsdk/hook_manager.cpp

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212

1313
using namespace unrealsdk::unreal;
1414

15+
namespace unrealsdk::hook_manager {
16+
17+
using DLLSafeCallback = utils::DLLSafeCallback<Callback>;
18+
1519
#pragma region Implementation
1620
#ifndef UNREALSDK_IMPORTING
17-
namespace unrealsdk::hook_manager::impl {
21+
namespace impl {
1822

1923
/*
2024
The fact that hooks run arbitrary user provided callbacks means our data structure can get modified
@@ -81,7 +85,7 @@ struct Node {
8185
std::wstring full_name;
8286
Type type;
8387
std::wstring identifier;
84-
DLLSafeCallback* callback;
88+
DLLSafeCallback callback;
8589

8690
// Using shared pointers because it's easy
8791
// Since we use std::make_shared, we're not really wasting allocations, but as a future
@@ -96,22 +100,12 @@ struct Node {
96100
std::wstring_view full_name,
97101
Type type,
98102
std::wstring_view identifier,
99-
DLLSafeCallback* callback)
103+
DLLSafeCallback&& callback)
100104
: fname(fname),
101105
full_name(full_name),
102106
type(type),
103107
identifier(identifier),
104-
callback(callback) {}
105-
Node(const Node&) = default;
106-
Node(Node&&) noexcept = default;
107-
Node& operator=(const Node&) = default;
108-
Node& operator=(Node&&) noexcept = default;
109-
~Node() {
110-
if (this->callback != nullptr) {
111-
this->callback->destroy();
112-
this->callback = nullptr;
113-
}
114-
}
108+
callback(std::move(callback)) {}
115109
};
116110

117111
namespace {
@@ -181,23 +175,24 @@ FName extract_func_obj_name(std::wstring_view func) {
181175
bool add_hook(std::wstring_view func,
182176
Type type,
183177
std::wstring_view identifier,
184-
DLLSafeCallback* callback) {
178+
DLLSafeCallback&& callback) {
185179
auto fname = extract_func_obj_name(func);
186180

187181
auto hash_idx = get_table_index(fname);
188182
auto node = hooks_hash_table.at(hash_idx);
189183
if (node == nullptr) {
190184
// This function isn't in the hash table, can just add directly.
191185
hooks_hash_table.at(hash_idx) =
192-
std::make_shared<Node>(fname, func, type, identifier, callback);
186+
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
193187
return true;
194188
}
195189

196190
// Look through hash collisions
197191
while (node->fname != fname) {
198192
if (node->next_collision == nullptr) {
199193
// We found a collision, but nothing matched our name, so add it to the end
200-
node->next_collision = std::make_shared<Node>(fname, func, type, identifier, callback);
194+
node->next_collision =
195+
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
201196
return true;
202197
}
203198
node = node->next_collision;
@@ -207,7 +202,8 @@ bool add_hook(std::wstring_view func,
207202
while (node->full_name != func) {
208203
if (node->next_function == nullptr) {
209204
// We found another function with the same fname, but nothing matches the full name
210-
node->next_function = std::make_shared<Node>(fname, func, type, identifier, callback);
205+
node->next_function =
206+
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
211207
return true;
212208
}
213209
node = node->next_function;
@@ -217,7 +213,8 @@ bool add_hook(std::wstring_view func,
217213
while (node->type != type) {
218214
if (node->next_type == nullptr) {
219215
// We found the right function, but it doesn't have any hooks of this type yet
220-
node->next_type = std::make_shared<Node>(fname, func, type, identifier, callback);
216+
node->next_type =
217+
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
221218
return true;
222219
}
223220
node = node->next_type;
@@ -228,7 +225,7 @@ bool add_hook(std::wstring_view func,
228225
if (node->next_in_collection == nullptr) {
229226
// Didn't find a matching identifier, add our new hook at the end
230227
node->next_in_collection =
231-
std::make_shared<Node>(fname, func, type, identifier, callback);
228+
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
232229
}
233230
node = node->next_in_collection;
234231
}
@@ -503,7 +500,7 @@ bool run_hooks_of_type(std::shared_ptr<Node> node, Type type, Details& hook) {
503500
bool ret = false;
504501
for (; node != nullptr; node = node->next_in_collection) {
505502
try {
506-
ret |= node->callback->operator()(hook);
503+
ret |= node->callback(hook);
507504
} catch (const std::exception& ex) {
508505
LOG(ERROR, "An exception occurred during hook processing");
509506
LOG(ERROR, L"Function: {}", hook.func.func->get_path_name());
@@ -514,14 +511,13 @@ bool run_hooks_of_type(std::shared_ptr<Node> node, Type type, Details& hook) {
514511
return ret;
515512
}
516513

517-
} // namespace unrealsdk::hook_manager::impl
514+
} // namespace impl
518515
#endif
519516
#pragma endregion
520517

521518
// =================================================================================================
522519

523520
#pragma region Public Interface
524-
namespace unrealsdk::hook_manager {
525521

526522
#ifdef UNREALSDK_SHARED
527523
UNREALSDK_CAPI(void, log_all_calls, bool should_log);
@@ -555,7 +551,7 @@ UNREALSDK_CAPI(bool,
555551
Type type,
556552
const wchar_t* identifier,
557553
size_t identifier_size,
558-
DLLSafeCallback* callback);
554+
DLLSafeCallback&& callback);
559555
#endif
560556
#ifndef UNREALSDK_IMPORTING
561557
UNREALSDK_CAPI(bool,
@@ -565,8 +561,9 @@ UNREALSDK_CAPI(bool,
565561
Type type,
566562
const wchar_t* identifier,
567563
size_t identifier_size,
568-
DLLSafeCallback* callback) {
569-
return impl::add_hook({func, func_size}, type, {identifier, identifier_size}, callback);
564+
DLLSafeCallback&& callback) {
565+
return impl::add_hook({func, func_size}, type, {identifier, identifier_size},
566+
std::move(callback));
570567
}
571568
#endif
572569

@@ -576,7 +573,7 @@ bool add_hook(std::wstring_view func,
576573
const Callback& callback) {
577574
// NOLINTBEGIN(cppcoreguidelines-owning-memory)
578575
return UNREALSDK_MANGLE(add_hook)(func.data(), func.size(), type, identifier.data(),
579-
identifier.size(), new DLLSafeCallback(callback));
576+
identifier.size(), {callback});
580577
// NOLINTEND(cppcoreguidelines-owning-memory)
581578
}
582579

src/unrealsdk/hook_manager.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ struct Details {
5555
* will not be run.
5656
* In post-hooks: ignored.
5757
*/
58-
using DLLSafeCallback = utils::DLLSafeCallback<bool, Details&>;
59-
using Callback = DLLSafeCallback::InnerFunc;
58+
using Callback = std::function<bool(Details&)>;
6059

6160
/**
6261
* @brief Toggles logging all unreal function calls. Best used in short bursts for debugging.

0 commit comments

Comments
 (0)