Skip to content

Commit

Permalink
Correct fix for long MSI interned strings (#25104)
Browse files Browse the repository at this point in the history
h/t binref/refinery#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
  • Loading branch information
iansltx authored Jan 2, 2025
1 parent d3e6311 commit 6014908
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 13 deletions.
18 changes: 7 additions & 11 deletions pkg/file/msi.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions tools/custom-package-parser/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
}

Expand Down

0 comments on commit 6014908

Please sign in to comment.