From 6014908ab660840126c800edd47ae871e387f81a Mon Sep 17 00:00:00 2001 From: Ian Littman Date: Thu, 2 Jan 2025 14:43:36 -0600 Subject: [PATCH] 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. - [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 --- pkg/file/msi.go | 18 +++++++----------- tools/custom-package-parser/main.go | 4 ++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/pkg/file/msi.go b/pkg/file/msi.go index db549e9b4ea1..7271dd0d9117 100644 --- a/pkg/file/msi.go +++ b/pkg/file/msi.go @@ -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) diff --git a/tools/custom-package-parser/main.go b/tools/custom-package-parser/main.go index d64506625e2c..9820da7cb7d9 100644 --- a/tools/custom-package-parser/main.go +++ b/tools/custom-package-parser/main.go @@ -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, ) }