Skip to content

Conversation

@mpwarres
Copy link
Contributor

@mpwarres mpwarres commented Oct 9, 2025

Document the de-facto serialization format used by the various proxy-wasm SDKs (C++, Rust, Go) to serialize path_data arguments for the proxy_get_property and proxy_set_property hostcalls.

Copy link
Member

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then concatenated in sequence to form the `path_data` argument.

e.g. the path segments `["foo", "bar"]` would be serialized as:
- `0x66`, `0x6f`, `0x6f`, `0x00`, `0x62`, `0x61`, `0x72`, `0x00`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not entirely correct. There is no NULL character at the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, while you're right about the Rust and Go SDKs not including a NULL char at the end, the C++ SDK does: code.

I can fix the C++ SDK to trim the last NULL char, but I think that host implementations would still need to tolerate a terminating NULL char in order to work with C++ plugins compiled prior to this fix. The Envoy implementation of getProperty does appear to tolerate this.

ISTM that in order to document the acceptable range of behaviors, the spec should say that path_data can (but is not required to) contain a terminating NULLchar. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to state that null char is a separator, but host implementations should also tolerate it as a terminator if present.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The segments could be empty, so the distinction is important actually. Although I don't recall if we ever tested it with empty segments, so it's under-specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reading of this logic in Envoy::Extensions::Common::Wasm::getProperty() is that:

  1. It handles each segment by finding the next null char (if any), and taking the substring up until that (which could be empty)
  2. It bumps start to the previous end (which doesn't include null char) + 1 (skipping over the null char, if present)
  3. Loop terminates when start >= path.size(). In the case of a path that does include a terminating null char, start will end up == path.size(), while in the case of a path that doesn't, start will end up equal to path.size() + 1. Either way, the loop terminates.

So I think it's still accurate to say that null char is a separator (which doesn't rule out empty segments), and that an optional terminating null char should be tolerated by host implementations.

If there's a different wording that either of you would prefer, I'm open to suggestions. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current text works fine for me, thanks!

To be honest, I'm actually surprised that the trailing \0 works fine, since I recall having issues with it, hence the extra code to remove it in Rust & Go SDKs... But I was also under the impression that the serialization format came from CEL and wasn't our own invention, so my memory is clearly a little hazy around those details.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binary format didn't come from CEL. The constraint was that "." wasn't good enough since segments can contain ".". But you should feel free to revise for vNext with a more standard list packing format.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current text works fine for me, thanks!

Great!

To be honest, I'm actually surprised that the trailing \0 works fine, since I recall having issues with it, hence the extra code to remove it in Rust & Go SDKs... But I was also under the impression that the serialization format came from CEL and wasn't our own invention, so my memory is clearly a little hazy around those details.

Yeah, I'm not sure--maybe something changed over time? FWIW my reading of the current logic in Context::getProperty() is that (currently) the trailing '\0' would never even be seen by any of the CEL-evaluation functions.

I'll draft a PR for the C++ SDK to stop including it, for consistency with the other SDKs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binary format didn't come from CEL. The constraint was that "." wasn't good enough since segments can contain ".". But you should feel free to revise for vNext with a more standard list packing format.

Ah, TIL! I had wondered about that, interesting to know the history.

Copy link
Member

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also add this to v0.2.0 and vNEXT (since any changes from v0.2.1 should be done via PRs and not by using a stale copy of the spec).

@mpwarres
Copy link
Contributor Author

I think we should also add this to v0.2.0 and vNEXT (since any changes from v0.2.1 should be done via PRs and not by using a stale copy of the spec).

Right--done.

Signed-off-by: Michael Warres <mpw@google.com>
But also stipulate that host implementations must tolerate a terminating null
char if present.

Signed-off-by: Michael Warres <mpw@google.com>
Signed-off-by: Michael Warres <mpw@google.com>
@mpwarres mpwarres force-pushed the v0.2.1-getproperty-path branch from 772b5f3 to f9667d1 Compare October 25, 2025 18:40
@mpwarres
Copy link
Contributor Author

@PiotrSikora PTAL again--thanks!

Copy link
Member

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Please capitalize the commit message summary & add trailing dot before merging.

@mpwarres mpwarres changed the title document how proxy_{get,set}_property expects paths to be serialized Document how proxy_{get,set}_property expects paths to be serialized. Oct 30, 2025
@mpwarres
Copy link
Contributor Author

Thanks! Done.

@mpwarres mpwarres merged commit ab70b9f into proxy-wasm:main Oct 30, 2025
2 checks passed
@mpwarres mpwarres deleted the v0.2.1-getproperty-path branch October 30, 2025 12:58
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.

3 participants