@@ -3091,29 +3091,30 @@ struct VM {
30913091 }
30923092
30933093 struct brand {
3094- static char brand_cache[ 512 ] ;
3094+ static std::string brand_cache;
30953095 static bool cached;
30963096
3097- static void store (const char * s) {
3098- str_copy ( brand_cache, s, sizeof (brand_cache)) ;
3097+ static void store (const std::string& s) {
3098+ brand_cache = s ;
30993099 cached = true ;
3100+ debug (" VM::brand(): cached brand string" );
31003101 }
31013102
31023103 static bool is_cached () { return cached; }
3103- static const char * fetch () { return brand_cache; }
3104+ static std::string fetch () { return brand_cache; }
31043105 };
31053106
31063107 struct multi_brand {
3107- static char brand_cache[ 1024 ] ;
3108+ static std::string brand_cache;
31083109 static bool cached;
31093110
3110- static void store (const char * s) {
3111- str_copy ( brand_cache, s, sizeof (brand_cache)) ;
3111+ static void store (const std::string& s) {
3112+ brand_cache = s ;
31123113 cached = true ;
31133114 }
31143115
31153116 static bool is_cached () { return cached; }
3116- static const char * fetch () { return brand_cache; }
3117+ static std::string fetch () { return brand_cache; }
31173118 };
31183119
31193120 // helper specifically for conclusion strings
@@ -4706,7 +4707,10 @@ struct VM {
47064707 #endif
47074708 };
47084709
4709- thread_local u32 aux = 0 ;
4710+ #if (MSVC)
4711+ thread_local u32 aux = 0 ;
4712+ #endif
4713+
47104714 auto cpuid = [](unsigned int leaf) noexcept -> u64 {
47114715 #if (MSVC)
47124716 // make regs volatile so writes cannot be optimized out, if this isn't added and the code is compiled in release mode, cycles would be around 40 even under Hyper-V
@@ -11933,8 +11937,7 @@ struct VM {
1193311937 debug (" VM::brand(): returned multi brand from cache" );
1193411938 return memo::multi_brand::fetch ();
1193511939 }
11936- }
11937- else {
11940+ } else {
1193811941 if (memo::brand::is_cached ()) {
1193911942 debug (" VM::brand(): returned brand from cache" );
1194011943 return memo::brand::fetch ();
@@ -11990,6 +11993,15 @@ struct VM {
1199011993 std::array<brand_element_t , core::MAX_BRANDS> active_brands;
1199111994 size_t active_count = 0 ;
1199211995
11996+ // wrappers for simplicity, these will most likely be inlined by the compiler anyway
11997+ auto fetch_brand_name = [&](const size_t index) -> const char * {
11998+ return active_brands[index].first ;
11999+ };
12000+
12001+ auto fetch_brand_score = [&](const size_t index) -> brand_score_t {
12002+ return active_brands[index].second ;
12003+ };
12004+
1199312005 for (size_t i = 0 ; i < core::brand_count; ++i) {
1199412006 if (core::brand_scoreboard[i].score > 0 ) {
1199512007 active_brands[active_count++] = std::make_pair (core::brand_scoreboard[i].name , core::brand_scoreboard[i].score );
@@ -11998,48 +12010,62 @@ struct VM {
1199812010
1199912011 // if all brands have a point of 0, return "Unknown"
1200012012 if (active_count == 0 ) {
12013+ memo::brand::store (brands::NULL_BRAND);
1200112014 return brands::NULL_BRAND;
1200212015 }
12003-
12004- // if there's only a single brand, return it immediately
12005- // We skip this early return if the single brand is HYPERV_ARTIFACT,
12006- // so that the removal logic at the end of the function can process it
12007- if (active_count == 1 && active_brands[0 ].first != TMP_HYPERV_ARTIFACT) {
12008- return active_brands[0 ].first ;
12009- }
12010-
12016+
1201112017 // helper lambdas for array manipulation
12012- auto find_index = [&](const char * name) noexcept -> int {
12018+ auto find_index = [&](const char * name) noexcept -> i8 {
1201312019 for (size_t i = 0 ; i < active_count; ++i) {
1201412020 // pointer comparison is sufficient for static brands
12015- if (active_brands[i].first == name) return static_cast <int >(i);
12021+ if (fetch_brand_name (i) == name) {
12022+ return static_cast <i8 >(i);
12023+ }
1201612024 }
1201712025 return -1 ;
1201812026 };
1201912027
12020- auto remove_at = [&](int index) noexcept {
12028+ auto remove_at = [&](const u8 index) noexcept {
1202112029 if (index >= 0 && index < static_cast <int >(active_count)) {
1202212030 if (index != static_cast <int >(active_count - 1 )) {
1202312031 active_brands[static_cast <size_t >(index)] = active_brands[active_count - 1 ];
1202412032 }
1202512033 active_count--;
1202612034 }
1202712035 };
12028-
12036+
1202912037 // remove Hyper-V artifacts if found with other brands
1203012038 if (active_count > 1 ) {
12031- const int idx = find_index (TMP_HYPERV_ARTIFACT);
12039+ const i8 idx = find_index (TMP_HYPERV_ARTIFACT);
1203212040 if (idx != -1 ) {
1203312041 remove_at (idx);
1203412042 }
1203512043 }
1203612044
12045+ // if there's only a single brand, return it immediately
12046+ // We skip this early return if the single brand is HYPERV_ARTIFACT,
12047+ // but we must also nullify the result if the score is above 0,
12048+ // which would most likely indicate a hardened VM instead and return "Unknown".
12049+ if (active_count == 1 ) {
12050+ const std::string& initial_brand = fetch_brand_name (0 );
12051+
12052+ if (initial_brand == TMP_HYPERV_ARTIFACT) {
12053+ if (score > 0 ) {
12054+ memo::brand::store (brands::NULL_BRAND);
12055+ return brands::NULL_BRAND;
12056+ }
12057+ }
12058+
12059+ memo::brand::store (initial_brand);
12060+ return initial_brand;
12061+ }
12062+
1203712063 // merge 2 brands
1203812064 auto merge = [&](const char * a, const char * b, const char * result) noexcept -> void {
12039- int idx_a = find_index (a);
12065+ i8 idx_a = find_index (a);
1204012066 if (idx_a == -1 ) return ;
1204112067
12042- int idx_b = find_index (b);
12068+ i8 idx_b = find_index (b);
1204312069 if (idx_b == -1 ) return ;
1204412070
1204512071 remove_at (idx_a);
@@ -12051,11 +12077,11 @@ struct VM {
1205112077
1205212078 // same as above, but for 3
1205312079 auto triple_merge = [&](const char * a, const char * b, const char * c, const char * result) noexcept -> void {
12054- int idx_a = find_index (a);
12080+ i8 idx_a = find_index (a);
1205512081 if (idx_a == -1 ) return ;
12056- int idx_b = find_index (b);
12082+ i8 idx_b = find_index (b);
1205712083 if (idx_b == -1 ) return ;
12058- int idx_c = find_index (c);
12084+ i8 idx_c = find_index (c);
1205912085 if (idx_c == -1 ) return ;
1206012086
1206112087 remove_at (idx_a);
@@ -12064,20 +12090,10 @@ struct VM {
1206412090
1206512091 active_brands[active_count++] = std::make_pair (result, 2 );
1206612092 };
12067-
12068- // some edgecase handling for Hyper-V and VirtualPC
12069- int idx_hv = find_index (TMP_HYPERV);
12070- int idx_vpc = find_index (TMP_VPC);
12071-
12072- if (idx_hv != -1 && idx_vpc != -1 ) {
12073- // existence is confirmed by index != -1
12074- merge (TMP_VPC, TMP_HYPERV, TMP_HYPERV_VPC);
12075- }
12076- else if (idx_hv != -1 && idx_vpc == -1 ) {
12077- // logic handled by merge check essentially
12078- }
12079-
12093+
1208012094 // Brand post-processing / merging
12095+ merge (TMP_VPC, TMP_HYPERV, TMP_HYPERV_VPC);
12096+
1208112097 merge (TMP_AZURE, TMP_HYPERV, TMP_AZURE);
1208212098 merge (TMP_AZURE, TMP_VPC, TMP_AZURE);
1208312099 merge (TMP_AZURE, TMP_HYPERV_VPC, TMP_AZURE);
@@ -12086,6 +12102,11 @@ struct VM {
1208612102 merge (TMP_KVM, TMP_HYPERV, TMP_KVM_HYPERV);
1208712103 merge (TMP_QEMU, TMP_HYPERV, TMP_QEMU_KVM_HYPERV);
1208812104 merge (TMP_QEMU_KVM, TMP_HYPERV, TMP_QEMU_KVM_HYPERV);
12105+
12106+ merge (TMP_KVM, TMP_HYPERV_VPC, TMP_KVM_HYPERV);
12107+ merge (TMP_QEMU, TMP_HYPERV_VPC, TMP_QEMU_KVM_HYPERV);
12108+ merge (TMP_QEMU_KVM, TMP_HYPERV_VPC, TMP_QEMU_KVM_HYPERV);
12109+
1208912110 merge (TMP_KVM, TMP_KVM_HYPERV, TMP_KVM_HYPERV);
1209012111 merge (TMP_QEMU, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV);
1209112112 merge (TMP_QEMU_KVM, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV);
@@ -12105,61 +12126,44 @@ struct VM {
1210512126 merge (TMP_VMWARE_HARD, TMP_GSX, TMP_VMWARE_HARD);
1210612127 merge (TMP_VMWARE_HARD, TMP_WORKSTATION, TMP_VMWARE_HARD);
1210712128
12108- // determine threshold (150 or 300)
12109- u16 confirmed_vm_threshold = threshold_score;
12110- if (core::is_enabled (flags, HIGH_THRESHOLD)) {
12111- confirmed_vm_threshold = high_threshold_score;
12112- }
12113-
12114- // check if Hyper-V artifact is present
12115- const int idx_art = find_index (TMP_HYPERV_ARTIFACT);
12116- if (idx_art != -1 ) {
12117- // If score confirms it is a VM, remove the "Artifact" label (because we're in a VM, not in a host machine)
12118- // so it falls back to "Unknown" if no other brands exist
12119- if (score >= confirmed_vm_threshold) {
12120- remove_at (idx_art);
12121- }
12122- }
12123-
1212412129 if (active_count > 1 ) {
1212512130 std::sort (active_brands.begin (), active_brands.begin () + static_cast <std::ptrdiff_t >(active_count), [](
1212612131 const brand_element_t & a,
1212712132 const brand_element_t & b
12128- ) {
12129- return a.second > b.second ;
12133+ ) {
12134+ return a.second > b.second ; // .second = brand score (usually u8)
1213012135 });
1213112136 }
1213212137
1213312138 #ifdef __VMAWARE_DEBUG__
1213412139 for (size_t i = 0 ; i < active_count; ++i) {
12135- debug (" scoreboard: " , (int )active_brands[i]. second , " : " , active_brands[i]. first );
12140+ debug (" scoreboard: " , (brand_score_t ) fetch_brand_score (i) , " : " , fetch_brand_name (i) );
1213612141 }
1213712142 #endif
1213812143
12139- if (active_count > 0 ) {
12140- if (!is_multiple) {
12141- memo::brand::store (active_brands[0 ].first );
12142- debug (" VM::brand(): cached brand string" );
12143- return memo::brand::fetch ();
12144- }
12145- else {
12146- char * buffer = memo::multi_brand::brand_cache;
12147- buffer[0 ] = ' \0 ' ;
12148- const size_t buf_size = sizeof (memo::multi_brand::brand_cache);
12144+ if (active_count == 0 ) {
12145+ memo::brand::store (brands::NULL_BRAND);
12146+ return brands::NULL_BRAND;
12147+ }
1214912148
12150- str_copy (buffer, active_brands[0 ].first , buf_size);
12151- for (size_t i = 1 ; i < active_count; i++) {
12152- str_cat (buffer, " or " , buf_size);
12153- str_cat (buffer, active_brands[i].first , buf_size);
12154- }
12149+ if (is_multiple) {
12150+ std::string buffer = {};
12151+ buffer += fetch_brand_name (0 );
1215512152
12156- memo::multi_brand::cached = true ;
12157- debug ( " VM::brand(): cached multiple brand string " ) ;
12158- return memo::multi_brand::fetch ( );
12153+ for ( size_t i = 1 ; i < active_count; i++) {
12154+ buffer += " or " ;
12155+ buffer += fetch_brand_name (i );
1215912156 }
12157+
12158+ memo::multi_brand::store (buffer);
12159+ debug (" VM::brand(): cached multiple brand string" );
12160+ return buffer;
1216012161 }
1216112162
12162- return brands::NULL_BRAND;
12163+ const std::string& result_brand = fetch_brand_name (0 );
12164+
12165+ memo::brand::store (result_brand);
12166+ return result_brand;
1216312167 }
1216412168
1216512169
@@ -12945,8 +12949,8 @@ size_t VM::core::brand_count = []() -> size_t {
1294512949
1294612950// initial definitions for cache items because C++ forbids in-class initializations
1294712951std::array<VM::memo::cache_entry, VM::enum_size + 1 > VM::memo::cache_table{};
12948- char VM::memo::brand::brand_cache[ 512 ] = { 0 } ;
12949- char VM::memo::multi_brand::brand_cache[ 1024 ] = { 0 } ;
12952+ std::string VM::memo::brand::brand_cache = " " ;
12953+ std::string VM::memo::multi_brand::brand_cache = " " ;
1295012954char VM::memo::cpu_brand::brand_cache[128 ] = { 0 };
1295112955char VM::memo::bios_info::manufacturer[256 ] = { 0 };
1295212956char VM::memo::bios_info::model[128 ] = { 0 };
0 commit comments