Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix escaping the backslash character in text marshaling #546

Merged
merged 3 commits into from
Oct 4, 2023

Conversation

fcelda
Copy link
Contributor

@fcelda fcelda commented Oct 3, 2023

When marshaling structures into text representation, capnp-go doesn't escape the backslash characters.

See the following reproducer:

using Go = import "/go.capnp";
@0xd2f8840130e47262;
$Go.package("main");
$Go.import("bug");

struct Bug {
  data @0 :Data;
package main

import (
	"fmt"

	"capnproto.org/go/capnp/v3"
	"capnproto.org/go/capnp/v3/schemas"
)

func main() {
	arena := capnp.SingleSegment(nil)
	_, seg, _ := capnp.NewMessage(arena)
	bug, _ := NewBug(seg)

	bug.SetData([]byte{92, 0})

	RegisterSchema(schemas.DefaultRegistry)
	fmt.Println(bug) // prints (data = "\\x00") instead of (data = "\\\x00")
}

I'm attaching a fix for the bug and extended unit tests.

@@ -33,11 +28,13 @@ func Append(buf []byte, s []byte) []byte {
case '\\':
buf = append(buf, '\\', '\\')
default:
buf = append(buf, '\\', 'x', hexDigit(b/16), hexDigit(b%16))
if needsEscape(b) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for submitting a pull request! I'd much rather see needsEscape() altered to detect backslash, double quote and single quote, preferring to keep both the switch and needsEscape() in sync.

Copy link
Contributor Author

@fcelda fcelda Oct 4, 2023

Choose a reason for hiding this comment

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

Thank you for the review, @davidhubbard. I returned to the previous version of the code and just updated needsEscape to handle the missing characters. I don't find it super readable but that's probably just a preference. Let me know if this is what you imagined.

As a side note, I don't know what kind of a quoted string is this expected to produce. This will produce a string literal that is valid in Go. However I looked at quoted string parsing in capnp and the quoting there is incompatible. For instance, \' is not a valid escape sequence in capnp.

I don't mind too much, I just want to get the backslash fixed because that is a regression from zombiezen.com/go/capnproto2.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks! Yes, this is what I was hoping for. I understand what you mean about reading the code - it makes sense to me, but I'm still happy for the detailed feedback.

For your question about quoted string parsing in capnp I think what @lthibault said on matrix sums it up: "Do you guys have any thoughts about #546? My understanding of that feature was that it was intended to print data to the screen (a la Println), not to serialize."

In short, I believe everyone is in favor of this change because:

  • It fixes backslash quoting (a regression from https://pkg.go.dev/zombiezen.com/go/capnproto2)
  • We're always grateful for pull requests, and this one is well written
  • It fixes the underlying issue that needsEscape() was not in sync with Append()

And I note the caveats we've unconvered:

  • This wasn't intended to be fed into capnp string parsing, I think it was just for printing to the screen. Specifically \' is not a valid escape sequence in capnp.
  • This code could use some love along the lines of becoming more readable (or maybe just some comments?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for detailed comments and merging.

@davidhubbard davidhubbard merged commit 66b5b8e into capnproto:main Oct 4, 2023
0 of 4 checks passed
@fcelda
Copy link
Contributor Author

fcelda commented Oct 5, 2023

Thank you, @davidhubbard. Please, would it be possible to tag a new release with these changes included?

@lthibault
Copy link
Collaborator

@fcelda There are some regressions on the tip of main, so I'm not quite comfortable tagging a new release. However, I think you can run go get capnproto.org/go/capnp/v3@66b5b8e003bad68348fa7619a03d99afc729eb5f if you want to pin to this version. The regressions have to do with pipelined RPC calls, so if you're not using those, you should be fine.

@fcelda
Copy link
Contributor Author

fcelda commented Oct 5, 2023

That's what I did. Understood. Thank you!

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