| @@ -721,45 +721,83 @@ String SystemStats::getUniqueDeviceID() | |||||
| }; | }; | ||||
| #pragma pack (pop) | #pragma pack (pop) | ||||
| if (smbiosBuffer->size() < sizeof (RawSMBIOSData)) | |||||
| { | |||||
| // Malformed buffer; not enough room for RawSMBIOSData instance | |||||
| jassertfalse; | |||||
| return {}; | |||||
| } | |||||
| String uuid; | String uuid; | ||||
| const auto* asRawSMBIOSData = unalignedPointerCast<const RawSMBIOSData*> (smbiosBuffer->data()); | const auto* asRawSMBIOSData = unalignedPointerCast<const RawSMBIOSData*> (smbiosBuffer->data()); | ||||
| if (smbiosBuffer->size() < sizeof (RawSMBIOSData) + static_cast<size_t> (asRawSMBIOSData->length)) | |||||
| { | |||||
| // Malformed buffer; declared length is longer than the buffer we were given | |||||
| jassertfalse; | |||||
| return {}; | |||||
| } | |||||
| Span<const std::byte> content (smbiosBuffer->data() + sizeof (RawSMBIOSData), asRawSMBIOSData->length); | Span<const std::byte> content (smbiosBuffer->data() + sizeof (RawSMBIOSData), asRawSMBIOSData->length); | ||||
| while (! content.empty()) | while (! content.empty()) | ||||
| { | { | ||||
| const auto* header = unalignedPointerCast<const SMBIOSHeader*> (content.data()); | |||||
| const auto* stringTable = unalignedPointerCast<const char*> (content.data() + header->length); | |||||
| std::vector<const char*> strings; | |||||
| if (content.size() < sizeof (SMBIOSHeader)) | |||||
| { | |||||
| // Malformed buffer; not enough room for header | |||||
| jassertfalse; | |||||
| break; | |||||
| } | |||||
| const auto* header = unalignedPointerCast<const SMBIOSHeader*> (content.data()); | |||||
| if (content.size() < header->length) | |||||
| { | |||||
| // Malformed buffer; declared length is longer than the buffer we were given | |||||
| jassertfalse; | |||||
| break; | |||||
| } | |||||
| std::vector<std::string_view> strings; | |||||
| // Each table comprises a struct and a varying number of null terminated | // Each table comprises a struct and a varying number of null terminated | ||||
| // strings. The string section is delimited by a pair of null terminators. | // strings. The string section is delimited by a pair of null terminators. | ||||
| // Some fields in the header are indices into the string table. | // Some fields in the header are indices into the string table. | ||||
| const auto sizeofStringTable = [stringTable, &strings, &content] | |||||
| const auto endOfStringTable = [&header, &strings, &content] | |||||
| { | { | ||||
| size_t tableLen = 0; | |||||
| const auto* dataTable = unalignedPointerCast<const char*> (content.data()); | |||||
| size_t stringOffset = header->length; | |||||
| while (tableLen < content.size()) | |||||
| while (stringOffset < content.size()) | |||||
| { | { | ||||
| const auto* str = stringTable + tableLen; | |||||
| const auto n = strlen (str); | |||||
| const auto* str = dataTable + stringOffset; | |||||
| const auto maxLength = content.size() - stringOffset; | |||||
| const auto n = strnlen (str, maxLength); | |||||
| if (n == 0) | if (n == 0) | ||||
| break; | break; | ||||
| strings.push_back (str); | |||||
| tableLen += n + 1; | |||||
| strings.emplace_back (str, n); | |||||
| stringOffset += std::min (n + 1, maxLength); | |||||
| } | } | ||||
| return jmax (tableLen, (size_t) 1) + 1; | |||||
| const auto lengthAfterHeader = jmax ((size_t) header->length + 2, stringOffset + 1); | |||||
| return jmin (lengthAfterHeader, content.size()); | |||||
| }(); | }(); | ||||
| const auto stringFromOffset = [&content, &strings = std::as_const (strings)] (size_t byteOffset) | |||||
| const auto stringFromOffset = [&content, &strings] (size_t byteOffset) -> String | |||||
| { | { | ||||
| if (const auto index = std::to_integer<size_t> (content[byteOffset]); 0 < index && index <= strings.size()) | |||||
| return strings[index - 1]; | |||||
| if (! isPositiveAndBelow (byteOffset, content.size())) | |||||
| return std::string{}; | |||||
| return ""; | |||||
| const auto index = std::to_integer<size_t> (content[byteOffset]); | |||||
| if (index <= 0 || strings.size() < index) | |||||
| return std::string{}; | |||||
| const auto view = strings[index - 1]; | |||||
| return std::string { view }; | |||||
| }; | }; | ||||
| enum | enum | ||||
| @@ -793,10 +831,14 @@ String SystemStats::getUniqueDeviceID() | |||||
| uuid += "\n"; | uuid += "\n"; | ||||
| char hexBuf[(16 * 2) + 1]{}; | char hexBuf[(16 * 2) + 1]{}; | ||||
| const auto* src = content.data() + systemUUID; | |||||
| for (auto i = 0; i != 16; ++i) | |||||
| snprintf (hexBuf + 2 * i, 3, "%02hhX", std::to_integer<uint8_t> (src[i])); | |||||
| if (systemUUID + 16 < content.size()) | |||||
| { | |||||
| const auto* src = content.data() + systemUUID; | |||||
| for (auto i = 0; i != 16; ++i) | |||||
| snprintf (hexBuf + 2 * i, 3, "%02hhX", std::to_integer<uint8_t> (src[i])); | |||||
| } | |||||
| uuid += hexBuf; | uuid += hexBuf; | ||||
| uuid += "\n"; | uuid += "\n"; | ||||
| @@ -826,10 +868,9 @@ String SystemStats::getUniqueDeviceID() | |||||
| uuid += stringFromOffset (processorPartNumber); | uuid += stringFromOffset (processorPartNumber); | ||||
| uuid += "\n"; | uuid += "\n"; | ||||
| break; | break; | ||||
| } | |||||
| } | |||||
| const auto increment = header->length + sizeofStringTable; | |||||
| content = Span (content.data() + increment, content.size() - increment); | |||||
| content = Span (content.data() + endOfStringTable, content.size() - endOfStringTable); | |||||
| } | } | ||||
| return String (uuid.hashCode64()); | return String (uuid.hashCode64()); | ||||