Correct fix for long MSI interned strings (#25104)

h/t https://github.com/binref/refinery/issues/72, for #24720. No changes
file as this is an unreleased bug.

Also added output for version in the custom package parser tool.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

<!-- Note that API documentation changes are now addressed by the
product design team. -->

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] Manual QA for all new/changed functionality
This commit is contained in:
Ian Littman
2025-01-02 14:43:36 -06:00
committed by GitHub
parent d3e6311989
commit 6014908ab6
2 changed files with 9 additions and 13 deletions
+7 -11
View File
@@ -242,24 +242,20 @@ func decodeStrings(dataReader, poolReader io.Reader) ([]string, error) {
}
return nil, fmt.Errorf("failed to read pool entry: %w", err)
}
stringEntrySize := int(stringEntry.Size)
stringEntrySize := uint32(stringEntry.Size)
// For string pool entries too long for the size to fit in a single uint16, entry size is 8 bytes instead of 4,
// with the first two bytes as zeroes, the next two are the two most-significant bytes of the size, shifted
// 17 (?!?) bits to the left, the following two are the less-significant bits of the size, and the last two are
// the reference count. Verified with the OpenVPN Connect v3 installer, which has a large string blob for
// licenses where a 17-bit shift captures the length properly.
// For string pool entries too long for the size to fit in a single uint16, the format sets the size as zero,
// maintains the reference count location in the structure, then uses the following four bytes (little-endian)
// to store the string size. See https://github.com/binref/refinery/issues/72.
if stringEntry.Size == 0 && stringEntry.RefCount != 0 {
stringEntrySize = int(stringEntry.RefCount) << 17
err := binary.Read(poolReader, binary.LittleEndian, &stringEntry)
err := binary.Read(poolReader, binary.LittleEndian, &stringEntrySize)
if err != nil {
return nil, fmt.Errorf("failed to read large string pool entry: %w", err)
return nil, fmt.Errorf("failed to read size of large string in string pool: %w", err)
}
stringEntrySize += int(stringEntry.Size)
}
buf.Reset()
buf.Grow(stringEntrySize)
buf.Grow(int(stringEntrySize))
_, err = io.CopyN(&buf, dataReader, int64(stringEntrySize))
if err != nil {
return nil, fmt.Errorf("failed to read string data: %w", err)
+2 -2
View File
@@ -31,8 +31,8 @@ func main() {
}
fmt.Printf(
"- Name: '%s'\n- Bundle Identifier: '%s'\n- Package IDs: '%s'\n",
metadata.Name, metadata.BundleIdentifier, strings.Join(metadata.PackageIDs, ","),
"- Name: '%s'\n- Bundle Identifier: '%s'\n- Package IDs: '%s'\n- Version: %s\n\n",
metadata.Name, metadata.BundleIdentifier, strings.Join(metadata.PackageIDs, ","), metadata.Version,
)
}