Skip to content

Preserve unrepresentable raw action values as references#203

Open
sfly9 wants to merge 1 commit into
electrikmilk:mainfrom
sfly9:preserve-raw-action-references
Open

Preserve unrepresentable raw action values as references#203
sfly9 wants to merge 1 commit into
electrikmilk:mainfrom
sfly9:preserve-raw-action-references

Conversation

@sfly9

@sfly9 sfly9 commented Jul 8, 2026

Copy link
Copy Markdown

Summary

Decompiling a raw action parameter whose value doesn't match any shape decompValueObject knows how to represent (e.g. a third-party app's opaque struct, such as a HomeKit scene selection) currently produces a silent empty string — the underlying data is discarded with no indication anything was lost. I hit this decompiling a Shortcut that uses a HomeKit trigger action.

This routes those values through the existing #ref mechanism instead of discarding them:

  • decompile.go: when decompValueObject can't represent a raw action parameter, register the value as a reference and emit a ${identifier} placeholder in the rawAction dict, with a decompWarning (existing helper, same pattern as the one at decompile.go:1186) noting a reference was substituted. Handles naming collisions when the same parameter key produces different values across multiple actions in the same Shortcut.
  • raw_actions.go: ${...} placeholders inside a rawAction() dict now also resolve against declared #refs (only when there's no @, since variable references always use @), not just variable names.
  • references.go: reference hashes now survive raw []byte (plist <data>) values. JSON has no native binary type, so without this a <data> element would silently round-trip back as an indistinguishable <string> — a correctness bug in the existing file/media reference path that this change also happens to fix, even though those reference types don't currently carry byte data.

Testing

  • go build ./...
  • go test -run TestCherriNoSign and go test -run TestDecomp — pass, including the new test case
  • golangci-lint run ./... — 22 pre-existing findings, confirmed identical (same count, same lines) on unmodified main; this change introduces none
  • Added a case to tests/raw-action-variable-values.cherri exercising a #ref used inside a rawAction() dict (the #ref hash was generated by the compiler itself against a synthetic fixture, not hand-written)
  • Manually verified against a real Shortcut using a HomeKit trigger action: recompiled the decompiled output and diffed the resulting plist's parameter value against the original — byte-for-byte identical, including the binary payload

Decompiling a raw action parameter that doesn't match any known
value shape (e.g. a third-party app's opaque struct, such as a
HomeKit scene selection silently produced an empty string,
discarding the underlying data with no indication anything was
lost.

Route these values through the existing #ref mechanism instead:
register the value as a reference and emit a
placeholder in the rawAction dict, with a decompWarning noting a
reference was used in place of literal Cherri source. Reference
hashes now also survive raw []byte (plist <data>) values, which
would otherwise become an indistinguishable base64 <string> when
round-tripped through JSON.

Verified against a real Shortcut using a third-party app's
HomeKit trigger action: the recompiled plist's parameter value is
byte-for-byte identical to the original, including the binary
payload. Added a tests/raw-action-variable-values.cherri case
exercising a #ref used inside a rawAction() dict.
EOF
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant