Escape ';' in N and ADR structured component values - #40
Open
gaoflow wants to merge 1 commit into
Open
Conversation
A literal ';' inside a structured-value component (N, ADR) was neither
escaped on encoding nor recognised as escaped on decoding, so it was
emitted as a raw component separator and corrupted the round trip:
c.SetName(&Name{FamilyName: "a;b", GivenName: "c"})
serialised to "N:a;b;c;;;" and parsed back with FamilyName "a" and the
rest of the value shifted into the following components.
RFC 6350 section 3.4 requires a literal ';' in a component to be escaped
as '\;'; only an unescaped ';' separates components. The existing escaper
handled '\\', '\n' and '\,' but never the sibling '\;'.
Escape and unescape structured values per component (backslash, newline,
comma and semicolon) and join/split on the unescaped ';'. Because a
component is now escaped as a unit, the general value escaper must not run
again over N and ADR, so the encoder and decoder leave those values to the
structured path. Parameter values are untouched (they are not structured).
The comma and backslash escaping already in place is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
A literal
;inside a structured-value component (N,ADR) is silently corrupted on a round trip through the library's own API:FamilyNamecomes back as"a"and"b"leaks intoGivenName. The encoder writes the literal;unescaped, and on decode it is read (correctly, per spec) as a component separator.Root cause
RFC 6350 section 3.4 defines a component escape set of
\\,\,,\;and\n; a;separates components only when unescaped.Name.field()/Address.field()join components with a raw;andnewName/newAddresssplit on a raw;, while the value escaper handled\\,\nand\,but never the sibling\;. So a literal;in a component has no escaped representation and round-trips as a separator.\and,are handled and round-trip fine —;is the missing case.Fix
Escape and unescape structured values per component (backslash, newline, comma and semicolon) and join/split on the unescaped
;. A literal;now serialises as\;:Because a component is escaped as a unit, the general value escaper must not run a second time over
N/ADR, so the encoder and decoder leave those to the structured path. One consequence worth calling out: the rawField.Valueof anN/ADRfield is now the escaped structured value (e.g.a\;b;c;;;); the components are obtained throughName()/Address()as before. Parameter values are deliberately untouched — they are quoted, not backslash-escaped, and are not structured values.Tests
structured_test.gocovers round-trips of;,,,\,\n, a backslash at a component end and a literal\;, for bothNandADR, asserts the encoded form (N:a\;b;c;;;), and asserts a;in a parameter is not structurally escaped. Full suite passes;gofmtandgo vetclean.Related but not addressed here:
ORGandCLIENTPIDMAPare also;-separated but have no typed accessors, andCATEGORIEShas the same separator-vs-literal question for,; happy to follow up if you'd like those in scope.