Skip to content

Commit b6a576c

Browse files
Intercept loader_log in testing framework
Allows capturing the output of loader_log and comparing it with expected values using fputs/fputc on *nix, and OutputDebugString on Windows. This interception is necessary due to the differing behavior between the debug log (through debug utils messenger) and the actual stderr output.
1 parent 0763e36 commit b6a576c

File tree

4 files changed

+131
-84
lines changed

4 files changed

+131
-84
lines changed

tests/framework/shim/shim.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,15 @@ struct FrameworkEnvironment; // forward declaration
134134
// Necessary to have inline definitions as shim is a dll and thus functions
135135
// defined in the .cpp wont be found by the rest of the application
136136
struct PlatformShim {
137-
PlatformShim() = default;
138-
PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) {}
137+
PlatformShim() { fputs_stderr_log.reserve(65536); }
138+
PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) { fputs_stderr_log.reserve(65536); }
139139

140140
// Used to get info about which drivers & layers have been added to folders
141141
std::vector<fs::FolderManager>* folders;
142142

143+
// Captures the output to stderr from fputs & fputc - aka the output of loader_log()
144+
std::string fputs_stderr_log;
145+
143146
// Test Framework interface
144147
void reset();
145148

@@ -156,6 +159,9 @@ struct PlatformShim {
156159
void add_manifest(ManifestCategory category, std::filesystem::path const& path);
157160
void add_unsecured_manifest(ManifestCategory category, std::filesystem::path const& path);
158161

162+
void clear_logs() { fputs_stderr_log.clear(); }
163+
bool find_in_log(std::string const& search_text) const { return fputs_stderr_log.find(search_text) != std::string::npos; }
164+
159165
// platform specific shim interface
160166
#if defined(WIN32)
161167
// Control Platform Elevation Level

tests/framework/shim/unix_shim.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
6363
#if defined(HAVE___SECURE_GETENV)
6464
#define __SECURE_GETENV_FUNC_NAME __secure_getenv
6565
#endif
66+
#define PRINTF_FUNC_NAME printf
67+
#define FPUTS_FUNC_NAME fputs
68+
#define FPUTC_FUNC_NAME fputc
6669
#elif defined(__APPLE__)
6770
#define OPENDIR_FUNC_NAME my_opendir
6871
#define READDIR_FUNC_NAME my_readdir
@@ -80,6 +83,8 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
8083
#define __SECURE_GETENV_FUNC_NAME my__secure_getenv
8184
#endif
8285
#endif
86+
#define FPUTS_FUNC_NAME my_fputs
87+
#define FPUTC_FUNC_NAME my_fputc
8388
#endif
8489

8590
using PFN_OPENDIR = DIR* (*)(const char* path_name);
@@ -93,6 +98,8 @@ using PFN_GETEGID = gid_t (*)(void);
9398
#if defined(HAVE_SECURE_GETENV) || defined(HAVE___SECURE_GETENV)
9499
using PFN_SEC_GETENV = char* (*)(const char* name);
95100
#endif
101+
using PFN_FPUTS = int (*)(const char* str, FILE* stream);
102+
using PFN_FPUTC = int (*)(int c, FILE* stream);
96103

97104
#if defined(__APPLE__)
98105
#define real_opendir opendir
@@ -109,6 +116,8 @@ using PFN_SEC_GETENV = char* (*)(const char* name);
109116
#if defined(HAVE___SECURE_GETENV)
110117
#define real__secure_getenv __secure_getenv
111118
#endif
119+
#define real_fputs fputs
120+
#define real_fputc fputc
112121
#else
113122
PFN_OPENDIR real_opendir = nullptr;
114123
PFN_READDIR real_readdir = nullptr;
@@ -124,6 +133,8 @@ PFN_SEC_GETENV real_secure_getenv = nullptr;
124133
#if defined(HAVE___SECURE_GETENV)
125134
PFN_SEC_GETENV real__secure_getenv = nullptr;
126135
#endif
136+
PFN_FPUTS real_fputs = nullptr;
137+
PFN_FPUTC real_fputc = nullptr;
127138
#endif
128139

129140
FRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
@@ -327,6 +338,27 @@ FRAMEWORK_EXPORT char* __SECURE_GETENV_FUNC_NAME(const char* name) {
327338
}
328339
#endif
329340
#endif
341+
342+
FRAMEWORK_EXPORT int FPUTS_FUNC_NAME(const char* str, FILE* stream) {
343+
#if !defined(__APPLE__)
344+
if (!real_fputs) real_fputs = (PFN_FPUTS)dlsym(RTLD_NEXT, "fputs");
345+
#endif
346+
if (stream == stderr) {
347+
platform_shim.fputs_stderr_log += str;
348+
}
349+
return real_fputs(str, stream);
350+
}
351+
352+
FRAMEWORK_EXPORT int FPUTC_FUNC_NAME(int ch, FILE* stream) {
353+
#if !defined(__APPLE__)
354+
if (!real_fputc) real_fputc = (PFN_FPUTC)dlsym(RTLD_NEXT, "fputc");
355+
#endif
356+
if (stream == stderr) {
357+
platform_shim.fputs_stderr_log += ch;
358+
}
359+
return real_fputc(ch, stream);
360+
}
361+
330362
#if defined(__APPLE__)
331363
FRAMEWORK_EXPORT CFBundleRef my_CFBundleGetMainBundle() {
332364
static CFBundleRef global_bundle{};
@@ -383,6 +415,8 @@ __attribute__((used)) static Interposer _interpose__secure_getenv MACOS_ATTRIB =
383415
VOIDP_CAST(__secure_getenv)};
384416
#endif
385417
#endif
418+
__attribute__((used)) static Interposer _interpose_fputs MACOS_ATTRIB = {VOIDP_CAST(my_fputs), VOIDP_CAST(fputs)};
419+
__attribute__((used)) static Interposer _interpose_fputc MACOS_ATTRIB = {VOIDP_CAST(my_fputc), VOIDP_CAST(fputc)};
386420
__attribute__((used)) static Interposer _interpose_CFBundleGetMainBundle MACOS_ATTRIB = {VOIDP_CAST(my_CFBundleGetMainBundle),
387421
VOIDP_CAST(CFBundleGetMainBundle)};
388422
__attribute__((used)) static Interposer _interpose_CFBundleCopyResourcesDirectoryURL MACOS_ATTRIB = {

tests/framework/shim/windows_shim.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
#include <ntstatus.h>
3232
#endif
3333

34+
#include <windows.h>
35+
#include <debugapi.h>
36+
3437
#include "shim.h"
3538

3639
#include "detours.h"
@@ -405,6 +408,15 @@ LONG WINAPI ShimGetPackagePathByFullName(_In_ PCWSTR packageFullName, _Inout_ UI
405408
return 0;
406409
}
407410

411+
using PFN_OutputDebugStringA = void(__stdcall *)(LPCSTR lpOutputString);
412+
static PFN_OutputDebugStringA fp_OutputDebugStringA = OutputDebugStringA;
413+
414+
void __stdcall intercept_OutputDebugStringA(LPCSTR lpOutputString) {
415+
if (lpOutputString != nullptr) {
416+
platform_shim.fputs_stderr_log += lpOutputString;
417+
}
418+
}
419+
408420
// Initialization
409421
void WINAPI DetourFunctions() {
410422
if (!gdi32_dll) {
@@ -454,6 +466,7 @@ void WINAPI DetourFunctions() {
454466
DetourAttach(&(PVOID &)fpRegCloseKey, (PVOID)ShimRegCloseKey);
455467
DetourAttach(&(PVOID &)fpGetPackagesByPackageFamily, (PVOID)ShimGetPackagesByPackageFamily);
456468
DetourAttach(&(PVOID &)fpGetPackagePathByFullName, (PVOID)ShimGetPackagePathByFullName);
469+
DetourAttach(&(PVOID &)fp_OutputDebugStringA, (PVOID)intercept_OutputDebugStringA);
457470
LONG error = DetourTransactionCommit();
458471

459472
if (error != NO_ERROR) {
@@ -483,6 +496,7 @@ void DetachFunctions() {
483496
DetourDetach(&(PVOID &)fpRegCloseKey, (PVOID)ShimRegCloseKey);
484497
DetourDetach(&(PVOID &)fpGetPackagesByPackageFamily, (PVOID)ShimGetPackagesByPackageFamily);
485498
DetourDetach(&(PVOID &)fpGetPackagePathByFullName, (PVOID)ShimGetPackagePathByFullName);
499+
DetourDetach(&(PVOID &)fp_OutputDebugStringA, (PVOID)intercept_OutputDebugStringA);
486500
DetourTransactionCommit();
487501
}
488502

0 commit comments

Comments
 (0)