diff --git a/AGENTS.md b/AGENTS.md index b9b3938..0213852 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ - `cmake --build --preset debug` compiles the program and tests. - `./build/debug/wibo /path/to/program.exe` runs a Windows binary. Use `-D` (or `WIBO_DEBUG=1`) for verbose logging. Use `-C` to set the working directory. - `ctest --preset fixtures` runs the self-checking WinAPI fixtures (requires `i686-w64-mingw32-gcc` and `i686-w64-mingw32-windres`). -- `clang-format -i path/to/file.cpp` and `clang-tidy path/to/file.cpp -p build` keep contributions aligned with the repo's tooling. +- `clang-format -i path/to/file.cpp` and `clang-tidy -p build/debug path/to/file.cpp` keep contributions aligned with the repo's tooling. ## Coding Style & Naming Conventions - Formatting follows `.clang-format` (LLVM base, tabbed indentation width 4, 120 column limit). diff --git a/dll/kernel32/debugapi.cpp b/dll/kernel32/debugapi.cpp index 4abaed3..d0f7b61 100644 --- a/dll/kernel32/debugapi.cpp +++ b/dll/kernel32/debugapi.cpp @@ -2,7 +2,6 @@ #include "common.h" #include "context.h" -#include "errors.h" namespace kernel32 { diff --git a/dll/kernel32/internal.h b/dll/kernel32/internal.h index 46ecc68..2d4fd77 100644 --- a/dll/kernel32/internal.h +++ b/dll/kernel32/internal.h @@ -55,7 +55,7 @@ struct ProcessObject final : WaitableObject { static constexpr ObjectType kType = ObjectType::Process; pid_t pid; - pid_t tid; + pid_t tid = 0; int pidfd; DWORD exitCode = STILL_ACTIVE; bool forcedExitCode = false; diff --git a/dll/kernel32/winnls.cpp b/dll/kernel32/winnls.cpp index 8b70f34..8baf3f7 100644 --- a/dll/kernel32/winnls.cpp +++ b/dll/kernel32/winnls.cpp @@ -315,9 +315,9 @@ int WIN_FUNC LCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWCH lpSrcStr, int cc for (size_t i = 0; i < srcLen; ++i) { uint16_t ch = lpSrcStr[i]; if (casingFlags == 0x00000200u) { - buffer[i] = static_cast(std::towupper(static_cast(ch))); + buffer[i] = wcharToUpper(ch); } else if (casingFlags == 0x00000100u) { - buffer[i] = static_cast(std::towlower(static_cast(ch))); + buffer[i] = wcharToLower(ch); } else { buffer[i] = ch; } diff --git a/dll/msvcrt.cpp b/dll/msvcrt.cpp index c324bb6..f464a2f 100644 --- a/dll/msvcrt.cpp +++ b/dll/msvcrt.cpp @@ -1613,13 +1613,13 @@ namespace msvcrt { int WIN_ENTRY strcmp(const char *lhs, const char *rhs) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcmp(%s, %s)\n", lhs, rhs); - return ::strcmp(lhs, rhs); + return ::strcmp(lhs, rhs); } int WIN_ENTRY strncmp(const char *lhs, const char *rhs, size_t count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strncmp(%s, %s, %zu)\n", lhs, rhs, count); - return ::strncmp(lhs, rhs, count); + return ::strncmp(lhs, rhs, count); } void WIN_ENTRY _exit(int status) { @@ -2150,8 +2150,7 @@ namespace msvcrt { return ERANGE; } for (size_t i = 0; i < len; ++i) { - wchar_t ch = static_cast(str[i]); - str[i] = static_cast(std::towupper(ch)); + str[i] = wcharToUpper(str[i]); } return 0; } @@ -2167,8 +2166,7 @@ namespace msvcrt { return ERANGE; } for (size_t i = 0; i < len; ++i) { - wchar_t ch = static_cast(str[i]); - str[i] = static_cast(std::towlower(ch)); + str[i] = wcharToLower(str[i]); } return 0; } @@ -2176,7 +2174,7 @@ namespace msvcrt { wint_t WIN_ENTRY towlower(wint_t ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("towlower(%d)\n", ch); - return static_cast(std::towlower(static_cast(ch))); + return wcharToLower(ch); } unsigned int WIN_ENTRY _mbctolower(unsigned int ch) { @@ -2416,9 +2414,8 @@ namespace msvcrt { } const auto wStr = stringToWideString(wibo::guestExecutablePath.c_str()); - if (_wpgmptr) { - delete[] _wpgmptr; - } + delete[] _wpgmptr; + _wpgmptr = new uint16_t[wStr.size() + 1]; std::copy(wStr.begin(), wStr.end(), _wpgmptr); _wpgmptr[wStr.size()] = 0; @@ -2660,7 +2657,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY wcscpy_s(uint16_t *dest, size_t dest_size, const uint16_t *src){ + int WIN_ENTRY wcscpy_s(uint16_t *dest, size_t dest_size, const uint16_t *src) { HOST_CONTEXT_GUARD(); std::string src_str = wideStringToString(src); VERBOSE_LOG("wcscpy_s(%p, %zu, %p)\n", dest, dest_size, src); @@ -2670,7 +2667,7 @@ namespace msvcrt { if (wstrlen(src) + 1 > dest_size) { dest[0] = 0; - return 34; + return 34; } wstrcpy(dest, src); @@ -2753,37 +2750,60 @@ namespace msvcrt { return wstrncmp(string1, string2, count); } - int WIN_ENTRY _vswprintf_c_l(uint16_t* buffer, size_t size, const uint16_t* format, ...) { + int WIN_ENTRY _vswprintf_c_l(uint16_t *buffer, size_t size, const uint16_t *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_vswprintf_c_l(%p, %zu, %p, ...)\n", buffer, size, format); - if (!buffer || !format || size == 0) + if (!buffer || !format || size == 0) { + if (buffer && size > 0) { + buffer[0] = 0; + } return -1; + } std::string narrow_fmt = wideStringToString(format); DEBUG_LOG("\tFmt: %s\n", narrow_fmt.c_str()); - + va_list args; va_start(args, format); - int required = vsnprintf(nullptr, 0, narrow_fmt.c_str(), args); - va_end(args); + va_list argsCopy; + va_copy(argsCopy, args); + int required = vsnprintf(nullptr, 0, narrow_fmt.c_str(), argsCopy); + va_end(argsCopy); + if (required < 0) { + va_end(args); buffer[0] = 0; return -1; } - char buffer_narrow[required + 1]; - va_start(args, format); - vsnprintf(buffer_narrow, required + 1, narrow_fmt.c_str(), args); + std::vector narrowBuffer(static_cast(required) + 1); + int written = vsnprintf(narrowBuffer.data(), narrowBuffer.size(), narrow_fmt.c_str(), args); va_end(args); - DEBUG_LOG("\tBuffer: %s\n", buffer_narrow); - std::vector wide = stringToWideString(buffer_narrow); - size_t copy_len = std::min(wide.size(), size - 1); - std::memcpy(buffer, wide.data(), copy_len * sizeof(uint16_t)); - buffer[copy_len] = 0; + if (written < 0) { + buffer[0] = 0; + return -1; + } + DEBUG_LOG("\tBuffer: %s\n", narrowBuffer.data()); - return static_cast(copy_len); - // return vswprintf(buffer, size, format, args); this doesn't work because on this architecture, wchar_t is size 4, instead of size 2 + std::vector wide = stringToWideString(narrowBuffer.data()); + size_t wideLen = wide.size(); + + if (wideLen + 1 > size) { + buffer[0] = 0; + return -1; + } + if (wideLen > static_cast(std::numeric_limits::max())) { + buffer[0] = 0; + return -1; + } + + if (wideLen > 0) { + std::memcpy(buffer, wide.data(), wideLen * sizeof(uint16_t)); + } + buffer[wideLen] = 0; + + return static_cast(wideLen); } const uint16_t* WIN_ENTRY wcsstr( const uint16_t *dest, const uint16_t *src ){ diff --git a/dll/ntdll.cpp b/dll/ntdll.cpp index a485ad1..ee2d2e7 100644 --- a/dll/ntdll.cpp +++ b/dll/ntdll.cpp @@ -14,7 +14,7 @@ #include -#define PIO_APC_ROUTINE void * +using PIO_APC_ROUTINE = void *; typedef struct _IO_STATUS_BLOCK { union { @@ -109,7 +109,7 @@ std::string windowsImagePathFor(const ProcessHandleDetails &details) { if (!ec) { return files::pathToWindows(files::canonicalPath(resolved)); } - return std::string(); + return {}; } } // namespace diff --git a/dll/version.cpp b/dll/version.cpp index d90c78d..57034d5 100644 --- a/dll/version.cpp +++ b/dll/version.cpp @@ -16,11 +16,11 @@ namespace { constexpr uint32_t RT_VERSION = 16; -static uint16_t readU16(const uint8_t *ptr) { return static_cast(ptr[0] | (ptr[1] << 8)); } +uint16_t readU16(const uint8_t *ptr) { return static_cast(ptr[0] | (ptr[1] << 8)); } -static size_t align4(size_t offset) { return (offset + 3u) & ~static_cast(3u); } +size_t align4(size_t offset) { return (offset + 3u) & ~static_cast(3u); } -static std::string narrowKey(const std::u16string &key) { +std::string narrowKey(const std::u16string &key) { std::string result; result.reserve(key.size()); for (char16_t ch : key) { @@ -40,7 +40,7 @@ struct VersionBlockView { uint32_t childrenBytes = 0; }; -static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlockView &out) { +bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlockView &out) { if (available < sizeof(uint16_t) * 3) { DEBUG_LOG("header too small: available=%zu\n", available); return false; @@ -99,8 +99,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo return true; } -static bool queryVersionBlock(const uint8_t *block, size_t available, const std::vector &segments, - size_t depth, const uint8_t **outPtr, uint32_t *outLen, uint16_t *outType) { +bool queryVersionBlock(const uint8_t *block, size_t available, const std::vector &segments, size_t depth, + const uint8_t **outPtr, uint32_t *outLen, uint16_t *outType) { VersionBlockView view; if (!parseVersionBlock(block, available, view)) return false; @@ -139,7 +139,7 @@ static bool queryVersionBlock(const uint8_t *block, size_t available, const std: return false; } -static bool splitSubBlock(const std::string &subBlock, std::vector &segments) { +bool splitSubBlock(const std::string &subBlock, std::vector &segments) { segments.clear(); if (subBlock.empty() || subBlock == "\\") return true; @@ -158,7 +158,7 @@ static bool splitSubBlock(const std::string &subBlock, std::vector return true; } -static bool loadVersionResource(const char *fileName, std::vector &buffer) { +bool loadVersionResource(const char *fileName, std::vector &buffer) { if (!fileName) { wibo::lastError = ERROR_INVALID_PARAMETER; return false; diff --git a/src/strutil.cpp b/src/strutil.cpp index 40a619b..bbb1426 100644 --- a/src/strutil.cpp +++ b/src/strutil.cpp @@ -36,14 +36,26 @@ uint16_t wcharToLower(uint16_t ch) { if (ch >= 'A' && ch <= 'Z') { return static_cast(ch + ('a' - 'A')); } - wchar_t wide = static_cast(ch); - wchar_t lowered = std::towlower(wide); - if (lowered < 0 || lowered > 0xFFFF) { + wint_t wide = static_cast(ch); + wint_t lowered = std::towlower(wide); + if (lowered > 0xFFFF) { return ch; } return static_cast(lowered); } +uint16_t wcharToUpper(uint16_t ch) { + if (ch >= 'a' && ch <= 'z') { + return static_cast(ch - ('a' - 'A')); + } + wint_t wide = static_cast(ch); + wint_t uppered = std::towupper(wide); + if (uppered > 0xFFFF) { + return ch; + } + return static_cast(uppered); +} + size_t wstrlen(const uint16_t *str) { if (!str) return 0; diff --git a/src/strutil.h b/src/strutil.h index 43f1446..bc90bb9 100644 --- a/src/strutil.h +++ b/src/strutil.h @@ -24,3 +24,4 @@ void toUpperInPlace(std::string &str); std::string stringToLower(std::string_view str); std::string stringToUpper(std::string_view str); uint16_t wcharToLower(uint16_t ch); +uint16_t wcharToUpper(uint16_t ch);