mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-10 04:15:39 -04:00
String safety (#1548)
* Array size UB fixes * Fix ShieldD * Remove (almost) all unsafe strcpy calls Bunch of macros. C arrays are easy enough and just need a different call. For various cases where a char* is passed around bare, I've made a TEXT_SPAN macro that can store a length too for bounds checking. * Move crash handling in safe string operations to separate TU * strcat safe version * sprintf made safe too * Fix compile
This commit is contained in:
committed by
GitHub
parent
af162bbd0a
commit
a6376368ee
@@ -0,0 +1,85 @@
|
||||
#include "dusk/string.hpp"
|
||||
#include "fmt/format.h"
|
||||
|
||||
namespace {
|
||||
void strncpyProxy(char* dst, const char* src, size_t count) {
|
||||
#if _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
strncpy(dst, src, count);
|
||||
#if _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace dusk {
|
||||
|
||||
void TextSpan::CrashSpawnEmpty() {
|
||||
CRASH("Span is empty!");
|
||||
}
|
||||
|
||||
void SafeStringCopyTruncate(char* buffer, size_t bufSize, const char* src) {
|
||||
if (buffer == src) [[unlikely]] {
|
||||
CRASH("Cannot copy string to same buffer");
|
||||
}
|
||||
|
||||
if (bufSize == 0) [[unlikely]] {
|
||||
CRASH("Target buffer cannot be size zero");
|
||||
}
|
||||
|
||||
strncpyProxy(buffer, src, bufSize);
|
||||
buffer[bufSize - 1] = 0;
|
||||
}
|
||||
|
||||
void SafeStringCopy(char* buffer, size_t bufSize, const char* src) {
|
||||
if (bufSize == 0) [[unlikely]] {
|
||||
CRASH("Target buffer cannot be size zero");
|
||||
}
|
||||
|
||||
if (buffer == src) [[unlikely]] {
|
||||
CRASH("Cannot copy string to same buffer");
|
||||
}
|
||||
|
||||
const auto srcSize = strlen(src);
|
||||
if (srcSize > bufSize - 1) [[unlikely]] {
|
||||
const auto msg = fmt::format(
|
||||
"Destination buffer too small! Need %d, have %d",
|
||||
srcSize + 1,
|
||||
bufSize);
|
||||
CRASH("%s", msg.c_str());
|
||||
}
|
||||
|
||||
strncpyProxy(buffer, src, bufSize);
|
||||
buffer[bufSize - 1] = 0;
|
||||
}
|
||||
|
||||
void SafeStringCat(char* buffer, size_t bufSize, const char* src) {
|
||||
if (bufSize == 0) [[unlikely]] {
|
||||
CRASH("Target buffer cannot be size zero");
|
||||
}
|
||||
|
||||
if (buffer == src) [[unlikely]] {
|
||||
CRASH("Cannot copy string to same buffer");
|
||||
}
|
||||
|
||||
const auto dstSize = strnlen(buffer, bufSize);
|
||||
const auto srcSize = strlen(src);
|
||||
if (dstSize + srcSize + 1 > bufSize) [[unlikely]] {
|
||||
CRASH("Destination buffer too small!");
|
||||
}
|
||||
|
||||
memcpy(buffer + dstSize, src, srcSize);
|
||||
buffer[dstSize + srcSize] = 0;
|
||||
}
|
||||
|
||||
int SafeStringVPrintf(char* buffer, size_t bufSize, const char* src, std::va_list args) {
|
||||
if (bufSize == 0) [[unlikely]] {
|
||||
CRASH("Target buffer cannot be size zero");
|
||||
}
|
||||
|
||||
return vsnprintf(buffer, bufSize, src, args);
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
Reference in New Issue
Block a user